REST API, практические вопросы
От: Artem Korneev США https://www.linkedin.com/in/artemkorneev/
Дата: 05.05.16 06:02
Оценка: 2 (1) +3
Пилим мы REST-сервисы для проекта. Стараемся следовать рекоммендациям для RESTful-архитектур, но иногда не получается. Вот, например, намедни коллега добавила метод с такой сигнатурой:

[HttpPost]
[Route("ValueSet/$expand")]
public FHIR.Model.Bundle GetValueSetMembersByOIDs(IEnumerable<string> oids)


На что я ей заметил, что метод, запрашивающий данные, должен использовать GET-запрос, а не POST. Коллега не соглашается, заявляет, мол, "я много раз так делала и всё нормально".

Вопрос — а допустимы ли такие фокусы в правильных REST-сервисах? Ну т.е. мне вот с одной стороны бросается в глаза такой косяк, но в то же время в описаниях REST-архитектур я не смог найти запрета на использование POST запросов вместо GET, для запроса данных.

Далее.. позвал я ихнего техлида и он мне пояснил причину такого кода — в кач-ве параметра к запросу передаётся массив идентификаторов. Каждый идентификатор — около 30 символов. Если передавать их как параметры GET-запроса, то легко массив из 60 идентификаторов займёт уже пару килобайт и они не уверены, не превысит ли это лимитов длины HTTP-запроса.

Вот второй, более важный вопрос — как такие вещи делаются по-человечески? Вот если нужно поддерживать GET-запросы, в которых длина аргументов тянет на пяток килобайт, как быть? Требовать разбивать запросы? Или плюнуть и запрашивать данные через POST-запрос, передавая параметры в теле запроса? Или настраивать Web-сервер, чтоб увеличить максимальную длину запроса?

Посоветуйте. Кто-нибудь наверняка ведь сталкивался с ситуацией, когда для запроса данных нужно передать несколько десятков параметров. Может какие-то примеры есть среди общеизвестных REST-сервисов?
С уважением, Artem Korneev.
Re: REST API, практические вопросы
От: #John Европа https://github.com/ichensky
Дата: 05.05.16 11:36
Оценка: -5
Здравствуйте, Artem Korneev, Вы писали:

AK>Вопрос — а допустимы ли такие фокусы в правильных REST-сервисах? Ну т.е. мне вот с одной стороны бросается в глаза такой косяк, но в то же время в описаниях REST-архитектур я не смог найти запрета на использование POST запросов вместо GET, для запроса данных.

Учитывая все несовершенсво http-протокола — да. Если url может стать больше 2048 символов,
то неважно передаем мы массив или просто несколько параметров — нам надо юзать post.
Вот напр. если имя пользователя может превышать 1000символов и фамилия больше 1000
и вся остальная часть url=96 символов,
а нам надо сделать запрос ввида ?name=xxx&secondname=yyy — нужно делать только post запрос.

Если переделать http, для современного веба, то по правильному http get — надо убать вообще.
http post надо кешировать как сейчас http get,т.е. кешировать на время указанное сервером.
к http post добавить флаг (IsUrlCanBeWrittenByHands)- специально для броузеров и поисковиков,
указывающий что этот запрос надо показать пользователю ввиде читаемого url.
Підтримати Україну у боротьбі з країною-терористом.

https://prytulafoundation.org/
https://u24.gov.ua/

Слава Збройним Силам України!!! Героям слава!!!
Re: REST API, практические вопросы
От: Sharov Россия  
Дата: 05.05.16 13:04
Оценка:
Здравствуйте, Artem Korneev, Вы писали:

AK>Вот второй, более важный вопрос — как такие вещи делаются по-человечески? Вот если нужно поддерживать GET-запросы, в которых длина аргументов тянет на пяток килобайт, как быть? Требовать разбивать запросы? Или плюнуть и запрашивать данные через POST-запрос, передавая параметры в теле запроса? Или настраивать Web-сервер, чтоб увеличить максимальную длину запроса?


AK>Посоветуйте. Кто-нибудь наверняка ведь сталкивался с ситуацией, когда для запроса данных нужно передать несколько десятков параметров. Может какие-то примеры есть среди общеизвестных REST-сервисов?


Вообще говоря POST предназначен для созданиям объектов, т.е. он ради сайд эффектов. Особого криминала приспособить его для получения объектов в случае когда на серевер отправляется много параметров запроса тоже не вижу. Но желательно пересмотреть архитектуру, например когда надо сделать запросы по ид от 1 до 10, то оформлять в виде диапазонов и пихать в querystring. Тут можно поглядеть обсуждение.
Кодом людям нужно помогать!
Re[2]: REST API, практические вопросы
От: Sharov Россия  
Дата: 05.05.16 13:07
Оценка:
Здравствуйте, #John, Вы писали:

J>Если переделать http, для современного веба, то по правильному http get — надо убать вообще.

J>http post надо кешировать как сейчас http get,т.е. кешировать на время указанное сервером.
J>к http post добавить флаг (IsUrlCanBeWrittenByHands)- специально для броузеров и поисковиков,
J>указывающий что этот запрос надо показать пользователю ввиде читаемого url.

Вот есть операции, универсальные для любого объекта -- получить, добавить, удалить и изменить. Зачем нужно удалять операцию "получить", базовую по сути?
Кодом людям нужно помогать!
Re: REST API, практические вопросы
От: α Российская Империя  
Дата: 05.05.16 13:49
Оценка: 3 (1)
Здравствуйте, Artem Korneev, Вы писали:

AK>Пилим мы REST-сервисы для проекта. Стараемся следовать рекоммендациям для RESTful-архитектур, но иногда не получается. Вот, например, намедни коллега добавила метод с такой сигнатурой


Вообще, если речь идёт о fhir, то в его спецификации прямо все расписано, как делать запросы и каким http-методом, разве не?
Согласно спецификации можно и GET и POST
Отредактировано 05.05.2016 16:59 α . Предыдущая версия .
Re[3]: REST API, практические вопросы
От: #John Европа https://github.com/ichensky
Дата: 05.05.16 15:47
Оценка: -2
Здравствуйте, Sharov, Вы писали:

S>Вот есть операции, универсальные для любого объекта -- получить, добавить, удалить и изменить. Зачем нужно удалять операцию "получить", базовую по сути?

Потому что в современном вебе http исспользуется не по назначению.
Был когда-то создан ftp протокол для обмена документами через сервак
и у него были вполене логичные комманды для манипулирования доками на серваке.
Но прошлое некоторое время, люди увидели что ftp — это слишком сложно: надо скачать документ,
потом проанализировать его название, содержимое, подобрать программу которая бы понимала документ,
открыть, прочитать. Этим людям нравилось просматривать гипертекстовые страницы(html+теги), а не маны,
так что бы все ключевы слова были выделенны, заголовки подчеркнуты
и можно было быстро легко переходить на другие документы по ссылкам.
Прибилизительно в тоже время кто-то изобрел мышку и этим людям оч. понравилось ею клацать.
И они решили создать более простой протокол который работал бы как ftp, но только для просмотра документов
определенного типа: гипертекстовых страниц.

Прошло время(развивался html -добавлялись новые теги),
люди захотели вставлять смишнявки(картиночки) в html, а также изменять содержимое этих документов,
что бы люди всегда получали самую актуальную информацию: были добавлены методы put, delete,
а чтобы серевер могу выдержать нагружку в 10человек, при дорогущем итернете, был запилем метод post.
Но в то время, наши прадеды и не догадовали, во что может превратиться их безобидная шутка с гипертекстовыми страницам.
Однажды(будущий создатель js) подумал: пользователи загружают статические странички, но они такие скучные:
"Было бы классно, если бы картиночки прыгали вверх-вниз, а текст мигал."
"Вот круто разыграю своего товарища" — подумал человек и создал js.

Если бы созадатели html+http+js только знали что в начале 21го века, компьютеры сами будут скачивать не доверенный,
не проверенный, не лицинзионный исполняемый код(js), который будет манипулировать пользовательскими данными.
А на js будут создаваться полноценные ria single page mvpmvvmmvc приложения с rest-full серверной архитектурой,
они бы никогда, никогда так не шутили.

Если кратко:
http — не создавался под нужды современного веба, а был адаптирован из безобидной шутки.
Підтримати Україну у боротьбі з країною-терористом.

https://prytulafoundation.org/
https://u24.gov.ua/

Слава Збройним Силам України!!! Героям слава!!!
http html js
Re[4]: REST API, практические вопросы
От: Sharov Россия  
Дата: 05.05.16 16:00
Оценка:
Здравствуйте, #John, Вы писали:

J>Здравствуйте, Sharov, Вы писали:


S>>Вот есть операции, универсальные для любого объекта -- получить, добавить, удалить и изменить. Зачем нужно удалять операцию "получить", базовую по сути?

J>Потому что в современном вебе http исспользуется не по назначению.

J>Если кратко:

J>http — не создавался под нужды современного веба, а был адаптирован из безобидной шутки.

REST как раз и призван это исправить и как-то упорядочить.
Кодом людям нужно помогать!
Re: REST API, практические вопросы
От: Vladek Россия Github
Дата: 05.05.16 16:30
Оценка: 7 (2)
Здравствуйте, Artem Korneev, Вы писали:

AK>Посоветуйте. Кто-нибудь наверняка ведь сталкивался с ситуацией, когда для запроса данных нужно передать несколько десятков параметров. Может какие-то примеры есть среди общеизвестных REST-сервисов?


Решал эту проблему двумя способами:

Отредактировано 05.05.2016 16:31 Vladek . Предыдущая версия .
Re[2]: REST API, практические вопросы
От: #John Европа https://github.com/ichensky
Дата: 05.05.16 17:44
Оценка: +1
Здравствуйте, Vladek, Вы писали:

V>Игрался с параметрами в Web.config


Норм. вариант, если делается типичное энтерпрайз single-page js-приложение,
работающее в одном из браузеров хрома, версии 50.x.x.x.x, max length

V>Аргумент у метода сервиса был простой строкой, которая парсилась и превращалась обратно в массив. Что-то вроде..

Норм. вариант. как частный случай для небольшого массива.
Что бы в js не пришлось вручную парсить, массивы обычно передают ввиде json arr(где ','-разделитель).
Підтримати Україну у боротьбі з країною-терористом.

https://prytulafoundation.org/
https://u24.gov.ua/

Слава Збройним Силам України!!! Героям слава!!!
Re[2]: REST API, практические вопросы
От: Artem Korneev США https://www.linkedin.com/in/artemkorneev/
Дата: 05.05.16 18:08
Оценка:
Здравствуйте, #John, Вы писали:

J>Если переделать http, для современного веба, то по правильному http get — надо убать вообще.

J>http post надо кешировать как сейчас http get

Зачем такие сложности? Поддержка передачи параметров в "body" вполне решила бы проблему с длиной URL.
С уважением, Artem Korneev.
Re[3]: REST API, практические вопросы
От: · Великобритания  
Дата: 06.05.16 09:03
Оценка:
Здравствуйте, Artem Korneev, Вы писали:

J>>Если переделать http, для современного веба, то по правильному http get — надо убать вообще.

J>>http post надо кешировать как сейчас http get

AK>Зачем такие сложности? Поддержка передачи параметров в "body" вполне решила бы проблему с длиной URL.

Только по стандарту это может не работать. Если ты передаёшь body в get, то сервер SHOULD игнорировать. Информация возвращаемая должна зависеть только от url.
https://tools.ietf.org/html/rfc2616#section-4.3

if the request method does not include defined semantics for an entity-body, then the message-body SHOULD be ignored when handling the request.

https://tools.ietf.org/html/rfc2616#section-9.3

The GET method means retrieve whatever information (in the form of an entity) is identified by the Request-URI.


Т.е. один из сильных аргументов rest "а давайте чтобы всё быстрее заработало — поставим обычный кеширующий http прокси" — вдруг всё поломает, т.к. прокси (да и любые другие компоненты) может игнорировать тело get и иметь ограничение на длину url.

Как последнее средство — попробовать передизайнить ваш API чтобы не приходилось слать большие списки в get.

Ещё можно свой http verb ввести, это стандарт позволяет.

Так что при всём богатстве выбора — альтернативы post нет.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Отредактировано 06.05.2016 9:07 · . Предыдущая версия .
Re[4]: REST API, практические вопросы
От: Artem Korneev США https://www.linkedin.com/in/artemkorneev/
Дата: 06.05.16 17:43
Оценка:
Здравствуйте, ·, Вы писали:

AK>>Зачем такие сложности? Поддержка передачи параметров в "body" вполне решила бы проблему с длиной URL.

·>Только по стандарту это может не работать.

Разумеется. Поэтому я и написал "решила бы".
С уважением, Artem Korneev.
Re[5]: REST API, практические вопросы
От: · Великобритания  
Дата: 06.05.16 18:14
Оценка:
Здравствуйте, Artem Korneev, Вы писали:

AK>·>Только по стандарту это может не работать.


AK>Разумеется. Поэтому я и написал "решила бы".

Тут ведь как. Если подумать, то это ограничение get возникло не на пустом месте. Оно позволяет кеши, балансеры и прочее реализовывать эффективно. Кешировать по небольшому урлу имеет смысл, а для произвольного размера body вряд ли получится сделать что-то полезное.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[2]: REST API, практические вопросы
От: Artem Korneev США https://www.linkedin.com/in/artemkorneev/
Дата: 09.05.16 05:45
Оценка:
Здравствуйте, α, Вы писали:

AK>>Пилим мы REST-сервисы для проекта. Стараемся следовать рекоммендациям для RESTful-архитектур, но иногда не получается. Вот, например, намедни коллега добавила метод с такой сигнатурой

α>Вообще, если речь идёт о fhir, то в его спецификации прямо все расписано, как делать запросы и каким http-методом, разве не?
α>Согласно спецификации можно и GET и POST

Да.. но там всё-таки POST используется для "search", т.е. выборки по каким-то фильтрам, а не просто для получения по ID.
Вот для запроса по одному ID там по спецификации требуется GET. А запроса по нескольким ID в спецификации нет — это мелкие дополнения нашей платформы. Всё-таки мы склоняемся к тому, что запрос по нескольким идентификаторам тоже должен быть GET.
С уважением, Artem Korneev.
Re[2]: REST API, практические вопросы
От: Artem Korneev США https://www.linkedin.com/in/artemkorneev/
Дата: 09.05.16 05:54
Оценка:
Здравствуйте, Vladek, Вы писали:

V>
  • Игрался с параметрами в Web.config

    По-моему, нету у нас web.config Ну или я его не нашёл.
    Шаблон проекта у нас не совсем обычный. Мы пилим микросервисы под Azure Service Fabric. А оно поддерживает self-hosted WebAPI сервисы через nuget-пакеты Owin. Т.е. там потом приложение запускается на кластере Azure Service Fabric и уже из него стартует WebAPI-сервис. Файла web.config там нет.
    Наверное можно ещё какими-то параметрами инициализации в коде поиграться чтоб добиться того же эффекта. Но я вчера опытным путём установил, что сервис нормально принимает строки до 16Kb — вполне достаточно для наших нужд. Правда, я это тестировал на локальном эмуляторе Azure Service Fabric. Но вроде на то он и эмулятор чтоб предоставлять примерно тот же рантайм, что и реальное облако. В любом случае, надо будет ещё в облаке всё это потестировать.
  • С уважением, Artem Korneev.
    Re[6]: REST API, практические вопросы
    От: Artem Korneev США https://www.linkedin.com/in/artemkorneev/
    Дата: 13.05.16 06:38
    Оценка:
    Здравствуйте, ·, Вы писали:

    ·>Кешировать по небольшому урлу имеет смысл, а для произвольного размера body вряд ли получится сделать что-то полезное.


    Так принципиальной разницы нет — урл тоже теоретически безразмерный. Стандарт не ограничивает. На практике установлено, что ASP.NET поддерживает, как минимум, ~16Kb в параметрах URL. А при желании можно и больше настроить.
    С уважением, Artem Korneev.
    Re[7]: REST API, практические вопросы
    От: · Великобритания  
    Дата: 14.05.16 18:30
    Оценка:
    Здравствуйте, Artem Korneev, Вы писали:

    AK>·>Кешировать по небольшому урлу имеет смысл, а для произвольного размера body вряд ли получится сделать что-то полезное.


    AK>Так принципиальной разницы нет — урл тоже теоретически безразмерный. Стандарт не ограничивает. На практике установлено, что ASP.NET поддерживает, как минимум, ~16Kb в параметрах URL. А при желании можно и больше настроить.

    Зато он говорит, что можно выкинуть 414 uri too long, а значит это может сделать любой промежуточный софт на пути http. Т.е. основывать свой rest api на произвольной длины урлах я бы не советовал.
    но это не зря, хотя, может быть, невзначай
    гÅрмония мира не знает границ — сейчас мы будем пить чай
    Re: REST API, практические вопросы
    От: pestis  
    Дата: 15.05.16 06:41
    Оценка: 10 (2) +4 -2
    Здравствуйте, Artem Korneev, Вы писали:

    AK>Вопрос — а допустимы ли такие фокусы в правильных REST-сервисах? Ну т.е. мне вот с одной стороны бросается в глаза такой косяк, но в то же время в описаниях REST-архитектур я не смог найти запрета на использование POST запросов вместо GET, для запроса данных.


    С мотивацией "ну ведь в GET может не влезть" категорически недопустимы.

    AK>Вот второй, более важный вопрос — как такие вещи делаются по-человечески? Вот если нужно поддерживать GET-запросы, в которых длина аргументов тянет на пяток килобайт, как быть? Требовать разбивать запросы? Или плюнуть и запрашивать данные через POST-запрос, передавая параметры в теле запроса? Или настраивать Web-сервер, чтоб увеличить максимальную длину запроса?


    По человечески это делается через POST метод %create_operation%, который принимает аргументы операции и возвращает токен. Затем по этому токену можно получить результат. Достоинства: идеологически верно, гарантированно не вызывает проблем с HTTP миддлварью, позволяет безболезненно прикрутить CQRS в реализации.
    ёб
    Re[2]: REST API, практические вопросы
    От: Sharov Россия  
    Дата: 16.05.16 10:23
    Оценка:
    Здравствуйте, pestis, Вы писали:



    P>По человечески это делается через POST метод %create_operation%, который принимает аргументы операции и возвращает токен. Затем по этому токену можно получить результат. Достоинства: идеологически верно, гарантированно не вызывает проблем с HTTP миддлварью, позволяет безболезненно прикрутить CQRS в реализации.


    Блин, вот реально огромная благодарность за столь очевидный, но мне в свое время
    Автор: Sharov
    Дата: 17.10.14
    не пришедший в голову ход.
    Кодом людям нужно помогать!
    Re[2]: REST API, практические вопросы
    От: yenik  
    Дата: 17.05.16 06:38
    Оценка:
    P>По человечески это делается через POST метод %create_operation%, который принимает аргументы операции и возвращает токен. Затем по этому токену можно получить результат. Достоинства: идеологически верно, гарантированно не вызывает проблем с HTTP миддлварью, позволяет безболезненно прикрутить CQRS в реализации.

    Между запросами эта операция должна храниться на сервере? Едва ли это идеологически верно.
    Подождите ...
    Wait...
    Пока на собственное сообщение не было ответов, его можно удалить.