Обновить

Комментарии 19

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

Очень приятно, что откликается )) думаю во многих проектах есть это))
Надеюсь люди прочитают и на несколько таких ошибок в мире не станет больше :)

Ловите 11 прикол из вк-бот-апи: тела ответов всех эндпоинтов копируется в utf8. Кроме одного, который грузит файл на облако. Там ответ в windows1251. В документации этого нет

Не знаю, актуально ли сейчас, но я попался на это в 22 году, и видел статьи на эту тему, датирующиеся 18 годом

это уже задел на "# 20 ошибок API" :)
спасибо !

Так а чем сложные фильтры в get отправлять-то?

POST /api/internal/equipment

1) в этом пункте больше акцент на то, что такое именование вводит в заблуждение тк стандартная практика POST ../equipment подразумевает именно создание единицы техники

2) с другой стороны часто когда решают, что «фильтр сложный, в query-параметры не влезет» не знают, что на самом деле вполне может влезть тк ограничение длины URL ~8000 символов (в зависимости от браузера/сервера) [хотя в некоторых редких случаях 2000символов] т.е. во многих случаях вполне можно было и GET использовать

3) и в самом крайнем варианте, если фильтр реально сложный и большой, то
можно использовать POST /api/equipment/search с JSON в теле.
НО явно добавить /search чтобы именование не вводило в заблуждение.
Так делают Elasticsearch, Google Cloud API, Stripe. Это нормальная практика, но вариант все таки крайний

GET /api/internal/equipment?payload=base64url

Туда пихаем json.

Так можно без боли со сложными форматами делать. Из минусов - не удобно просматривать и редактировать вручную

Если фильтров, особенно обязательных, очень много, то есть риск не уложиться в длину урла. Но это прям нужно постараться. Даже если уложишься, то сама строка с урлом выглядит как мусор, и этот мусор сложно повторить руками, если нужно быстро набрать, например. Плюс, если в фильтрах есть массивы или словари, то с ними отдельная боль. Не все форматы их передачи и не везде поддерживаются, тут нужно прям запариться чтобы объяснить чего ты ждёшь не сервере и как это передавать, и обязательно кто-то из клиентов затупит, да и сам наверняка тупить местами будешь.

Я на такие случаи готовлю отдельный урл, который принимает post с фильтрами в теле, шифрую тело в одну строку и эту строку выдаю клиенту как ответ со статусом 201. Теперь этот фильтр он может передать в строке гет запроса к целевому ресурсу, а сервер строку расшифрует и получит фильтры. Да, это всё ещё некрасивая огромная строка урла, плюс один дополнительный запрос к фильтру (откровенно, это решается шифрованием на клиенте), но такой способ идеально поддаётся документированию и не требует лишних телодвижений чтобы разъяснить клиенту как ему эти фильтры форматировать.

А почему просто не сериализовать на клиенте? Сериализация намного проще шифрования. Шифрование вообще избыточно в этом случае, ведь данные в любом случае передаются "в открытую" вначале. На мой взгляд, это уже сильный оверхед только ради красивой документации. При медленном интернете (что особенно актуально сейчас) это будет боль...

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

Зашифровать я имел ввиду не в плане зашифровать с точки зрения криптографии, а в плане превратить в строку, которую удобно скопировать и вставить в урл. Тот же urlBase64 вполне подойдёт.

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

просто для base64, мне кажется, эндпоинт всё-таки избыточен... В доке (в том же сваггере) можно написать, что "это поле принимает base64". Можно даже в названии параметра это указать: "searchQueryBase64". Вам же по-любому нужно будет это указать)) всё равно есть промежуток между сериализацией и отправкой итогового запроса

В любом случае, очень круто, что столько внимания уделяется документации

RFC 9110 просто существует...

Злобное «хо-хо-хо». Что? Мы вас не слышим! У нас тут всегда get, а если что-то большое вложением, то post! Что? А, да, до свидания!..

Хорошая статья. Но хотелось бы рассмотреть тему с другой стороны.
HTTP коды не тоже самое что бизнес-коды.
HTTP методы не равны бизнес-методам.
Поэтому REST хорошо, а RESTful (в обычном пониманиии: GET -Получение, POST- Создание, PUT/PATCH - Обновление, DELETE - Удаление) это плохо.
Идемпотентность - это бизнес правило. Сейчас get /users/123 вернет одно, а через 5 минут другое. Или счетчик какой-то увеличится.
Конечно, неперехваченная ошибка - это 500, не авторизированный запрос - это 401, нет прав - 403, нет страницы - 404.
Остальное - обсуждается (или ставится не вами, например,таймаут). Обычно это 400 Bad Request.
PS. и на вентилятор, проходилось посылать/принимать даные в body для get, и в query-string для post. А еще и в header'е.

А почему RESTful - плохо? Да, всё, что Вы перечислили до этого, имеет место быть. Но это не мешает существовать корректному RESTful)

P.S. у GET методов нет body (или тут имеется ввиду не метод, а "суть" - получение данных?)

Правильней было бы так сформулиривать - требование следовать ему всегда/везде - это плохо.
имхо, есть только один паттерн - здравый смысл. но это слишком абстрактно и плохо формализуется. А restful, solid, clean code и иже с ними - нужно применять только там, где нужно (сорри за тавтологию)

Тогда согласен на все сто. Очень не нравится, когда люди следуют паттернам по принципу "потому что так надо"

если формировать HTTP request ручками (т.е. на низком уровне) - то есть и query string, и body, и header. А HTTP verb можно любой подставить.

Хах, такими темпами новый TCP протокол получится))

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации