Запрос GET с заголовком Content-Type и Accept с JAX-RS Jersey 2.2
Я пытаюсь получить доступ к веб-сервису открытых данных, который дает мне информацию о трафике. Документация говорит, что запросы должны быть GET
и должны содержать Accept: application/json
и Content-Type: application/json
. Я не понимаю, зачем им нужен Content-Type
, но нормально:
Я попытался получить данные только с заголовком Accept:
, но я всегда получаю 415 Unsupported Media Type
. Теперь я в настоящее время пытаюсь это сделать (но я не уверен, правильно ли настроил оба заголовка):
String entity = ClientBuilder.newClient().target(liveDataURI)
.path(liveDataPath)
.request(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.get(String.class);
Как вы видите, я использую Jersey 2.2, и я все еще получаю 415 Unsupported Media Type
.
ИЗМЕНИТЬ
Итак, я получил его на работу, но я не понимаю, почему. Разве не accept(MediaType.APPLICATION_JSON)
и header("Content-type","application/json")
то же самое?
String responseEntity = ClientBuilder.newClient()
.target(liveDataURI)
.path(liveDataPath)
.request(MediaType.APPLICATION_JSON)
.header("Content-type", "application/json")
.get(String.class);
Ответы
Ответ 1
Заголовок Accept
сообщает серверу, что ваш клиент хочет в ответе. Заголовок Content-Type
сообщает серверу, что клиент отправляет в запросе. Таким образом, они не совпадают.
Если сервер принимает только application/json
, вы должны отправить запрос, который указывает содержимое запроса:
Content-Type: application/json
Вот почему ваш отредактированный код работает.
Edit
В вашем первом коде вы используете WebTarget.request(MediaType... acceptedResponseTypes)
. Параметры этого метода
определить принятые типы сообщений ответа.
Вы используете Innvocation.Builder.accept(MediaType... mediaTypes)
в результате этого вызова метода. Но accept()
не добавляет нового заголовка, в вашем первом коде нет необходимости.
Вы никогда не укажете тип содержимого вашего запроса. Поскольку сервер ожидает заголовок Content-Type
, он отвечает 415
.
Ответ 2
Не accept(MediaType.APPLICATION_JSON)
и header("Content-type","application/json")
то же самое?
Нет, они разные.
Вот как они связаны:
Client Server
(header) (class/method annotation)
====================================================
Accept <---> @Produces
Content-Type <---> @Consumes
Сервер потребляет то, что он получает от клиента в теле (его формат указан в Content-Type
), и он производит то, что клиент принимает (его формат указан в Accept
).
Пример:
- клиент отправляет следующие заголовки:
-
Content-Type
= text/xml
(он отправляет XML в тело)
-
Accept
= application/json
(он ожидает получить JSON в качестве ответа)
- сервер должен иметь по крайней мере следующие аннотации для соответствующего метода (аннотации берутся из уровня класса, если они явно не указаны для этого метода):
-
@Consumes(MediaType.TEXT_XML)
(он получает XML от клиента)
-
@Produces(MediaType.APPLICATION_JSON)
(он отправляет JSON клиенту)
набл
-
Сервер может быть более гибким, будучи настроен на получение/создание нескольких возможных форматов.
Например: клиент может отправлять XML, в то время как другой клиент может отправить JSON на тот же метод, если он имеет следующую аннотацию: @Consumes({ MediaType.APPLICATION_JSON, MediaType.TEXT_XML })
.
-
Значения MediaType
представляют собой просто константы String
:
public final static String APPLICATION_JSON = "application/json";
public final static String TEXT_XML = "text/xml";
Ответ 3
Вы можете использовать ContainerResponseFilter
, чтобы установить заголовок Accept по умолчанию, если он не указан во входном запросе.
@Provider
public class EntityResponseFilter implements ContainerResponseFilter {
private MediaType getExternalMediaType(){
MediaType mediaType = new MediaType("application", "vnd.xxx.resource+json")
return mediaType;
}
@Override
public void filter( ContainerRequestContext reqc , ContainerResponseContext resc ) throws IOException {
MediaType mediaType = getExternalMediaType();
List<MediaType> mediaTypes = reqc.getAcceptableMediaTypes();
if( mediaTypes.contains(mediaType) ) {
resc.setEntity( resc.getEntity(), new Annotation[0], mediaType );
}
// ...
}
}