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

Лучшая практика REST для перекрытия URI

У меня есть службы 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?

4b9b3361

Ответ 1

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

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

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

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


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

Ответ 2

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

  • GET следует использовать для извлечения ресурсов (через какой-то уникальный идентификатор)
  • POST следует использовать для создание ресурсов (с содержанием в теле)
  • PUT следует использовать для обновление ресурса (с помощью содержимое в теле)
  • DELETE следует использовать для удаления ресурса

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

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

Ответ 3

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

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

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

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

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

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

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

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

Ответ 4

Ниже приведен небольшой вариант вашего второго варианта. Создайте себе процессорный ресурс под названием QueryMaker. Отправьте свои параметры на него и позвольте перенаправить вас на ресурс временных запросов, который вернет ваши результаты.

POST /QueryMaker
Body: Big Json representation of parameters

303: See Other
Location: http://example.org/TemporaryQueries/123213

Ответ 5

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

Некоторые прокси (например, все, кроме самых последних версий Squid) ограничивают их примерно до 4k, хотя это медленно двигается к 8k.

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

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

Ответ 6

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

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

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