Как я могу справиться с ограничениями длины строки запроса HTTP GET и все еще хотеть быть RESTful? - PullRequest
73 голосов
/ 17 ноября 2010

Как указано в http://www.boutell.com/newfaq/misc/urllength.html, Строка HTTP-запроса имеет ограниченную длину. Он может быть ограничен клиентом (Firefox, IE, ...), сервером (Apache, IIS, ...) или сетевым оборудованием (аппликативный брандмауэр, ...).

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

У нас так много полей, что длина строки запроса составляет 1100 байт, и у нас есть брандмауэр, который отбрасывает запросы HTTP GET с более чем 1024 байтами. Наш системный администратор рекомендует использовать взамен POST, поэтому ограничений не будет.

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

Но есть ли недостаток в дизайне сервисов RESTful? Если у нас ограниченная длина в GET-запросе, как я могу отправить большие объекты в веб-службу RESTful? Например, если у меня есть программа, которая выполняет вычисления на основе файла, и я хочу предоставить RESTful веб-сервис, подобный этому: http://compute.com?content=<base64 file>. Это не сработает, потому что длина строки запроса не ограничена.

Я немного озадачен ...

Ответы [ 7 ]

59 голосов
/ 17 ноября 2010

HTTP-спецификация на самом деле советует использовать POST при отправке данных на ресурс для вычисления.

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

После некоторого промежутка времени вы можете удалить токены результатов поиска.

Пример

POST /search
query=something&category=c1&category=c2&...

201 Created
Location: /search/01543164876

тогда

GET /search/01543164876

200 Ok
... your results here...

Таким образом, браузеры и прокси могут по-прежнему кэшировать результаты поиска, но вы отправляете параметры запроса с помощью POST.

РЕДАКТИРОВАТЬ

Для пояснения, 01543164876 здесь представляет уникальный идентификатор ресурса, представляющего ваш поиск. Эти 2 запроса в основном означают: создать новый поисковый объект с этими критериями, а затем получить результаты, связанные с созданным поисковым объектом.

Этот идентификатор может быть уникальным идентификатором, сгенерированным для каждого нового запроса. Это будет означать, что ваш сервер будет пропускать «поисковые» объекты, и вам придется регулярно очищать их с помощью стратегии кэширования.

Или это может быть хэш всех критериев поиска, фактически представляющих запрос, заданный пользователем. Это позволяет повторно использовать идентификаторы, поскольку при повторном поиске будет возвращаться существующий идентификатор, который может (или не может) быть уже кэширован.

49 голосов
/ 17 ноября 2010

На основании вашего описания, ИМХО, вы должны использовать POST. POST предназначен для размещения данных на сервере и, в некоторых случаях, для получения ответа. В вашем случае вы выполняете поиск (отправляете запрос на сервер) и получаете результат этого поиска (извлекаете результат запроса).

Определение GET говорит о том, что он должен использоваться для извлечения уже существующего ресурса. По определению POST - это создание нового ресурса. Это именно то, что вы делаете: создаете ресурс на сервере и извлекаете его! Даже если вы не сохраните результат поиска, вы создали объект на сервере и получили его. Как ранее сказал PeterMmm, вы можете сделать это с помощью POST (создать и сохранить результат запроса), а затем использовать GET для повторного получения запроса, но более практичным является только POST и получение результата.

Надеюсь, это поможет! :)

5 голосов
/ 10 июня 2011

Путаница вокруг GET - это ограничение браузера.Если вы создаете интерфейс RESTful для приложения A2A или P2P, тогда нет никаких ограничений на длину вашего GET.

Теперь, если вам захочется использовать браузер для просмотра вашего интерфейса RESTful (он же во время разработки / отладки), тогда вы столкнетесь с этим пределом, но для этого есть инструменты.

5 голосов
/ 17 ноября 2010

REST - это способ ведения дел, а не протокол.Даже если вам не нравится POST, когда это действительно GET, он будет работать.

Если вы будете / должны придерживаться «стандартного» определения GET, POST и т. Д., Чем, возможно, следует рассматривать POST как запрос,этот запрос будет сохранен на сервере с идентификатором запроса, а запрос будет позже с GET по идентификатору.

3 голосов
/ 17 ноября 2010

Что касается вашего примера: http://compute.com?content={base64file}, я бы использовал POST, потому что вы загружаете «что-то» для вычисления.Для меня это «что-то» больше похоже на ресурс как простой параметр.

В отличие от этого в обычном поиске я бы начал придерживаться GET и параметров.Вы делаете так, что api-клиентам намного проще тестировать и играть с вашим API.Сделайте доступ только для чтения (который в большинстве случаев составляет большую часть трафика) настолько простым, насколько это возможно!

Но дилемма больших строк запроса является допустимым ограничением GET.Здесь я бы пошел прагматично, пока вы не достигнете этого предела, используйте GET и url-params.Это будет работать в 98% поисковых запросов.Действуйте, только если вы достигнете этого предела, а затем также введете POST с полезной нагрузкой (с типом mime Content-Type: application/x-www-form-urlencoded).

У вас есть больше примеров из реальной жизни?

0 голосов
/ 25 августа 2016

Это легко.Используйте POST.HTTP не накладывает ограничения на длину URL для GET, но серверы делают.Будьте прагматичны и обходите это ПОЧТОМ.

Вы также можете использовать тело GET (это разрешено), но это двойная ошибка в том смысле, что это неправильное использование и, вероятно, будут проблемы с сервером.

0 голосов
/ 26 февраля 2015

5 лет спустя, кажется, существует еще один жизнеспособный вариант - использовать тело сообщения GET.Я включил этот ответ в качестве альтернативы всем вышеизложенным предложениям, хотя у него есть свои ограничения (проведите небольшое исследование).

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