Як я можу впоратися з обмеженнями довжини рядка запиту 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, але, можливо, я помиляюся
cbliard

GET не підходить для пошуку, оскільки результати пошуку можуть з часом змінюватися. Веб-інфраструктура часто дозволяє кешувати запити GET. Якщо ви використовуєте GET, ви ризикуєте отримати застарілі результати пошуку. POST - це спосіб, як рекомендується нижче.
okulus

15
Все змінюється з плином часу ( en.wikipedia.org/wiki/Impermanence ), така природа Всесвіту ... Але GET слід використовувати для пошуку, оскільки "пошукова дія" не змінює результати
Luxspes

Відповіді:


51

Виходячи з вашого опису, IMHO, ви повинні використовувати POST. POST призначений для розміщення даних на сервері та, в деяких випадках, отримання відповіді. У вашому випадку ви виконуєте пошук (надсилаєте запит на сервер) і отримуєте результат цього пошуку (отримуєте результат запиту).

Визначення GET говорить, що його потрібно використовувати для отримання вже існуючого ресурсу. За визначенням, POST - це створення нового ресурсу. Це саме те, що ви робите: створюєте ресурс на сервері та отримуєте його! Навіть якщо ви не зберігаєте результат пошуку, ви створили об'єкт на сервері та отримали його. Як попередньо сказав PeterMmm, ви можете зробити це за допомогою POST (створити та зберегти результат запиту), а потім використовувати GET для отримання запиту, але більш практичним є лише POST і отримання результату.

Сподіваюся, це допомагає! :)


2
Ви маєте рацію, я можу розглядати це як POST, оскільки пошук - це нестабільний нещодавно обчислений ресурс. Але я все ще маю проблеми з баченням межі між POST та GET. Якщо я хочу здійснити пошук у всіх науково-фантастичних книгах у бібліотеці, я отримаю колекцію існуючих ресурсів, тому у мене виникає спокуса скористатися GET, але ви пропонуєте розглядати його як POST, оскільки пошук сам є новим ресурсом. Отже, рядок запиту в GET слід використовувати лише для зміни представлення даних, але не для фільтрування даних. Чи правий я?
cbliard

8
POST не слід використовувати для пошуку, GET - це те, що слід використовувати, таким чином ви можете ділитися та кешувати, отриману URL-адресу та результати, і ви краще використовуєте RESTful архітектуру Інтернету
Luxspes

37
Ця відповідь звучить більше як спроба пограти словами. За цією логікою ми можемо робити все як запити POST і при цьому залишатись RESTful.
supertonsky

9
Ця відповідь здається, що якийсь адвокат розмовляє зі мною :-) Питання справді: "У мене є справа GET, добре. Але мій рядок запиту перевищує дозволену довжину. Як я маю справу". Проголосувавши проти цієї відповіді.
Г. Стойнєв

2
Якщо ця логіка слідувала, то кожен запит створює ресурс і отримує його.
Алекс

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тут представлений унікальний ідентифікатор ресурсу, що представляє ваш пошук. Ці 2 запити в основному означають: створіть новий об’єкт пошуку з цими критеріями, а потім отримайте результати, пов’язані зі створеним об’єктом пошуку.

Цей ідентифікатор може бути унікальним ідентифікатором, що генерується для кожного нового запиту. Це означало б, що ваш сервер буде витікати "пошукові" об'єкти, і вам доведеться регулярно очищати їх за допомогою стратегії кешування.

Або це може бути хеш усіх критеріїв пошуку, що фактично представляють пошук, заданий користувачем. Це дозволяє повторно використовувати ідентифікатори, оскільки відтворення пошуку призведе до повернення існуючого ідентифікатора, який може (або може не бути) вже кешований.


Як це стосується вимоги OP щодо закладки запиту?
Ревінь

2
@Rhubarb він вирішує це чітко, створюючи ресурс для певного пошуку.
maulik13

3
Це сповільнить результати. Виконайте пост, а потім виконайте GET. він додасть щонайменше 300 мс більше для пошуку.
jaxxbo

Посилання на джерело мертве
Emobe

Я збентежений, що робить сервер між POST та GET? чи кешує дані пошуку на сервері і просто чекає надходження запиту GET? Для цього йому потрібно було б використовувати якийсь унікальний ідентифікатор, щоб ви могли отримати кеш. Ваша відповідь приємна, але, безумовно, не повна. А використання кеш-пам'яті зробить речі менш апатридними.
Alexander Mills

5

REST - це спосіб робити щось, а не протокол. Навіть якщо ви не любите POST, коли це дійсно GET, це спрацює.

Якщо ви будете / повинні дотримуватися "стандартного" визначення GET, POST тощо, ніж, можливо, розглянути можливість POST запиту, цей запит буде зберігатися на сервері з ідентифікатором запиту та запитувати запит пізніше за допомогою GET by id.


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

4

Плутанина навколо GET - це обмеження браузера. Якщо ви створюєте інтерфейс RESTful для додатків A2A або P2P, тоді довжина вашого GET не обмежена.

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


6
"GET - це обмеження браузера" - це також обмеження сервера. Ви знайдете, що всі веб-сервери застосовують обмеження, і якщо у вас є CDN, вони також можуть застосувати обмеження. Використання інших інструментів для виконання запиту не обійде обмеження сервера.
Кортні Майлз

0

Це легко. Використовуйте POST. HTTP не встановлює обмеження на довжину URL-адреси для GET, але сервери це роблять. Будьте прагматичними та обійдіть це за допомогою POST.

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.