Разработка API запросов RESTful с длинным списком параметров запросов

75

Итак, мне нужно создать API запросов RESTful, который возвращает набор объектов на основе нескольких фильтров. Обычный HTTP-метод для этого - GET. Единственная проблема заключается в том, что у нее может быть как минимум дюжина фильтров, и если мы передадим все из них в качестве параметров запроса, URL-адрес может стать довольно длинным (достаточно долго, чтобы блокироваться некоторым брандмауэром).

Уменьшение количества параметров не является вариантом.

Один из вариантов, о котором я мог думать, - использовать метод POST в URI и отправлять фильтры как часть тела POST. Это против RESTfull (создание запроса POST для запроса данных).

У кого-нибудь есть лучшие дизайнерские предложения?

Спасибо

  • 2
    Использовать короткие (1 символ и т. Д.) Имена параметров?
  • 2
    Это может быть не совсем RESTful, но я думаю, что вы должны быть практичными, когда дело доходит до GET и POST. Если у вас есть так много переменных для отправки, и вы не можете их уменьшить, я бы ПОСТАНОВИЛ их. Я не люблю набивать URL, но это только я.
Теги:
rest
http-parameters

3 ответа

56

Многие люди согласились с тем, что GET с слишком длинной или слишком сложной строкой запроса (например, строки запроса не обрабатывают вложенные данные легко) может быть отправлено как POST вместо этого, причем представленные сложные/длинные данные в теле запроса.

Посмотрите спецификацию для POST в спецификации HTTP. Он невероятно широк. (Если вы хотите отплыть линкор через лазейку в REST... используйте POST.)

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

(lol long digression... Недавно я обнаружил, что по спецификации HTTP GET может содержать тело документа. Там один раздел, который говорит, перефразируя: "Любой запрос может иметь тело документа, кроме тех, которые перечислены в этом разделе"... и раздел, на который он ссылается, не отображает список. Я искал и нашел поток, в котором об этом говорили авторы HTTP, и это было намеренно, так что маршрутизаторам и таким не пришлось бы различать разные сообщения. Тем не менее, на практике многие объекты инфраструктуры бросают тело GET. Таким образом, вы можете ПОЛУЧИТЬ с фильтрами, представленными в теле, например, POST, но вы будете катать кости.)

  • 9
    Смотрите также этот вопрос для дальнейшего обсуждения HTTP GET с телом.
52

Помните, что с помощью REST API все это касается вашей точки зрения.

Двумя ключевыми понятиями в REST API являются конечные точки и ресурсы (сущности). Понятно, что конечная точка либо возвращает ресурсы через GET, либо принимает ресурсы через POST и PUT и т.д. (Или комбинацию выше).

Принимается, что с помощью POST отправленные вами данные могут или не могут привести к созданию нового ресурса и связанных с ним конечных точек, которые, скорее всего, не будут "жить" под POSTed url. Другими словами, когда вы отправляете POST, вы отправляете данные для обработки. Конечная точка POST не находится там, где обычно может быть найден ресурс.

Цитата из RFC 2616 (с несоответствующими деталями опущены и выделены соответствующие части):

9.5 POST

Метод POST используется для запроса, чтобы исходный сервер принял объект, заключенный в запрос в качестве нового подчиненного ресурса идентифицированных Request-URI в строке запроса. POST предназначен для позволяют единообразный метод охватывать следующие функции:

  • ...
  • Предоставление блока данных, например результата отправки формы, процессу обработки данных;
  • ...

...

Действие, выполняемое методом POST , может не привести к ресурсу, который может быть идентифицирован с помощью URI. В этом случае либо 200 (ОК), либо 204 (Нет содержимого) - это соответствующий статус ответа, в зависимости от , включает ли ответ объект, который описывает результат.

Если ресурс был создан на исходном сервере, ответ ДОЛЖЕН быть 201 (создан)...

Мы привыкли к конечным точкам и ресурсам, представляющим "вещи" или "данные", будь то пользователь, сообщение, книга - независимо от того, что диктует проблемная область. Однако конечная точка также может выставлять другой ресурс - например, результаты поиска.

Рассмотрим следующий пример:

GET    /books?author=AUTHOR
POST   /books
PUT    /books/ID
DELETE /books/ID

Это типичный REST CRUD. Однако что, если бы мы добавили:

POST /books/search

    {
        "keywords": "...",
        "yearRange": {"from": 1945, "to": 2003},
        "genre": "..."
    }

В этой конечной точке нет ничего лишнего. Он принимает данные (сущность) в форме тела запроса. Эти данные являются критериями поиска - DTO, как и любой другой. Эта конечная точка создает ресурс (объект) в ответ на запрос: Результаты поиска. Ресурс результатов поиска является временным, немедленно передается клиенту без переадресации и не подвергается какому-либо другому каноническому URL-адресу.

Он все еще REST, за исключением того, что сущности не являются книгами - объект запроса является критерием поиска книг, а объект ответа - результаты поиска в книгах.

  • 0
    Не могли бы вы предложить некоторые соглашения об именах классов для DTO?
  • 0
    Лично я бы пошел с BooksSearchCriteriaDTO и BooksSearchResultsDTO .
Показать ещё 2 комментария
2

Вкратце: сделайте POST, но переопределите HTTP-метод, используя заголовок X-HTTP-Method-Override.

Реальный запрос

POST/books

Тело сущности

{ "title": "Ipsum", "год": 2017 год }

Заголовки

X-HTTP-метод-переопределение: GET

На стороне сервера проверьте, существует ли заголовок X-HTTP-Method-Override, а затем берет его значение как способ построения маршрута к конечной конечной точке в бэкэнд. Кроме того, возьмите тело объекта как строку запроса. С обратной стороны запрос стал просто GET.

Таким образом, вы держите дизайн в гармонии с принципами REST.

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню