Подтвердить что ты не робот

Дизайн URL-адреса REST для более чем, меньше, чем операций

Мне сложно создать URL-адрес службы отдыха, которая может обрабатывать запросы клиентов на основе разбивки на страницы как один тип операций или запрашивать больше или меньше операторов в качестве другого типа операции. Например:

Разбивка:

GET /customers/0/100

На странице будет получено 100 клиентов.

Больше/меньше, чем:

Мне также нужен URL-адрес, чтобы получить клиентов с идентификатором больше n (например, скажем, 716). Как бы вы включили "больше" или "меньше" в URL-адрес. Я должен помнить, что символы " > " и "<" являются незаконными в URL-адресах. Я думаю, что этот дизайн URL выглядит странно:

GET /customers/greaterthan/716
GET /customers/lessthan/716

Я не могу использовать диапазон, поскольку это противоречило бы шаблону разбивки на страницы, указанному выше, и не является хорошим решением в любом случае, например:

GET /customers/716/999999999999
GET /customers/0/716

Я уверен, что мне не хватает чего-то очевидного - есть ли у кого-нибудь лучшее решение?

4b9b3361

Ответ 1

Pagination, morethan и lessthan, звучат как параметр запроса для меня, так как вы запрашиваете свой ресурс с этими параметрами. Поэтому вы должны сделать что-то вроде:

/customers? page = 1, или
/customers? page = 1 & gt = 716, или
/customers? page = 1 & gt; 716 & lt = 819

Вы можете даже ограничить размер страницы:

/customers? page = 1 & gt = 716 & lt = 819 & maxpagesize = 100

где gt означает больше (то же, что и при xml-экранировании), а lt меньше <.pdf >

Ответ 2

Если у вас есть несколько параметров и вам необходимо применить некоторые условия для каждого параметра, я рекомендую передать объект JSON в параметры.

Предположим, вы хотите выполнить условие для id и page:

/customers?id={"lt": 100, "gt": 30}&page={"start": 1, "size": 10}

В нем говорится, что я хочу, чтобы клиенты, у которых Id (s) меньше 100 и больше 30 на странице 1 и номер страницы из 10.

Итак, теперь, если вы хотите применить другое условие для других параметров, вы можете сделать это:

/customers?id={"lt": 100, "gt": 30}&children={"lt": 5, "gt": 2}&page={"start": 1, "size": 10}

и этот запрос означает, что клиенты с Id (s) меньше 100 и больше 30, дети меньше 5 и больше 2 в номере страницы 1 с размером страницы из 10.

Я настоятельно рекомендую вам прочитать этот документ о разработке API RESTful: http://blog.luisrei.com/articles/rest.html

Ответ 3

REST - это архитектурный стиль, который не следует рассматривать как специфичный для HTTP. Структура URI не является тем, что делает архитектуру RESTful.

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

/customers?min=0&max=76

Ответ 4

@Юлио Фаерман:

Ну, проблема начинается, когда вы получаете несколько параметров. Представьте строку запроса для "Клиенты старше 18 лет и моложе 60 с более чем двумя детьми".

Вы можете определить любые параметры запроса, например:

/customers?min-age=19&max-age=59&min-children=3

в моем примере min и max являются целыми числами и являются инклюзивными. Вы можете изменить это, если хотите. Помните, что все, что содержится в URI, является частью идентификатора ресурса. Мое личное мнение состоит в том, что вещи после ? приравниваются к предложениям в WHERE части SQL-запроса (плюс ORDER BY и LIMIT, не показаны здесь):

SELECT * FROM customers WHERE age>=19 AND age<=59 AND children>=3

Edit:
Вместо префиксов min- и max- вы можете разрешить >, < (и, возможно, !) в качестве окончательного символа имени параметра, поэтому вместо min-age у вас есть параметр с именем age>, который в сочетании со значением в строке запроса заканчивается похожим на age>=19:-)
Очевидно, вы можете использовать этот трюк только тогда, когда сравнение имеет знак равенства.

Ответ 5

Предположим, вы собираетесь получать журналы своего сервера и предположите, что ваши данные выглядят следующим образом:

{
    "protocol": "http",
    "host": "example.domain.com",
    "path": "/apis/classified/server/logs",
    "method": "GET",
    "ip": "::ffff:127.0.0.1",
    "time": 1483066346338,
    "usingTime": 12,
    "status": 200,
    "headers": {
        "user-agent": "Mozilla/5.0 Chrome"
    }
}

И вы хотите запросить такой способ, где

  • protocol равно 'http'.
  • host равно 'example.domain.com', или не равно 'example.domain.me'.
  • path равно '/apis/classified/server/logs' или нравится /*classified\/server*/.
  • method равно 'DELETE' или не равно 'GET' или в ['POST', 'PUT', 'DELETE'].
  • ip равно '127.0.0.1', или не равно '127.0.0.1'.
  • usingTime больше, чем 3500, или больше или равно 1500 и меньше или равно 3500.
  • status равно 404, или не равно 200, или больше или равно 400 и меньше 500.
  • headers.user-agent нравится /*chrome*/i.

Здесь маршруты идут следующим образом:

  • /apis/classified/server/logs?path=/apis/classfied
  • /apis/classified/server/logs?path.regex=*classfied*
  • /apis/classified/server/logs?method.ne=GET
  • /apis/classified/server/logs?method=POST&method=PATCH&method=PUT
  • /apis/classified/server/logs?usingTime.gte=1500&usingTime.lte=2500
  • /apis/classified/server/logs?headers.user-agent.regex=*chrome*

Если вы используете express.js в качестве сервера, ваш req.query будет структурирован следующим образом:

  • {"path": "/apis/classfied"}
  • {"path": {"regex": "*classfied*"}}
  • {"method": "DELETE"}
  • {"method": ["GET","POST","PUT"]}
  • {"usingTime": {"gte": "1500","lte": "2500"}} (lte: меньше или равно)
  • {"status": {"ne": "200"}}} (ne: не равно)
  • {"path": {"regex": "*classfied*"}}
  • {"headers": {"user-agent": {"regex": "*chrome*", "flag": "i"}}}

И вы собираетесь использовать много if-else, чтобы составить свой метод запросов mongoose или, возможно, строку SQL.

Ответ 6

Я бы реализовал его как диапазон, и если обе стороны открыты, просто не заполняйте его.

GET /customers/16-
GET /customers/-716

При запросе всех клиентов не добавляйте все, просто оставьте пустым

GET /customers

Или, когда вам нужно - знаки в вашем номере/коде, используйте это:

GET /customers/16/
GET /customers//716
GET /customers/16/716

Вы можете избежать косой черты, если они являются частью числа.

Ответ 7

Некоторые стандарты на основе REST предлагают адекватные подходы к этой проблеме. Например, https://www.hl7.org/fhir/stu3/search.html

Ваша проблема может быть решена следующим образом: GET /customers?id=ge500&id=lt1000

Кроме того, OData, который гораздо более совместим с любым стандартом на уровне отрасли. И он предлагает этот стиль: GET /customers?$filter=id ge 500 and id lt 1000

Ответ 8

ПРЕДУПРЕЖДЕНИЕ. Прочитайте отказ от ответственности ниже

Я не знаю, связан ли этот quetion с С#. Но если вы используете linq для своих запросов на стороне сервера, у меня есть другое предложение:

GET /customers?filter=CustomerNo>=16 AND CustomerNo<=716

Затем на стороне сервера:

using System.Linq.Dynamic;

var filteredCustomers = myCustomerTable.Where(filter);

Это должно быть самым гибким решением для всех, я думаю.


ПРЕДУПРЕЖДЕНИЕ добавлено 19 января 2017 г. Я просто обратил внимание на то, что для Dynamic Linq существует эксплойт для инъекций кода. В приведенном выше примере открывается возможность того, что клиент может запустить выполнение кода на сервере.

Ответ 9

Вот как я это делал.

Допустим, у вас есть поле age, которое является числом.

Вот как будут выглядеть URL-адреса
Равно: /filter/age = 5
Больше чем: /filter/age [gt] = 5
Больше чем равно: /filter/age [gte] = 5
Меньше, чем: /filter/age [lt] = 5
Меньше чем равно: /filter/age [lte] = 5
Не равно: /filter/age [ne] = 5

Затем, когда я передаю эти аргументы бэкэнду, у меня есть скрипт, который просто анализирует ключ и преобразует его в правильный фильтр на основе возраста [INSERT_OPERATOR_HERE]

Ответ 10

Я бы взял

 GET /customers/greaterthan=16;lessthan=716/

поскольку порядок не важен. Вы можете даже разбивать страницы сверху:

 GET /customers/greaterthan=16;lessthan=716/page/10

В качестве альтернативы (с соответствующим маршрутизатором запроса):

 GET /customers/16-716/page/10

И без "фильтра":

 GET /customers/all/page/10