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

84

Как указано в 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>. Это не сработает, потому что строка запроса не имеет неограниченной длины.

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

светильник
источник
2
Что означает «покой» в вашем контексте? Или перефразируя: почему GET успокаивает, а POST - нет? Потому что GET можно построить с помощью простой конкатенации строк? Ограничение длины запроса - избежать динамического выделения памяти в приложениях, которые предназначены для быстрой работы.
хачик
5
Когда я хочу выполнить поиск, я не хочу что-то создавать, удалять или обновлять, я просто хочу получить данные, поэтому мне не следует использовать POST, DELETE или PUT, а я должен использовать GET. Вот как я понял REST, но могу ошибаться на этот
счет
GET не подходит для поиска, поскольку результаты поиска могут со временем меняться. Веб-инфраструктура часто позволяет кэшировать запросы GET. Если вы используете GET, вы рискуете получить устаревшие результаты поиска. POST - это способ, рекомендованный ниже.
occulus
15
Все меняется со временем ( en.wikipedia.org/wiki/Impermanence ), такова природа вселенной ... Но GET следует использовать для поиска, потому что «действие поиска» не меняет результаты
Luxspes

Ответы:

51

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

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

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

jmpcm
источник
2
Вы правы, я вижу это как POST, потому что поиск - это изменчивый недавно вычисленный ресурс. Но у меня все еще есть проблемы с просмотром границы между POST и GET. Если я хочу выполнить поиск по всем научно-фантастическим книгам в библиотеке, я получу набор существующих ресурсов, поэтому у меня возникает соблазн использовать GET, но вы предлагаете рассматривать его как POST, потому что поиск сам по себе является новым ресурсом. Таким образом, строку запроса в GET следует использовать только для изменения представления данных, но не для фильтрации данных. Я прав?
cbliard
8
POST не следует использовать для поиска, GET - это то, что следует использовать, таким образом вы можете делиться и кешировать полученный URL-адрес и результаты, и вы лучше используете архитектуру RESTful в Интернете
Luxspes,
37
Этот ответ больше похож на попытку поиграть словами. По этой логике мы можем делать все как запросы POST и при этом оставаться в состоянии REST.
supertonsky
9
Этот ответ выглядит так, будто со мной разговаривает какой-то юрист :-) На самом деле вопрос звучит так: «У меня действительно есть дело GET, хорошо. Но моя строка запроса превышает допустимую длину. Как мне поступить». Голосование против этого ответа.
Г. Стойнев
2
Если следовать этой логике, то каждый запрос создает ресурс и получает его.
Alex
66

Спецификация 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здесь представлен уникальный идентификатор ресурса, представляющего ваш поиск. Эти два запроса в основном означают: создать новый объект поиска с этими критериями, а затем получить результаты, связанные с созданным объектом поиска.

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

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

Винсент Роберт
источник
Как это отвечает требованиям OP о закладке запроса?
Rhubarb
2
@Rhubarb явно решает эту проблему, создавая ресурс для заданного поиска.
maulik13
3
Это замедлит результаты. Выполните публикацию, а затем выполните GET. он добавит еще как минимум 300 мс для получения результатов поиска.
jaxxbo
Ссылка на источник мертва
Emobe
Я не понимаю, что сервер делает между POST и GET? кэширует ли он данные поиска на сервере и просто ждет поступления запроса GET? Для этого нужно будет использовать какой-то уникальный идентификатор, чтобы вы могли получить кеш. Ваш ответ хорош, но, конечно, не полон. А использование кеша сделает вещи менее безгражданскими.
Alexander Mills
5

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

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

ПитерМмм
источник
4

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

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

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

У вас есть еще примеры из реального мира?

Мануэль Алдана
источник
Вычисление было примером из реального мира. Что касается поиска, мы хотим иметь возможность искать транзакции в нескольких точках продажи, поэтому мы открываем новое окно браузера, чтобы выбрать точки продажи. И когда мы проверяем, мы изменяем скрытый параметр в форме поиска, чтобы установить выбранные точки продажи. Если их действительно много, то полученный поисковый запрос будет иметь очень длинную строку запроса.
cbliard
3

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

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

Кен Кранц
источник
7
«GET - это ограничение браузера» - это тоже ограничение сервера. Вы обнаружите, что все веб-серверы применяют ограничение, и если у вас есть CDN, они также могут применять ограничение. Использование других инструментов для выполнения запроса не позволит обойти ограничения сервера.
Кортни Майлз
0

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

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

Рик О'Ши
источник