【问题标题】:JAX-WS client: UnsupportedMediaException for gzipped responseJAX-WS 客户端:gzip 响应的 UnsupportedMediaException
【发布时间】:2024-01-21 00:44:01
【问题描述】:

我编写了 JAX-WS(来自 Sun)客户端,它进行服务调用,期望服务器响应被压缩:

Map<String, List<String>> theHeaders = new HashMap<String, List<String>>();
theHeaders.put("Content-Encoding", Collections.singletonList("gzip"));
theHeaders.put("Accept", Collections.singletonList("application/x-gzip"));
theHeaders.put("Accept-Encoding", Collections.singletonList("gzip, deflate"));
theHeaders.put("Content-Type", Collections.singletonList("application/x-gzip"));
((BindingProvider) client).getRequestContext().put(MessageContext.HTTP_REQUEST_HEADERS, theHeaders);

根据 Fiddler 的说法,响应是 HTTP 200 (Ok),soap 响应是 gzip 压缩的。 不过,我收到以下错误:

com.sun.xml.ws.server.UnsupportedMediaException: Unsupported Content-Type: application/x-gzip Supported ones are: [application/soap+xml]
at com.sun.xml.ws.encoding.StreamSOAPCodec.decode(StreamSOAPCodec.java:322)
at com.sun.xml.ws.encoding.StreamSOAP12Codec.decode(StreamSOAP12Codec.java:107)
at com.sun.xml.ws.encoding.StreamSOAPCodec.decode(StreamSOAPCodec.java:156)
at com.sun.xml.ws.encoding.SOAPBindingCodec.decode(SOAPBindingCodec.java:312)
at com.sun.xml.ws.transport.http.client.HttpTransportPipe.createResponsePacket(HttpTransportPipe.java:295)

read 认为 JAX-WS 应该支持开箱即用的 gzip 压缩 web 服务响应,但它看起来不支持。尽管事实响应包含 Content-Type: application/x-gzip 标头,但它尝试使用适用于 application/soap+xml 的默认编解码器。

有没有办法让它使用另一个编解码器,用于 gzip?有这样的编解码器吗?

【问题讨论】:

    标签: java jax-ws gzip


    【解决方案1】:

    您提到的链接告诉它在发送响应时支持 gzip

    Content-encoding: gzip
    

    标头,除了标准的内容类型标头。如果服务器以Content-Type: application/x-gzip 响应,则它是一个不同的标头,即使支持gzip 本身,它似乎也不支持。我认为你不应该设置这个:

    theHeaders.put("Accept", Collections.singletonList("application/x-gzip"));
    

    相反,只需设置接受编码,包括 gzip:

    theHeaders.put("Accept", Collections.singletonList("application/soap+xml"));
    theHeaders.put("Content-Type", Collections.singletonList("application/soap+xml"));
    theHeaders.put("Accept-Encoding", Collections.singletonList("gzip"));
    theHeaders.put("Content-Encoding", Collections.singletonList("gzip"));
    

    【讨论】:

    • 所以,为了确保我没有弄错:服务器端应该 exactly 响应 gzip 内容编码标头,而不是 application/x-gzip让它在客户端被视为 gzip?
    • @MikhailBerastau application/gzip 是内容类型标头值,gzip 是应用程序编码标头值。因此,对于所有实现,服务器应该使用内容编码 gzip 进行响应才能使其正常工作。对于某些 Web 服务客户端库,可以使用 also 应用程序/gzip 内容类型 - 对于某些人来说不是。根据错误消息,我猜测在这种情况下不是。
    • 查看了 jaxws-rt 的来源,比较如下: if (contentEncoding != null && contentEncoding.contains("gzip")) { in = new GZIPInputStream(in);所以任何在内容编码中提到 gzip 都是可以接受的; re content-type - 我认为你是对的,它应该是 application/soap+xml。
    • 在我的情况下,问题是 contentEncoding 变量为空(通过调试检查),即使在响应中正确设置了 Content-Encoding。
    • 是的,任何提及都应该是可以接受的。我把它当作只有一个,因为你指出 gzip 是你要使用的那个。