jax-ws 将内容类型更改为内容类型,因为服务器非常敏感

2022-09-04 20:01:35

我必须连接到一个实现不佳的服务器,该服务器只能理解(大写-T)而不是。如何要求我的 JAX-WS 客户机发送?Content-TypeContent-typeContent-Type

我试过了:

Map<String, List<String>> headers = (Map<String, List<String>>)
((BindingProvider)port).getRequestContext().get(MessageContext.HTTP_REQUEST_HEADERS);

但是.我做错了什么?headersnull


答案 1

我必须连接到一个实现不佳的服务器,该服务器仅了解内容类型(大写字母-T)而不是内容类型。如何要求我的 jax-ws 客户端发送内容类型?

我又挖了一点这个问题,可悲的是,恐怕答案是:你不能。让我分享我的发现。

首先,您将在 https://jax-ws.dev.java.net/guide/HTTP_headers.html 中找到的代码允许您访问未来HTTP请求的HTTP标头(此时尚未创建),它允许您设置其他HTTP标头以发出请求(稍后将添加到HTTP请求中)。

因此,如果您之前没有任何东西,请不要期望以下代码不会返回(实际上,您只会在那里获得您的内容):nullputput

((BindingProvider)port).getRequestContext().get(MessageContext.HTTP_REQUEST_HEADERS);

然后,我根据同一链接中提供的代码进行了一些测试:

AddNumbersImplService service = new AddNumbersImplService();
AddNumbersImpl port = service.getAddNumbersImplPort();

((BindingProvider)port).getRequestContext().put(MessageContext.HTTP_REQUEST_HEADERS,
    Collections.singletonMap("X-Client-Version",Collections.singletonList("1.0-RC")));

port.addNumbers(3, 5);

这是我在运行客户端代码时在HTTP请求中看到的:

POST /q2372336/addnumbers HTTP/1.1
Content-type: text/xml;charset="utf-8"
X-client-version: 1.0-RC
Soapaction: ""
Accept: text/xml, multipart/related, text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
User-Agent: JAX-WS RI 2.1.6 in JDK 6
Host: localhost:8080
Connection: keep-alive
Content-Length: 249

您是否注意到了区别:只有标题的第一个字符保持大写,其余部分降低!X-Client-Version

事实上,如果您检查用于表示HTTP请求(和响应)标头的类c.s.x.w.t.Headers,您将看到它在添加键时“规范化”了它们(在):normalize(String)

/* Normalize the key by converting to following form.
 * First char upper case, rest lower case.
 * key is presumed to be ASCII 
 */
 private String normalize (String key) {
     ...
 }

因此,虽然 c.s.x.w.t.h.c.HttpTransportPipe 类(我的理解是,这是创建 HTTP 请求的位置,也是将以前添加的标头添加到 HTTP 请求标头的位置)实际上将“Content-Type”添加为 c.s.x.w.t.Headers 实例中的键,但由于前面提到的实现细节,该键将被修改。

我可能是错的,但我不明白如何在不修补代码的情况下进行更改。奇怪的是,我不认为这种“规范化”的东西真的符合RFC的要求(虽然没有检查RFC对标头情况的看法)。我很惊讶。实际上,您应该提出一个问题

所以我在这里看到了三个选项(因为等待修复可能不是一个选项):

  • 自行修补代码并重新构建 JAX-WS RI(具有此方法的所有缺点)。
  • 为您的客户端尝试另一个 JAX-WS 实现,如 CFX。
  • 让请求通过某种自定义代理来动态修改标头。

答案 2

您可以从 RequestContext 修改 HTTP 标头。如果您有权访问端口对象,则可以将其强制转换为javax.xml.ws.BindingProvider,这将允许您访问RequestContext。

您可能还希望删除未被接受的“内容类型”标头。

本页更详细地显示了如何执行此操作:https://jax-ws.dev.java.net/guide/HTTP_headers.html

如果您需要更多代码示例,或者如果您粘贴了一些代码,请告诉我,我可以向您展示如何修改它。