java jax-ws 将 Content-type 更改为 Content-Type,因为服务器非常敏感
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2372336/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
jax-ws change Content-type to Content-Type because server is hyper sensitive
提问by Esben Skov Pedersen
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?
我必须连接到一个只理解Content-Type(capital-T) 而不是Content-type. 我如何要求我的 JAX-WS 客户端发送Content-Type?
I've tried:
我试过了:
Map<String, List<String>> headers = (Map<String, List<String>>)
((BindingProvider)port).getRequestContext().get(MessageContext.HTTP_REQUEST_HEADERS);
But headersis null. What am I doing wrong?
但是headers是null。我究竟做错了什么?
回答by Pascal Thivent
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?
我必须连接到一个只理解 Content-Type(capital-T) 而不是 Content-type 的实现不佳的服务器。如何让我的 jax-ws 客户端发送 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.htmldoes notgive 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).
首先,您将在https://jax-ws.dev.java.net/guide/HTTP_headers.html中找到的代码不会让您访问未来 HTTP 请求的 HTTP 标头(尚未创建)此时),它允许您设置额外的 HTTP 标头以发出请求(稍后将添加到 HTTP 请求中)。
So, don't expect the following code to not return nullif you don't putanything before (and actually, you'll only get what you putin there):
所以,null如果你put之前什么都不做,不要指望下面的代码不会返回(实际上,你只会得到你put在那里的东西):
((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:
这就是我在运行客户端代码时在 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
Do you notice the difference: only the first char of the X-Client-Versionheader is kept upper cased, the rest is lowered!
您是否注意到不同之处:只有X-Client-Version标题的第一个字符保持大写,其余字符降低!
And indeed, if you check the class c.s.x.w.t.Headersthat is used to represent HTTP request (and response) headers, you'll see that it "normalizes" keys when they are added (in normalize(String)):
事实上,如果您检查c.s.x.w.t.Headers用于表示 HTTP 请求(和响应)标头的类,您会看到它在添加键时“规范化”了键(在 中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.HttpTransportPipeclass (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.Headersinstance, the key will be modified because of the previously mentioned implementation detail.
因此,虽然c.s.x.w.t.h.c.HttpTransportPipe类(我的理解是这是创建 HTTP 请求的地方,这也是先前添加的标头将添加到 HTTP 请求标头的地方)实际上"Content-Type"在c.s.x.w.t.Headers实例中添加为键,但键将被修改,因为前面提到的实现细节。
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.
我可能是错的,但我不知道如何在不修补代码的情况下改变它。奇怪的是,我不认为这种“规范化”的东西真的符合 RFC(虽然没有检查 RFC 对标头案例的说法)。我很惊讶。其实,你应该提一个问题。
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 RI(具有这种方法的所有缺点)。
- 为您的客户端尝试另一个 JAX-WS 实现,如 CFX。
- 让请求通过某种自定义代理来动态修改标头。
回答by Mark Pope
You can modify the HTTP headers from the RequestContext. If you have access to the port object you can cast it to a javax.xml.ws.BindingProvider, which will give you access to the RequestContext.
您可以从 RequestContext 修改 HTTP 标头。如果您有权访问端口对象,则可以将其转换为 javax.xml.ws.BindingProvider,这将使您能够访问 RequestContext。
You might also want to remove the unaccepted "Content-type" header.
您可能还想删除不被接受的“Content-type”标头。
This page shows how to do it in a bit more detail: https://jax-ws.dev.java.net/guide/HTTP_headers.html
此页面更详细地展示了如何执行此操作:https: //jax-ws.dev.java.net/guide/HTTP_headers.html
Let me know if you need more code samples, or if you paste some of your code I can show you how to modify it.
如果您需要更多代码示例,或者您粘贴一些代码,请告诉我,我可以向您展示如何修改它。

