Jax-ws изменяет Content-type на Content-Type, потому что сервер гиперчувствителен

Мне нужно подключиться к плохо реализованному серверу, который понимает только Content-Type (capital-T), а не Content-Type. Как я могу попросить моего клиента JAX-WS отправить Content-Type?

Я пробовал:

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

Но headers - null. Что я делаю неправильно?

Ответ 1

Мне нужно подключиться к плохо реализованному серверу, который понимает только Content-Type (capital-T), а не Content-type. Как я могу попросить моего jax-ws-клиента отправить Content-Type?

Я выкопал этот вопрос немного больше, и, к сожалению, я боюсь, что ответ таков: вы не можете. Позвольте мне поделиться своими выводами.

Во-первых, код, который вы найдете в https://jax-ws.dev.java.net/guide/HTTP_headers.html , не дает вам доступ к HTTP заголовки будущего HTTP-запроса (который не был создан на данный момент), он позволяет установить дополнительные HTTP-заголовки для создания запроса (который будет добавлен в HTTP-запрос позже).

Итак, не ожидайте, что следующий код не вернет null, если вы не put ничего раньше (и на самом деле вы получите только то, что вы put):

((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

Вы заметили разницу: только первый char заголовка X-Client-Version хранится в верхней части, остальные опускаются!

И действительно, если вы проверите класс 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) {
     ...
 }

Итак, в то время как класс 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

Вы можете изменить заголовки HTTP из RequestContext. Если у вас есть доступ к объекту порта, вы можете отправить его в javax.xml.ws.BindingProvider, который предоставит вам доступ к RequestContext.

Вы также можете удалить непринятый заголовок "Content-type".

На этой странице показано, как сделать это немного подробнее: https://jax-ws.dev.java.net/guide/HTTP_headers.html

Сообщите мне, если вам нужно больше образцов кода, или если вы вставляете часть своего кода, я могу показать вам, как его изменить.