Конфликты согласования содержимого HTTP в JAX-RS / Jersey? - PullRequest
6 голосов
/ 09 марта 2011

Мне нравится автоматическое согласование содержимого HTTP JAX-RS (в частности, Джерси), т. Е. Его способность направлять мои ресурсы по заголовкам «Accept» и / или «Content-Type».Но я обнаружил, что иногда это не дает мне достаточного контроля, когда возникает конфликт.

Например, рассмотрим следующие конечные точки:

@Path("/order")
public class OrderController {

    @GET
    @Path("{orderID: \\d+}")
    @Produces("text/html")
    public View getOrderView(@PathParam("orderID") long id) {
        Order order = this.getOrderData(id);
        return new OrderView(order);
    }

    @GET
    @Path("{orderID: \\d+}")
    @Produces({"application/json", "application/xml"})
    public Order getOrderData(@PathParam("orderID") long id) {
        return new OrderService.findOrder(id);
    }
}

Я получу разные результаты междуFirefox и Chrome.Firefox будет сопоставляться с конечной точкой HTML, в то время как Chrome будет запускать конечную точку XML, когда я перехожу к URL-адресу конечной точки.Разница между ними заключается в порядке перечисления типов MIME в их заголовках Accept.Chrome отправляет следующее:

User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_6; en-US) AppleWebKit/534.13 (KHTML, like Gecko) Chrome/9.0.597.107 Safari/534.13
Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5

В отличие от Firefox, он сначала отображает HTML:

User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

Кажется логичным, что он будет соответствовать первой записи, когда все будут взвешены одинаково.Но в моем случае я получаю результаты, отличные от тех, которые мне нужны, поэтому было бы неплохо определить лучший метод разрыва связей.

Мой вопрос: если не вставить информацию заголовка в этиметоды и выполнение обработки медиа-типов самостоятельно, есть ли способ «подправить вес», так сказать, в случае ничьей?Например, могу ли я сказать, что всегда бить XML с HTML?Мои клиенты RESTful очень четко говорят, какой тип они хотят вернуть, но браузеры общеизвестно неаккуратны с заголовками Accept.(Лично я думаю, что они должны весить HTML немного выше XML, поскольку это то, чего ожидают пользователи, но для этого уже немного поздно.)

В качестве альтернативы, могу ли я выполнить свое собственное согласование пользовательского контента только один раз в каком-то централизованном месте?Я не против написания этой логики вручную, но не в том случае, если это означает применение ее к каждому экземпляру моих ресурсов.Есть ли в JAX-RS концепция добавления фильтра в конвейер для настройки запросов перед их маршрутизацией?

Ответы [ 2 ]

10 голосов
/ 04 апреля 2011

В Джерси существует механизм, позволяющий переопределить относительную степень предпочтения из заголовка HTTP Accept.Просто добавьте параметр «qs» в аннотацию @Produces, который вы хотите иметь приоритет.В вашем случае: @Produces("text/html;qs=2") Обратите внимание, что значения http "q" варьируются от 0 до 1, а значения "qs" на Джерси должны быть> = 1 (по умолчанию 1).

(об этом я узнал этот источник , и я написал небольшую заметку для себя здесь )

1 голос
/ 10 марта 2011

Как на Джерси Руководство пользователя гласит:

Если оба одинаково приемлемы, тогда будет выбран первый, потому что это происходит первым.

Насколько я знаю, это оставляет вам две возможности / хаки:

  1. Добавьте расширение файла к вашему URI для переопределения заголовка Accept

  2. Напишите фильтр сервлетов, который перезаписывает заголовок Accept для эти пользовательские агенты

...