问题描述
我必须连接到一个执行不佳的服务器,该服务器只能理解 Content-Type
(capital-T) 而不是 Content-type
.如何让我的 JAX-WS 客户端发送 Content-Type
?
我试过了:
地图<字符串,列表<字符串>>标头=(地图<字符串,列表<字符串>>)((BindingProvider)port).getRequestContext().get(MessageContext.HTTP_REQUEST_HEADERS);
但是 headers
是 null
.我做错了什么?
我必须连接到一个执行不佳的服务器,该服务器只理解 Content-Type(capital-T) 而不是 Content-type.如何让我的 jax-ws 客户端发送 Content-Type?
我对这个问题进行了更多研究,但遗憾的是,恐怕答案是:你不能.让我分享一下我的发现.
首先,您将在 https://jax- 中找到代码ws.dev.java.net/guide/HTTP_headers.html 不允许您访问未来 HTTP 请求的 HTTP 标头(此时尚未创建),它允许您设置用于发出请求的附加 HTTP 标头(稍后将添加到 HTTP 请求中).
所以,如果你之前没有 put
任何东西,不要期望下面的代码不会返回 null
(实际上,你只会得到你 <代码>把放在那里):
((BindingProvider)port).getRequestContext().get(MessageContext.HTTP_REQUEST_HEADERS);
然后,我根据同一个链接中提供的代码做了一个小测试:
AddNumbersImplService 服务 = new AddNumbersImplService();AddNumbersImpl 端口 = 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 请求中看到的内容:
<上一页>发布/q2372336/addnumbers HTTP/1.1内容类型:text/xml;charset="utf-8"X 客户端版本:1.0-RC皂化:"接受:text/xml、multipart/related、text/html、image/gif、image/jpeg、*;q=.2, */*;q=.2用户代理:JDK 6 中的 JAX-WS RI 2.1.6主机:本地主机:8080连接:保持活动内容长度:249你注意到区别了吗:只有 X-Client-Version
标头的第一个字符保持大写,其余的被降低!
确实,如果您检查类 csxwtHeaders
用于表示HTTP请求(和响应)标头,您会看到它在添加键时规范化"键(在 normalize(String)
中):
/* 通过转换为以下形式来规范化密钥.* 第一个字符大写,其余小写.* key 假定为 ASCII*/私有字符串规范化(字符串键){...}
所以,虽然 csxwthcHttpTransportPipe
类(我的理解是这里是创建HTTP请求的地方,这也是之前添加的地方标头将添加到 HTTP 请求标头中)实际上添加 "Content-Type"
作为 csxwtHeaders
实例,因为前面提到的实现细节,key 会被修改.
我可能是错的,但我不明白如何在不修补代码的情况下更改它.奇怪的是,我不认为这种规范化"的东西真的符合 RFC(尽管没有检查 RFC 关于标头大小写的内容).我很惊讶.实际上,您应该提出问题.
所以我在这里看到了三个选项(因为等待修复可能不是一个选项):
- 自己修补代码并重建 JAX-WS RI(具有这种方法的所有缺点).
- 为您的客户尝试另一种 JAX-WS 实现,例如 CFX.
- 让请求通过某种自定义代理来动态修改标头.
I have to connect to a poorly implemented server that only understands Content-Type
(capital-T) and not Content-type
. How can I ask my JAX-WS client to send Content-Type
?
I've tried:
Map<String, List<String>> headers = (Map<String, List<String>>)
((BindingProvider)port).getRequestContext().get(MessageContext.HTTP_REQUEST_HEADERS);
But headers
is null
. What am I doing wrong?
I have to connect to a poorly implemented server that only understands Content-Type(capital-T) and not Content-type. How can I ask my jax-ws client to send Content-Type?
I've dug this question a bit more and, sadly, I'm afraid the answer is: you can't. Let me share my findings.
First, the code that you'll find in https://jax-ws.dev.java.net/guide/HTTP_headers.html does not give you access to the HTTP headers of the future HTTP request (that hasn't been created at this point), it allows you to set additional HTTP headers for making a request (that will be added to the HTTP request later).
So, don't expect the following code to not return null
if you don't put
anything before (and actually, you'll only get what you put
in there):
((BindingProvider)port).getRequestContext().get(MessageContext.HTTP_REQUEST_HEADERS);
Then, I did a little test based on the code provided in the same link:
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);
And this is what I see in the HTTP request when running the client code:
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
Do you notice the difference: only the first char of the X-Client-Version
header is kept upper cased, the rest is lowered!
And indeed, if you check the class c.s.x.w.t.Headers
that is used to represent HTTP request (and response) headers, you'll see that it "normalizes" keys when they are added (in 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) {
...
}
So, while the c.s.x.w.t.h.c.HttpTransportPipe
class (my understanding is that this is where the HTTP request is created, this is also where previously added headers will be added to the HTTP request headers) actually adds "Content-Type"
as key in a c.s.x.w.t.Headers
instance, the key will be modified because of the previously mentioned implementation detail.
I may be wrong but I don't see how this could be changed without patching the code. And the odd part is that I don't think that this "normalizing" stuff is really RFCs compliant (didn't check what RFCs say about headers case though). I'm surprised. Actually, you should raise an issue.
So I see three options here (since waiting for a fix might not be an option):
- Patch the code yourself and rebuild JAX-WS RI (with all the drawbacks of this approach).
- Try another JAX-WS implementation like CFX for your client.
- Let the request go through some kind of custom proxy to modify the header on the fly.
这篇关于jax-ws 将 Content-type 更改为 Content-Type 因为服务器是超敏感的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!