Лучшая практика REST для длинных URI - PullRequest
19 голосов
/ 15 января 2010

У меня есть службы REST, которые должны получать действительно длинные запросы через GET. Например, я хочу запросить услугу с много географических координат, чтобы узнать что-то обо всех этих координатах.

1) Моей первой мыслью было использование длинных URI и увеличение максимальной длины URI контейнера сервлета.

Это будет выглядеть так:

GET http://some.test/myresource?query={really big JSON object}

Но кажется, что URI длиннее 2 КБ ненадежны из-за старых прокси-серверов (верно?).

2) Мой обходной путь - сначала создать временный ресурс через POST и использовать URI этого ресурса в качестве параметра в реальном запросе GET. Это будет выглядеть так:

POST http://some.test/temp
Request Body: {really big JSON object}

201 Created Location: http://some.test/temp/12309871

GET http://some.test/myresource?query=http://some.test/temp/12309871

3) Использовать тело запроса GET. Я прочитал ответы на вопрос, является ли хорошей идеей использовать тело запроса GET для запроса, и консенсус: нет. Даже Рой Филдинг говорит, что это плохая идея .

4) Другим подходом может быть интерпретация POST как «ресурса результата создания запроса» и удаление этого ресурса после запроса. Но я считаю, что это не RESTful и плохая идея.

Есть ли лучший способ обрабатывать большие запросы с помощью запросов GET?

Ответы [ 6 ]

4 голосов
/ 20 июня 2016

Используйте PUT.

Почему? По следующим причинам:

  • То, что глагол PUT 'может обновлять' ресурс, не означает, что он будет или должен изменять основное состояние ресурса.
  • Никакой новый идентификатор ресурса (url) не должен создаваться стороной API PUT. Да, технически PUT с указанным клиентом идентификатором возможен, но в этом случае вы используете существующий ресурс.
  • PUT похоже на GET в том смысле, что оно должно быть идемпотентным, то есть результаты запроса всегда будут одинаковыми, независимо от того, как часто вы его вызываете, и у него нет побочных эффектов.

PUT означает, что вы помещаете данные ресурса в существующий ресурс. С точки зрения статьи или поста в мире постов документов / блогов, это было бы похоже на загрузку новой редакции какого-либо документа в существующий URL ресурса. Если вы загружаете ту же ревизию на тот же URL, ничто не должно измениться в ресурсе, который вы получите обратно.

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

Более пуристическим методом использования глагола GET для запроса может быть:

  • Создание конечной точки для типа ресурса запроса
  • POST набор JSON деталей запроса к конечной точке ресурса запроса и получение идентификатора ресурса запроса (скажем, он возвращает идентификатор запроса 123)
  • Подать в запрос на получение идентификатор запроса http://some.test/myresource?query_id=123
  • Удалить ресурс запроса 123

Я вижу, что чистый метод намного более затратен, чем использование PUT с данными ресурса запроса в теле.

3 голосов
/ 15 января 2010

Я думал, что весь смысл REST заключается в том, чтобы работать над «документами» (или чем-то похожим). URI-часть запроса предназначена для идентификации уникально ресурса, с которым нужно работать. В отличие от этого, основная часть документа предназначена для части содержимого.

Следовательно, используйте часть «body» запроса.

Также обратите внимание, что семантика запроса "GET" не должна использоваться для документов "PUTTING" или "POSTING". .

В любом случае, как вы указали, часть URI ограничена (я уверен, что на то есть веские причины).


Если вас интересует кэширование, то для этого помогает использование полей ETag / Last-Modified (в сочетании с «условным GET»).

2 голосов
/ 15 января 2010

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

POST /QueryMaker
Body: Big Json representation of parameters

303: See Other
Location: http://example.org/TemporaryQueries/123213
2 голосов
/ 15 января 2010

Если вы используете запрос GET для отправки больших объектов, вы неправильно используете REST.

  • GET следует использовать для получения ресурсы (через какой-то уникальный идентификатор)
  • POST должен использоваться для создание ресурсов (с содержанием в теле)
  • PUT следует использовать для обновление ресурса (с содержимое в теле)
  • УДАЛИТЬ следует использовать для удаления ресурса

Если вы будете следовать этим рекомендациям, вам никогда не понадобятся слишком длинные URI.

Некоторые рекомендации по REST для наилучшей практики приведены здесь: http://www.xml.com/pub/a/2004/08/11/rest.html

0 голосов
/ 15 апреля 2010

Самым большим ограничением длины URL в открытом Интернете является IE, который ограничивает их до 2083 символов .

Некоторые прокси (например, все, кроме самых последних версий Squid) будут ограничивать их до 4 КБ, хотя медленно движется к 8 К

Ваш обходной путь № 2 - хороший подход, в зависимости от вашего варианта использования.

Отправка тел в GET может быть разрешена некоторыми реализациями и запрещена другими, так что это плохая идея для функциональной совместимости, а также для теоретических соображений. Самое главное, как кеш узнает, что использовать в качестве ключа?

0 голосов
/ 15 января 2010

Разве вы не можете просто отправить большие данные JSON с телом запроса GET вместо создания временного ресурса?

Хотя это не на 100% кошерно, я обнаружил, что оно прекрасно работает с firefox, IE и IMO, строка запроса не элегантна и обычно предоставляет детали реализации, которые не принадлежат URI. Просто добавьте параметр строки запроса кэш-буфера, если вам нужны свежие данные, поскольку сервер будет игнорировать данные при определении, может ли он вернуть кэшированный ответ.

См. здесь для обсуждения плюсов и минусов заполнения данных в теле запроса GET.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...