Подтвердить что ты не робот

Запрос 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);
4b9b3361

Ответ 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 );
        }
        // ...
    }
}