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

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

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

Ответ 1

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

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

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

Ответ 2

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

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

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

Пример

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

201 Created
Location: /search/01543164876

затем

GET /search/01543164876

200 Ok
... your results here...

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

EDIT

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

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

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

Ответ 3

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

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

Ответ 4

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

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

Ответ 5

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

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

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

Есть ли у вас более реальные примеры?

Ответ 6

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

Ответ 7

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

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