RESTful API Design: 13 лучших практик, которые сделают ваших пользователей счастливыми
написать впереди
Причина, по которой я перевел эту статью, заключается в том, что с тех пор, как я стал фронтенд-фермером кода, настройка интерфейса стала обычным делом, а также сопровождается бесчисленными спорами и беспомощностью. пиши дружелюбноrestful api
Будь то для ваших коллег или пользователей, которые в будущем будут вызывать интерфейс как сторонний сервис, это очень важно. оrestful api
Я прочитал много статей и книг одну за другой с точки зрения самих себя и принципов дизайна.Прочитав исходный текст, я чувствую, что 13 лучших практик, указанных в тексте, являются относительно всеобъемлющими и содержательными, поэтому я перевел их и поделился их с вами. Если есть какая-то ошибка, пожалуйста, поправьте меня.
Так как я вообще склоняюсь к вольному переводу, то буду опускать начальные слова в исходном тексте или какой-то не относящийся к теме контент.Ведь время-деньги.Друзьям,которые хорошо владеют английским языком и умеют научно бороздить просторы интернета,советую прочитать исходный текст , чтобы не вызывать недоразумений.
1. Понимание HTTP применительно к REST
Если вы хотите построить хорошо спроектированныйREST API, узнать немного оHTTP-протоколОсновы полезны, ведь заточка ножей не делает дровосеков ошибкой.
На MDN много хорошего качестваДокументацияЗнакомство с HTTP. Однако толькоДизайн REST-APIСами по себе точки знаний HTTP, вероятно, включают следующее:
- Включено в HTTPглагол(или метод):
GET
,POST
,PUT
,PATCH
а такжеDELETE
является наиболее часто используемым. - ОТДЫХориентированный на ресурсы, ресурс используетсяURIвыявлены, такие как
/articles/
. -
конечная точка, который обычно относится к комбинации глагола и URI, например
GET: /articles/
. - Конечную точку можно интерпретировать как действие над ресурсом. Например,
POST: /articles
Может означать «создать новую статью». - В бизнесе мы часто можемглагола такжеCRUD(Добавить, удалить, найти и изменить) Связано с:
GET
от имени Ча,POST
представляет увеличение,PUT
а такжеPATCH
означает изменение (примечание: PUT обычно означает полное обновление, а PATCH — частичное обновление), аDELETE
представляет удаление.
Конечно, вы можете применить все, что предусмотрено протоколом HTTP, к дизайну REST API, но они довольно простые, поэтому важно всегда помнить о них.
2. Не возвращайте обычный текст
Хотя возврат данных в формате данных JSON не требуется спецификацией схемы REST, большинство API-интерфейсов REST следуют этому правилу.
Однако недостаточно просто вернуть данные в формате данных JSON, вам также необходимо указать заголовок возвращаемого тела, напримерContent-Type
, значение которого должно быть указано какapplication/json
. Это особенно важно для программных клиентов (например, черезrequests
модули для взаимодействия с API) — от этого заголовка зависит, правильно ли эти программы декодируют возвращаемые данные.
Примечание: Вообще говоря, для браузеров это не кажется проблемой, потому что браузеры обычно имеют свой собственный механизм сниффинга контента, но для согласованности лучше установить этот заголовок в ответе.
3. Избегайте использования глаголов в URI
Если вы поняли, что передала передовая практика № 1, теперь вы понимаетене хочуПоместите глагол в URI REST API. Это связано с тем, что глаголов HTTP достаточно для описания операций бизнес-логики, выполняемых над ресурсами.
Например, если вы хотите предоставить интерфейс, который предоставляет изображение баннера для статьи и возвращает его, вы можете реализовать интерфейс в следующем формате:
GET: /articles/:slug/generateBanner/
Здесь GET уже объяснил, что этот интерфейс делаетчитатьТаким образом, операцию можно упростить до:
GET: /articles/:slug/banner/
Аналогично, если порт для создания статьи:
// 不要这么做
POST: /articles/createNewArticle/
// 这才是最佳实践
POST: /articles/
Попробуйте использовать HTTP-глаголы для описания задействованных операций бизнес-логики.
4. Используйте существительные во множественном числе для описания ресурсов.
Иногда возникают определенные трудности при использовании множественного или единственного числа ресурсов, например, использование/article/:id/
лучше или использовать/articles/:id/
лучше?
Здесь я рекомендую последний. Зачем? Потому что форма множественного числа может удовлетворить потребности всех типов конечных точек.
единственное числоGET /article/2/
Он по-прежнему выглядит хорошо, но если этоGET /article/
Шерстяная ткань? Можете ли вы определить, возвращает ли интерфейс статью или несколько статей, просто по буквальной информации?
Поэтому, чтобы избежать двусмысленности, вызванной именованием в единственном числе, и сохранить максимально возможную согласованность, используйте формы множественного числа, такие как:
GET: /articles/2/
POST: /articles/
...
5. Верните детали ошибки в ответ
Когда сервер API обрабатывает ошибки, если возвращенное тело JSON может включать информацию об ошибке, это в определенной степени поможет вызывающим интерфейс объектам отладки. Например, для общей формы отправки при появлении следующего сообщения об ошибке:
{
"error": "Invalid payoad.",
"detail": {
"surname": "This field is required."
}
}
Вызывающий интерфейс быстро понимает, почему произошла ошибка.
6. Будьте осторожны с кодами состояния
Это, наверное, самое главное, самое главное, самое главное и, наверное, единственное, что вам нужно иметь в виду в этой статье.
Вы, наверное, знаете, что в HTTP вы можете вернуть ответ об ошибке с кодом состояния 200, но это довольно плохо. Не делайте этого, вы должны вернуть тот же тип, что и возвращаемая ошибкаКод состояния с некоторым значением.
Проницательный читатель может сказать, что я следую пункту 5 передовой практики, чтобы предоставить достаточно подробностей, не так ли? Конечно, но позвольте мне рассказать историю:
Однажды я использовал API, и для всех ответов, которые он возвращал, код состояния был200 OK
, при передаче данных ответа вstatus
поле, чтобы указать, успешно ли выполнен текущий запрос, например:
{
"status": "success",
"data": {}
}
Таким образом, пока код состояния200 OK
, но я не совсем уверен, что запрос прошел успешно, на самом деле при возникновении ошибки API возвращает ответ следующего вида:
HTTP/1.1 200 OK
Content-Type: text/html
{
"status": "failure",
"data": {
"error": "Expected at least two items in list."
}
}
голова неподвижнаtext/html
, потому что он также возвращает некоторые фрагменты HTML.
Из-за этого я должен проверить правильность кода состояния ответа, но также необходимо проверить это особое значениеstatus
Значение поля, вы можете безопасно обрабатывать возвращенный ответdata
.
Настоящим недостатком этого дизайна является то, что он разрушает «доверие» между интерфейсом и вызывающим абонентом, потому что вы можете беспокоиться о том, что интерфейс вам лжет (примечание: подразумевается, что, поскольку специальные поля могут изменяться, добавляя ненадежность).
Итак, используйте правильный код состояния и возвращайте сообщения об ошибках только в теле ответа и устанавливайте правильные заголовки, например:
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": "Expected at least two items in list."
}
7. Сохраняйте код состояния согласованным
Как только вы освоите правильное использование кодов состояния, вы должны стремиться сделать их согласованными.
Например, если конечная точка типа POST возвращает201 Created
, то все конечные точки POST должны возвращать один и тот же код состояния. Преимущество этого в том, что вызывающей стороне не нужно заботиться о том, чтобы код состояния, возвращаемый конечной точкой, зависел от специального условия, которое формирует согласованность. Если есть особые случаи, укажите их на видном месте в документации.
Вот коды состояния, которые я рекомендую в соответствии с глаголами:
GET: 200 OK
POST: 201 Created
PUT: 200 OK
PATCH: 200 OK
DELETE: 204 No Content
8. Не вкладывайте ресурсы
Используйте REST API для получения данных о ресурсах, обычно прямое получение нескольких или отдельных, но когда нам нужно получитьСвязанныйресурсы, что делать?
Например, мы ожидаем получить список статей, автором которых является автор — скажем, автора.id=12
. Здесь есть два варианта:
Первое решение описывается размещением вложенного ресурса после связанного ресурса в URI, например:
GET: /authors/12/articles/
Причина, по которой некоторые люди рекомендуют этот подход, заключается в том, что эта форма URI описывает в некоторой степени отношение «один ко многим» между автором и статьей. Но в то же время, в сочетании с пунктом 4 передовой практики, мы не можем различить, являются ли данные, возвращаемые текущей конечной точкой, типом автора или типом статьи.
Вот статьястатья, уточняет, что плоская форма лучше вложенной формы, поэтому должен быть лучший способ, который является вторым вариантом ниже:
GET: /articles/?author_id=12
Вы можете напрямую извлечь логику фильтрации статей в строки запросов.По сравнению с предыдущими, такие URI более четко описывают значение «получить все статьи с автором (id = 12)».
9. Изящно обрабатывать косые черты
Не стоит обсуждать, должен ли хороший URI включать косую черту в конце, просто выберите более предвзятый стиль и соблюдайте его согласованность, а также предоставьте ответ перенаправления, когда клиент неправильно использует косую черту в конце.
Расскажу еще одну свою историю. На днях я интегрировал конечную точку API в проект, но продолжал получать500 Internal Error
Ошибка конечной точки, которую я вызываю, выглядит примерно так:
POST: /entities
После отладки в течение некоторого времени я чуть не разбился, потому что понятия не имел, что делаю неправильно, пока не обнаружил, что сервер выдает ошибку 500, потому что я небрежно уронил завершающую косую черту (примечание: этот опыт случается со всеми, с кем я сталкивался, У меня были подобные проблемы бесчисленное количество раз на SF), когда я изменил URI на:
POST: /entities/
После этого все работало нормально.
Конечно, большинство веб-фреймворков изящно обрабатывают и предоставляют параметры настройки того, содержит ли URL-адрес завершающую косую черту, и, если вы можете, найти ее и включить.
10. Используйте строку запроса для завершения фильтрации и пейджинга
В большинстве случаев простая конечная точка не может удовлетворить ответственный бизнес-сценарий.
Ваши пользователи могут захотеть получить определенные наборы данных, соответствующие определенным условиям, и для обеспечения производительности получить только подмножество этого набора. Другими словами, это обычно называютфильтрфункция инумерация страницФункция:
- Фильтрация: пользователи могут предоставлять дополнительные свойства для управления сбором возвращаемых данных.
- Разбиение по страницам: получение подмножества набора данных. Простейшее разбиение по страницам основано на количестве страниц. Оно состоит из
page
а такжеpage_size
решать
Итак, вопрос в том, как объединить эти две возможности с RESTful API?
Ответ, конечно, черезquerystring. Для пагинации, очевидно, более уместно использовать этот метод, например:
GET: /articles/?page=1&page_size=10
Но для фильтрации вы можете совершать проблемы, указанные в пункте 8 передовой практики, такие как получение списка статей, которые находятся в опубликованном состоянии:
GET: /articles/published/
В дополнение к проблемам, затронутым ранее, здесь также возникает проблема дизайна, котораяpublishedЭто не сам ресурс, это просто характеристика ресурса, аналогичная этому полю характеристики, они должны быть размещены в строке запроса:
GET: /articles/?published=true&page=2&page_size=20
Изящнее и понятнее, не правда ли?
11. Различайте 401 и 403
Когда мы сталкиваемся с ошибками, связанными с безопасностью в API, легко спутать эти два разных типа ошибок.Сертификацияа такжеРазрешить(например, связанные с разрешениями) - я, честно говоря, сам сильно запутался.
Вот мое собственное резюме памятки, объясняющее, как я различаю их в практической ситуации:
- Пользователь не предоставил учетные данные для аутентификации? Сертификация еще актуальна? Этот тип ошибки обычно не аутентифицируется (
401 Unauthorized
). - Пользователь правильно аутентифицирован, но не имеет необходимых разрешений для доступа к ресурсу? Это вообще недопустимо(
403 Forbidden
)
12. Используйте 202 Принято
я нашел202 Accepted
в некоторых случаях201 Created
Очень удобная альтернатива , значение этого кода состояния:
Сервер принял ваш запрос, но новых ресурсов пока не создано, но все в нормальном состоянии.
Делюсь двумя особенно подходящими для использования202 Accepted
Бизнес-сценарии кода состояния:
- Если ресурс создается после последовательности обработки в будущем, например, когда задание завершается
- Если ресурс уже существует, но это идеально и поэтому не должно быть признано ошибкой
13. Используйте платформу настройки REST API
В качестве последнего передового опыта давайте рассмотрим вопрос: как вы внедряете передовой опыт в свою реализацию API?
Часто бывает так, что вы хотите быстро создать API, чтобы некоторые службы могли обращаться друг к другу. Разработчики Python могут сразу отказаться от Flask, а разработчики JS не должны отставать и предлагать Express, который они будут использовать для реализации некоторых простых маршрутов для обработки HTTP-запросов.
Но проблема с этим в том, что, как правило, веб-фреймворков специально для создания сервисов REST API не существует, другими словами, Flask и Express — это два очень общих фреймворка, но они не особо подходят для построения сервисов REST API. Таким образом, вам нужно предпринять дополнительные шаги для реализации лучших практик в вашем API, но в основном лень или ограничения по времени означают, что вы не прилагаете слишком много усилий в этих областях, а затем вашим пользователям предоставляется причудливая конечная точка API.
Решение очень простое: если рабочий хочет хорошо работать, он должен сначала наточить свой инструмент, а освоить и использовать правильную работу — лучшее решение. На разных языках появилось много новых платформ, предназначенных для создания сервисов REST API, которые могут помочь вам легко выполнять задачи, не жертвуя производительностью, следуя передовым методам. В Python одна из лучших платформ API, которые я нашел, этоFalcon. Это так же просто, как Flask, очень эффективно и идеально подходит для создания сервисов REST API. Если вы предпочитаете Django, используйтеDjango REST FrameworkДостаточно, хотя фреймворк не такой уж интуитивно понятный (примечание: по моему пониманию, следует сказать, что начать работу непросто, но я так не думаю), но он очень мощный. В NodeJS,RestifyТоже неплохой вариант, хотя еще не пробовал. Я настоятельно рекомендую вам дать этим фреймворкам шанс! Они помогут вам создавать канонические, элегантные и хорошо продуманные сервисы REST API.
Суммировать
Мы все должны стремиться к тому, чтобы обращение к API доставляло удовольствие. Надеюсь, эта статья дала вам несколько советов и советов по созданию лучших сервисов REST API. На мой взгляд, эти лучшие практики следует свести к трем пунктам: хорошая семантика, краткость и рациональность.
Подписывайтесь на официальный аккаунт Full Stack 101, говорите только о технологиях, а не о жизни