Руководство программиста по api

Значение интерфейсов прикладного программирования(API) в разработке программного обеспечения трудно переоценить. API превратились в незаменимые строительные блоки, позволяющие разработчикам создавать многофункциональные, универсальные и масштабируемые приложения. Цель данного руководства — обеспечить глубокое погружение в разработку API, чтобы дать возможность как начинающим, так и опытным разработчикам использовать весь потенциал API в своих проектах.

В этом обширном руководстве будут рассмотрены основные аспекты разработки API, включая концепции, типы и протоколы, а также лучшие практики и доступные инструменты. Мы начнем с демистификации роли API в современной разработке программного обеспечения, объясняя, как они способствуют беспрепятственной связи между различными компонентами программного обеспечения. Затем мы рассмотрим различные типы API, такие как RESTful, GraphQL и SOAP, изучим их уникальные характеристики и идеальные случаи использования.

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

Что такое API и почему он важен?

Интерфейс прикладного программирования (API) — это структурированный набор протоколов, процедур и инструментов, который обеспечивает беспрепятственную связь между различными программными приложениями. API выступают в роли посредника, позволяя разработчикам использовать готовые функциональные возможности или услуги, предоставляемые сторонними системами, не вникая в основную кодовую базу. Значение API в современной разработке программного обеспечения невозможно недооценить.

no-code API

Они способствуют модульности, эффективности и масштабируемости, позволяя разработчикам опираться на существующие компоненты, ускоряя циклы разработки и сокращая время выхода на рынок. Кроме того, API способствуют взаимодействию между разрозненными системами, обеспечивая беспрепятственную интеграцию и обмен данными между разнородными средами. API служат жизненно важным стержнем в экосистеме программного обеспечения, устраняя разрыв между приложениями и стимулируя инновации благодаря сотрудничеству и совместному использованию ресурсов.

Терминология разработки API

В сфере разработки API существует несколько ключевых терминов, с которыми необходимо быть знакомым для обеспечения эффективного общения и понимания. Ниже приведены некоторые основные термины и понятия:

  • Конечная точка API: Конкретный URL или адрес, по которому API получает запросы и отправляет ответы. Конечные точки обычно организованы вокруг ресурсов, таких как пользователи или продукты.
  • HTTP-методы: Стандартные глаголы HTTP, такие как GET, POST, PUT, PATCH и DELETE, которые используются для выполнения операций CRUD (создание, чтение, обновление и удаление) над ресурсами через API.
  • Запрос и ответ: Фундаментальные компоненты взаимодействия API, когда клиент отправляет запрос API, а API обрабатывает его и возвращает ответ, часто в форматах JSON или XML.
  • REST (Representational State Transfer): Популярный архитектурный стиль для разработки сетевых приложений. RESTful API используют методы HTTP, придерживаются принципов связи без статического состояния и используют единый интерфейс для улучшения масштабируемости и удобства обслуживания.
  • JSON (JavaScript Object Notation): Легкий, человекочитаемый формат обмена данными, обычно используемый в API-коммуникациях для структурирования данных в виде пар ключ-значение.
  • Аутентификация и авторизация: Механизмы безопасности, используемые в API для проверки личности клиентов и определения их привилегий доступа к ресурсам.
  • API-ключ: Уникальный идентификатор, используемый для аутентификации пользователя, разработчика или приложения, выполняющего запрос API, обычно предоставляемый поставщиком API.
  • Ограничение скорости: Метод контроля клиентских запросов к API в определенные временные рамки для предотвращения злоупотреблений и обеспечения справедливого использования.
  • Документация API: Всесторонние, хорошо структурированные руководства, предоставляющие подробную информацию о функциональности API, конечных точках и примерах использования, помогающие разработчикам понять и эффективно интегрировать API.
  • Версионирование API: Управление изменениями и обновлениями API с течением времени, что позволяет разработчикам поддерживать обратную совместимость и вводить новые функции без нарушения существующих интеграций.

Работа API

API служат в качестве посредников, обеспечивающих бесперебойную связь и обмен данными между программными приложениями. Процесс начинается с того, что клиент, например, мобильное приложение или веб-приложение, инициирует запрос к API. Этот запрос содержит важную информацию, такую как конечная точка API, метод HTTP, а также, если требуется, учетные данные аутентификации и полезную нагрузку данных.

Получив запрос, сервер API обрабатывает его на основе заранее определенных правил. Это может включать маршрутизацию запроса в соответствующую службу, проверку данных и применение соответствующей бизнес-логики. Затем сервер API связывается с необходимыми внутренними службами для выполнения запроса, которые могут включать запросы к базе данных, взаимодействие со сторонними службами или другие внутренние службы.

Внутренние службы обрабатывают данные и выполняют запрошенные операции, такие как создание, обновление или извлечение ресурсов. После обработки данных сервер API подготавливает ответ, обычно преобразуя данные в стандартный формат, например JSON или XML. Затем сервер API отправляет ответ обратно клиенту, включая коды состояния, указывающие на результат запроса, например, успех, неудачу или ошибки.

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

Попробуйте no-code платформу AppMaster

AppMaster поможет создать любое веб, мобильное или серверное приложение в 10 раз быстрее и 3 раза дешевле

Начать бесплатно

Лучшие практики для создания правильного API

Создание правильного API требует соблюдения лучших практик, которые способствуют поддержке, масштабируемости и удобству использования. Очень важно тщательно спланировать и спроектировать API перед его разработкой. Вы можете создать хорошо структурированный и перспективный API, определив целевую аудиторию, сценарии использования и ресурсы, которые он будет предоставлять.

Принятие архитектурного стиля REST очень важно, так как это гарантирует, что ваш API будет придерживаться принципа связи без статического состояния, использовать методы HTTP надлежащим образом и использовать единый интерфейс. Это облегчает его понимание и интеграцию. Используйте четкие, краткие, последовательные соглашения об именовании конечных точек, параметров и ресурсов, чтобы улучшить читаемость и понятность.

Версионность API позволяет управлять изменениями и обновлениями с течением времени, обеспечивая обратную совместимость и вводя новые функции без нарушения существующих интеграций. Реализация пагинации является ключевой для API, возвращающих большие наборы данных, поскольку она возвращает данные небольшими фрагментами, улучшая время отклика и снижая нагрузку на клиент и сервер.

Защита API с помощью надлежащих механизмов аутентификации и авторизации, таких как API-ключи, OAuth или JWT, необходима для защиты ресурсов и контроля доступа. Ограничение скорости помогает контролировать количество запросов, которые клиент может отправить в определенный промежуток времени, предотвращая злоупотребления и обеспечивая справедливое использование.

Предоставление четких и информативных сообщений об ошибках с соответствующими кодами состояния HTTP позволяет разработчикам более эффективно диагностировать и решать проблемы. Предоставление полной, хорошо структурированной и актуальной документации по API помогает разработчикам понять и эффективно интегрировать ваш API.

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

Стоимость разработки API

Стоимость разработки API может значительно варьироваться в зависимости от множества факторов. Одним из таких факторов является сложность и функциональность API, поскольку более сложные API с широким спектром функциональных возможностей требуют дополнительного времени и усилий для проектирования, реализации и тестирования. Технологический стек, включающий языки программирования, фреймворки и инструменты, также может повлиять на общую стоимость, поскольку некоторые технологии могут потребовать специальных знаний или более высоких лицензионных отчислений.

Интеграционные требования также играют свою роль, поскольку API, требующие интеграции со сторонними сервисами, базами данных или другими системами, требуют дополнительной работы для обеспечения бесперебойной связи и обмена данными. Обеспечение соответствия API стандартам безопасности и отраслевым нормам, таким как GDPR или HIPAA, может увеличить стоимость разработки за счет внедрения мер безопасности, шифрования и аудита.

Создание исчерпывающей документации, предоставление поддержки и текущее обслуживание, включая исправление ошибок, обновление и расширение функциональности, — все это влияет на общую стоимость разработки API. Кроме того, выбор между разработкой собственными силами и передачей стороннему агентству или внештатному сотруднику может повлиять на стоимость, при этом аутсорсинг потенциально снижает накладные расходы и обеспечивает доступ к специализированным знаниям. В отличие от этого, разработка собственными силами может обеспечить лучший контроль над процессом разработки.

Учитывая эти переменные, определить конкретную стоимость разработки API довольно сложно. Стоимость простого API может составлять от $5 000 до $15 000, в то время как стоимость более сложного API может превысить $50 000 или даже $100 000, в зависимости от требований и задействованных ресурсов. Стоимость разработки API в конечном итоге должна оцениваться в каждом конкретном случае с учетом уникальных потребностей и ограничений каждого проекта.

Каждому ли предприятию нужен API?

Хотя API может понадобиться не каждому предприятию, растущие потребности в подключении, автоматизации и обмене данными в цифровую эпоху делают API ценным активом для многих организаций. Решение о разработке API зависит от различных факторов, включая характер бизнеса, его цели и цифровую стратегию. Вот некоторые сценарии, в которых API может быть полезен для бизнеса:

  • Интероперабельность: Если предприятие полагается на несколько программных приложений для связи и обмена данными, API может облегчить бесшовную интеграцию и повысить эффективность работы.
  • Автоматизация: API позволяют автоматизировать повторяющиеся задачи и оптимизировать рабочие процессы, что позволяет сэкономить время, уменьшить количество человеческих ошибок и повысить производительность.
  • Расширение экосистемы: Для компаний, предлагающих цифровые продукты или услуги, API могут помочь расширить сферу своего влияния, позволяя сторонним разработчикам создавать приложения, которые интегрируются с их услугами, способствуя инновациям и создавая новые потоки доходов.
  • Сотрудничество с партнерами: API могут упростить сотрудничество с партнерами, поставщиками или клиентами, предоставляя стандартизированный и безопасный способ доступа к данным и обмена ими, уменьшая трения и улучшая деловые отношения.
  • Масштабируемость: По мере роста бизнеса возрастает потребность в лучшем управлении данными и более эффективных процессах. API могут улучшить масштабируемость за счет модульного построения функциональных возможностей и обеспечения беспрепятственного взаимодействия между различными системами.
  • Конкурентное преимущество: В некоторых отраслях наличие API может стать конкурентным преимуществом, позволяя компаниям предоставлять улучшенные услуги, повышать качество обслуживания клиентов и предлагать инновационные решения.

В конечном итоге, решение о разработке API должно основываться на тщательном анализе потребностей, целей и цифровой стратегии компании, взвешивании потенциальных выгод и необходимых инвестиций.

Что необходимо учитывать при создании API

При создании API необходимо учитывать различные факторы, влияющие на его успех, удобство использования и поддерживаемость. Начните с четкого определения цели вашего API и его целевой аудитории, что поможет определить необходимую функциональность, ресурсы и структуры данных для создания целенаправленного и хорошо структурированного API. Примите последовательный и интуитивно понятный дизайн, придерживаясь установленных архитектурных принципов, таких как REST, используя осмысленные соглашения об именовании и логическую иерархию ресурсов и конечных точек. Выберите подходящие форматы данных для обмена данными, например, JSON или XML, и рассмотрите возможность использования общепринятых отраслевых стандартов для улучшения совместимости и простоты интеграции.

Попробуйте no-code платформу AppMaster

AppMaster поможет создать любое веб, мобильное или серверное приложение в 10 раз быстрее и 3 раза дешевле

Начать бесплатно

Оптимизируйте API для производительности и масштабируемости, обеспечивая быстрое время отклика и способность обрабатывать многочисленные запросы. Внедрите кэширование, пагинацию и ограничение скорости для управления нагрузкой на сервер и повышения производительности. Безопасность имеет решающее значение, поэтому интегрируйте надежные механизмы аутентификации и авторизации для защиты API от несанкционированного доступа и злоупотреблений. Шифруйте передаваемые данные и следуйте лучшим практикам для обеспечения конфиденциальности и безопасности данных.

Предоставляйте четкие и информативные сообщения об ошибках с соответствующими кодами состояния HTTP для эффективной диагностики и решения проблем. Разработайте полную, актуальную и легкодоступную документацию, которая охватывает все аспекты вашего API, включая конечные точки, форматы данных, аутентификацию и примеры использования. Тестирование и мониторинг жизненно важны во время разработки и после развертывания. Используйте инструменты автоматизированного тестирования и решения для мониторинга, чтобы обнаруживать и устранять проблемы заранее. Планируйте будущие изменения и обновления API путем внедрения версионности, что позволит вводить новые функции и улучшения без нарушения существующих интеграций.

Наконец, сосредоточьтесь на обеспечении положительного опыта для разработчиков, который включает в себя простые в использовании конечные точки, понятную документацию и отзывчивую поддержку. Отличный опыт разработчиков будет способствовать принятию и интеграции вашего API. Учет этих факторов в процессе разработки API поможет создать надежный, удобный и поддерживаемый API, который будет отвечать потребностям разработчиков и конечных пользователей, обеспечивая долгосрочный успех и адаптируемость.

Инструменты для создания API без кода

По мере роста потребности в эффективных и масштабируемых программных решениях в качестве популярной альтернативы для создания API без написания кода появились инструменты no-code. Эти инструменты позволяют нетехническим пользователям создавать и управлять API, что дает им возможность использовать данные и создавать приложения более эффективно. Вот несколько заслуживающих внимания инструментов для создания API без кода:

AppMaster

no-code solutions

AppMaster — это мощная платформа, позволяющая пользователям создавать и управлять API, веб-приложениями и мобильными приложениями без знаний кодирования. Платформа предлагает широкий спектр компонентов и интеграций, позволяя пользователям создавать пользовательские API, отвечающие их требованиям. Интуитивно понятный интерфейс с перетаскиванием и визуальными рабочими процессами упрощает разработку, тестирование и развертывание API.

Sparklite

Sparklite — это инструмент разработки API без кода, который упрощает создание, развертывание и поддержку API. Он предлагает удобный интерфейс и коллекцию готовых модулей, которые можно легко настроить для создания пользовательских API. Визуальный редактор Sparklite позволяет пользователям определять конечные точки API, структуры данных и бизнес-логику без написания единой строки кода, что обеспечивает быструю разработку и развертывание API.

Sheetsu

Sheetsu — это уникальный инструмент, не требующий написания кода, который превращает Google Sheets в полнофункциональные API. Пользователи могут создавать, читать, обновлять и удалять данные непосредственно в Google Sheets, что позволяет им создавать приложения и интеграции без написания кода. Sheetsu предлагает простой процесс настройки, что делает его идеальным решением для малого бизнеса, стартапов и частных лиц, желающих использовать возможности API без вложения значительных средств в разработку.

Airtable

Airtable — это гибкая платформа без кода, которая сочетает в себе функциональность электронных таблиц и баз данных. Пользователи могут создавать пользовательские API, создавая базы Airtable, по сути, структурированные базы данных с богатыми типами полей и настраиваемыми представлениями. Airtable предоставляет автоматически создаваемый API для каждой базы, позволяя пользователям интегрировать свои данные с другими приложениями, сервисами или инструментами без кодирования.

Bubble

Bubble — это универсальная платформа без кода, предназначенная для создания веб-приложений и API. Она обладает широкими возможностями, включая визуальный редактор, готовые плагины и мощный механизм рабочего процесса, который позволяет пользователям создавать пользовательские API и логику без написания кода. Удобный интерфейс Bubble и широкие возможности настройки делают его идеальным решением для предприятий и частных лиц, желающих быстро и эффективно разрабатывать API и приложения.

В заключение

Появление инструментов для создания API без кода демократизировало мир разработки программного обеспечения, предоставив частным лицам и компаниям возможность использовать возможности API без обширных технических знаний и ресурсов. Эти инновационные платформы, такие как AppMaster, Sparklite, Sheetsu, Airtable и Bubble, предоставляют удобные интерфейсы и широкие возможности настройки, позволяя пользователям создавать пользовательские API в соответствии со своими потребностями. Используя эти инструменты, компании могут оптимизировать рабочие процессы, улучшить взаимодействие и ускорить внедрение инноваций, что в конечном итоге способствует росту и успеху в цифровую эпоху. Ожидается, что по мере того, как движение «без кода» будет набирать обороты, появятся еще более мощные и универсальные инструменты, которые еще больше упростят разработку API и позволят более широкой аудитории внести свой вклад в постоянно развивающийся ландшафт разработки программного обеспечения.

На чтение 6 мин. Просмотров 42 Опубликовано

Ранее в разделе “Введение в API” мы обсуждали, что API – это конструкции, доступные в языках программирования, позволяющие разработчикам легко создавать сложные функциональные возможности. Теперь, когда у нас есть четкое понимание API, давайте рассмотрим, как с ними работать.

В прошлый раз мы сделали следующий запрос:

# Defining method (X), and headers (H):
cURL -X GET 'https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY' -H 'Host: api.nasa.gov' -H 'Accept: text/html,application/xhtml+xml,application/xml'

# Or, alternatively can also be written verbose

# Using long form options
# Splitting cURL commands across multiple lines
# Line continuation character is represented in cURL by ``

cURL 
--request GET 'https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY' 
--header 'Host: api.nasa.gov' 
--header 'Accept: text/html,application/xhtml+xml,application/xml'

Войти в полноэкранный режим Выйти из полноэкранного режима

Обратите внимание, что приведенный выше код не является JavaScript, и он выглядит иначе, чем код из нашего предыдущего примера. Он начинается с cURL (для клиентского URL), который представляет собой инструмент командной строки, используемый разработчиками для передачи данных.

В итоге, ознакомьтесь с cURL. На самом фундаментальном уровне cURL позволяет вам (а) разговаривать с сервером, (б) поддерживает несколько различных протоколов и (в) работает на различных платформах. Все это делает cURL идеальным для тестирования связи из любого места, где есть доступ к командной строке и сетевому соединению. Подробнее о том, что делает cURL, здесь, а о документации cURL – здесь.

Содержание

  1. Инструментарий cURL
  2. Использование Postman
  3. Отправка первого запроса
  4. Создание HTTP-запроса с помощью cURL и Postman
  5. Методы HTTP-запросов
  6. Коллекции Postman
  7. Экспорт данных Postman
  8. Заключение

Инструментарий cURL

Какие инструменты мы можем использовать для тестирования различных веб-сервисов перед созданием API-интеграций? Я рекомендую следующие инструменты, которые мы будем использовать сегодня:

  • Postman: для тестирования веб-сервисов и генерации cURL сниппетов (и для нескольких других языков).
  • cURL Converter (опционально): для преобразования команд cURL в JavaScript (и для некоторых других языков).

Итак, в этот раз давайте начнем использовать cURL для представления вызовов API, с которыми мы будем работать с помощью Postman (платформа для создания и использования API).

Использование Postman

Отправка первого запроса

Postman позволяет легко создавать и отправлять API-запросы. Вам не нужно вводить команды в терминале или писать какой-либо код. В его графическом интерфейсе достаточно просто создать новый запрос (например, используя данные из фрагмента cURL) и нажать кнопку Send. Ответ API появляется прямо внутри Postman.

Если вы никогда раньше не пользовались Postman, давайте сделаем это шаг за шагом.

Как войти в Postman:

  1. Войдите с помощью Google (или электронной почты/имени пользователя) в Postman
  2. Заполните информацию о пользователе (имя и роль, John Doe, Fullstack Developer).
  3. Продолжить без команды

Создание HTTP-запроса с помощью cURL и Postman

Итак, давайте возьмем наш фрагмент cURL и импортируем его в Postman. Чтобы сделать это:

  1. В личном рабочем пространстве нажмите на иконку + New HTTP Request, чтобы сразу же отправить запрос. В качестве альтернативы, используйте инструмент Импорт и вставьте фрагмент cURL, представленный выше, чтобы сэкономить время,
  2. Если вы импортируете (если нет, пропустите этот шаг), появится модальное/всплывающее окно, в котором вы импортируете спецификации API как Raw Text, нажмите Continue и подтвердите, нажав Import.
  3. Нажмите на Отправить и
  4. Просмотрите ответ прямо в Postman.

Примечание: Импорт API – это отличная функция, позволяющая импортировать существующую схему API из локального файла, каталога, URL, необработанного текста, хранилища кода или даже API-шлюза. Это полезно знать, поскольку Postman позволяет импортировать и экспортировать данные, чтобы помочь вам консолидировать рабочий процесс разработки API.

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

Методы HTTP-запросов

Как мы уже говорили, архитектурный стиль REST использует все преимущества HTTP, поэтому, в свою очередь, любой RESTful API также унаследует их. На самом базовом уровне запрос API включает в себя URL конечной точки ресурса и метод запроса HTTP. Метод запроса HTTP (также называемый HTTP-глаголами) указывает на желаемое действие, которое вы хотите выполнить для данного ресурса.

Все методы HTTP-запросов имеют общие черты: они безопасны, идемпотентны и кэшируемы. Рассмотрим наиболее распространенные методы:

  • GET извлекает данные из API
  • POST отправляет новые данные в API
  • PATCH и PUT обновляют существующие данные
  • DELETE удаляет существующие данные

Давайте изучим эти методы HTTP с помощью нашей первой коллекции Postman.

Коллекции Postman

Это группа сохраненных запросов. Чем больше вы используете Postman, тем больше времени отнимает необходимость оставлять открытыми вкладки для запросов, искать их в разделе истории или создавать их заново. Вместо этого вы можете сохранить все свои запросы, упорядочить их и поделиться ими в виде коллекции Postman.

Вы можете создать коллекцию следующим образом:

  • Сохранив один запрос и воспользовавшись быстрой ссылкой Новая коллекция во всплывающем окне/модальном меню ИЛИ
  • нажав на значок + на вкладке Обзор (левое меню) вашего рабочего пространства.

Теперь, когда вы знаете, как создать коллекцию Postman, давайте быстро обсудим, как поделиться результатами работы Postman.

Экспорт данных Postman

Вы можете экспортировать свои коллекции Postman в файлы JSON для последующего использования из любого экземпляра Postman или использовать их с помощью инструмента CLI, например, Newman (инструмент, позволяющий запускать коллекции Postman из командной строки). Нажмите на Export или Share в любом месте папки с коллекцией. Отсюда у вас есть следующие возможности:

  • Отправить коллекцию по электронной почте для совместной работы (аналогично предыдущему варианту экспорта).
  • Экспорт в виде файла JSON
  • Через JSON ссылку, которая генерирует статический снимок вашей коллекции (подобно тому, что я предоставил ранее).

Заключение

Postman имеет более 135 тысяч опубликованных коллекций, которые вы можете использовать для изучения нескольких различных API. Компании активно используют Postman не только для разработки и тестирования своих API, но и для быстрого создания прочной базы документации и предоставления ее миру. Для всех публичных коллекций Postman существуют категории AI, Communication, Data Analytics, Developer Productivity, DevOps, Financial Services, поэтому обязательно ознакомьтесь с ними и продолжайте учиться работать с API.

ПРИМЕЧАНИЕ: Эта статья относится к продолжающемуся циклу статей, который все еще находится в процессе работы. Если вы еще не читали, ознакомьтесь с частью 1: Введение в API. Часть 3: Руководство для начинающих по тестированию API.

Спасибо за прочтение.

Edit me

После раздела «Обзор API» обычно идет раздел «Начало работы», в котором подробно описываются первые шаги, которые пользователи должны пройти для использования API. Этот раздел часто включает весь процесс от начала до конца, сжатый настолько просто, насколько это возможно.

Цель раздела “Начало работы”

Раздел «Начало работы» это как Hello World для разработчиков, только с API. “Начало работы” ведет за руку пользователя от начала до конца при создании простейшего возможного вывода с системой. Для Hello World самым простым выводом является сообщение «Hello World». Для API это может быть успешный ответ на самый простой запрос.

time

Раздел «Начало работы» это как `Hello World`, только с API. Сколько времени понадобится разработчику, чтобы получить максимально простой ответ, используя ваш API?

И Hello World и “Начало работы” преследуют одну и ту же цель: показать пользователю, как использовать инфраструктуру, API или какую-либо другую систему, для получения простого и легкого результата, чтобы пользователи получили полное представление о работе системы, API и т.д.

В качестве примера можно взять общий базовый сценарий использования API и показать, как создать запрос, а также какой ответ возвращается. Если разработчик сможет успешно выполнить такой вызов, значит и с остальными не должно возникнуть проблем.

Раздел “Начало работы” может содержать следующие пункты:

  • Войти в аккаунт;
  • Получить API ключ;
  • Создание запроса
  • Оценка ответа.

get_start

Раздел ‘Начало работы’ обычно знакомит пользователей с процессом от начала до конца, но сжатым и простым способом.

Поместите ссылку на раздел “Начало работы” на домашней странице документации. Сделайте так, чтобы разработчики могли с легкостью использовать API для получения определенного результата. Если подразумевается использование предварительно подготовленных учетных записей или конфигураций настройки, нужно продумать и это.

Кнопка Run in Postman

В разделе “Начало работы” можно рассмотреть возможность добавления кнопки Run in Postman. (Postman — это клиент REST API GUI, который мы изучили ранее в разделе Отправка запросов в Postman.) Если есть конечные точки API, интегрированные с Postman, можно экспортировать свои коллекции Postman в виде виджета для встраивания в HTML-страницу.

Run in Postman это кнопка, которая при нажатии импортирует информацию об API в Postman, чтобы пользователи могли выполнять вызовы с помощью клиента Postman. Таким образом, кнопка Run in Postman позволяет импортировать интерактивный пробный интерфейс API для конечных точек на веб-страницу.

Чтобы добавить кнопку Run in Postman, можно импортировать спецификацию OpenAPI в Postman или ввести информацию об API вручную. Стоит изучить раздел “Postman/docs”, как создать кнопку Run in Postman.

Множество демонстраций Run in Postman можно посмотреть здесь. Многие из этих демонстраций перечислены в сети API Postman.

api network

сеть API Postman

Вот демо Run in Postman с использованием конечной точки weather API OpenWeatherMap (с которой мы работали раннее ):

Run in Postman

Если нажать на кнопку, будет предложено открыть коллекцию в клиенте Postman:

open

Вариант открытия коллекции

Postman предоставляет мощный клиент REST API, с которым знакомы многие разработчики. Postman позволяет пользователям настраивать ключ и параметры API и сохранять эти значения. Хотя Postman не имеет возможности вызова в браузере, как в Swagger UI, во многих отношениях клиент Postman более полезен, поскольку позволяет пользователям настраивать и сохранять сделанные ими запросы. Postman — тот инструмент, который внутренние разработчики часто используют для хранения запросов API при тестировании и изучении функциональности.

Особенно, если ваши пользователи уже знакомы с Postman, Run in Postman является хорошим вариантом для пользователей, чтобы опробовать API, потому что он позволяет пользователям легко генерировать необходимый код для отправки запросов практически в любой язык. Это дает пользователям отправную точку, где они могут опираться на информацию для создания более подробных и настраиваемых вызовов.

Если в документации еще нет функции Try it out, кнопка Run in Postman предоставляет такую интерактивность простым способом, не требуя жертв со стороны единственного источника знаний для документации.

Недостатком является то, что в Postman не попадают описания параметров и конечных точек. Кроме того, если пользователи незнакомы с Postman, им может быть трудно понять, как им пользоваться. Редакторы Try it out, которые запускаются непосредственно в браузере, как правило, более просты и лучше интегрируют документацию.

Примеры разделов “Начало работы”

Ниже приведены несколько примеров разделов “Начало работы” в API. Если сравнить различные разделы «Начало работы», можно увидеть, что некоторые из них являются подробными, а некоторые — высокоуровневыми и краткими. В общем, чем дольше можно вести разработчика за руку, тем лучше. Тем не менее, раздел должен быть кратким, а не многословным с другой документацией. Ключевым моментом является то, чтобы показать пользователю полный, от и до, процесс работы с API.

Paypal

Paypal

“Начало работы” Paypal содержит довольно много деталей, начиная с авторизации, запросов и других деталей до первого запроса. Хотя этот уровень детализации не так краток, он помогает сориентировать пользователей на необходимую им информацию. Чистый и понятный формат.

Twitter

twitter

Начало работы в Твиттер

На стартовой странице Twitter есть несколько разделов, посвященных началу работы, для разных целей разработки. Текст лаконичен и понятен. В разделе размещены ссылки на другую документацию для получения более подробной информации. В целях краткости можно следовать такой же стратегии — быть кратким и ссылаться на другие страницы, которые содержат более подробную информацию.

Parse Server

Parse Server

Начало работы Parse Server

Раздел “Начало” работы в Parse Server содержит большое количество деталей и подробное описание различных этапов. Для более подробных шагов по подключению вашего приложения и запуску сервера в другом месте, в разделе размещена ссылка на дополнительную информацию.

Adsense

Adsense

Начало работы Adsense

“Начало работы” Adsense выделяет некоторые основные предпосылки для начала работы на платформе. После того, как вы настроитесь, он предоставляет «краткое руководство по началу работы». Такое руководство знакомит пользователей с простым сценарием от начала до конца, помогая им понять продукт и его возможности.

Aeris

Aeris

Начало работы Aeris

Начало работы в сервисе погоды Aeris предоставляет информацию для настройки приложения, а затем делает запрос на одном из нескольких популярных языков. Хотя показ кода на определенных языках, несомненно, более полезен для программистов, использующих данный язык, примеры кода могут быть неуместны для других пользователей (например, разработчики Java могут найти код Python неуместным, и наоборот). Фокусировка на определенном языке часто является компромиссом.

Watson and IBM Cloud

Watson and IBM Cloud

Начало работы Watson and IBM Cloud

В разделе “Начало работы” Watson и IBM Cloud перечислены три шага. Тем не менее, это не полное руководство по началу работы. Пользователь может только выбрать сервис для своего проекта. В итоге кодировать начинаем с помощью Watson Dashboard.

В идеале, раздел “Начало работы” должен помочь пользователю увидеть ощутимые результаты, но возможно ли это или нет, зависит от API.

👨‍💻 Практическое занятие: Раздел “Начало работы”

В своем найденном опен-сорс проекте найдем раздел “Начало работы” и ответим на следующие вопросы:

  • Есть ли у API раздел “Начало работы”?
  • Описан ли процесс начала работы от и до в разделе?
  • Можно ли успешно выполнить все шаги в разделе?
  • Сколько времени занимает освоение раздела?
  • Отобразятся ли предположения о вашем техническом уровне в документации при попытках упростить инструкцию?

🔙

Go next ➡

В руководстве по HTTP API собрана информация по проектированию, основному функционалу, а также о внутреннем API в Heroku.

Рекомендации по проектированию HTTP API, которые почерпнуты из API облачной платформы Heroku. Здесь вы также найдёте информацию о функционале и внутреннем API в Heroku.

Основными целями при построении HTTP API является соблюдение последовательности и концентрация на реализации бизнес-логики. Мы ищем различные, не обязательно самые лучшие, но хорошо документируемые способы разработки API.

  1. Основы
  2. Запросы
  3. Построение пути к ресурсу
  4. Ответы
  5. Артефакты
  6. Выводы

Основы

Принцип разделения ответственности

При проектировании старайтесь сохранять простоту системы, разделяя ответственность между различными частями цикла «запрос-ответ».  При этом простота принимаемых решений позволит концентироваться на решении все более сложных задач. Запросы и ответы выполняются для получения доступа к определенному ресурсу или набору ресурсов. Для определения сущности, которую необходимо получить, используйте путь и тело ответа для передачи содержимого, а заголовки – для передачи метаданных. Можно передавать все параметры в теле запроса, но, как показывает практика, такое решение является менее гибким. Более правильным подходом будет передача части параметров в заголовках.

Требуйте использования защищенных соединений

Для получения данных с помощью HTTP API используйте только защищенные соединения с TLS. Лучше решением было бы отклонять все запросы, не использующие TLS, а именно запросы по http или на 80-ый порт, во избежание небезопасного обмена данными. В случаях, когда это невозможно, отдавайте ответ 403 Forbidden.

Перенаправления не приветствуются, поскольку они допускают некорректное поведение клиента, не предоставляя при этом никаких четких объяснений. Клиенты, которые полагаются на редиректы, удваивают таким образом трафик сервера и использование TLS в этом случае бесполезно, поскольку важные данные оказываются незащищенными при первом вызове.

Требуйте наличие версии в заголовке Accept

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

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

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

			Accept: application/vnd.heroku+json; version=3
		

Используйте заголовок ETags для кеширования

Включайте заголовок ETags во все запросы, определяя при этом версию возвращаемого ресурса. Это позволит пользователям кэшировать ресурсы и реализовывать условные запросы при помощи использования заголовка If-None-Match, который поможет определить, нужно обновлять кэш или нет.

Используйте Request-ID для интроспекции

Включайте заголовок Request-Id, содержащий в себе UUID значение, в каждый ответ сервера. Регистрируя эти значения на клиенте, сервере или другом сервисе, вы получаете возможность отлаживать и диагностировать проблемы, связанные с запросами.

Разделяйте большие ответы сервера на несколько небольших при помощи заголовка Range

Большие ответы необходимо разбивать на более мелкие, используя заголовок Range. Для получения более детальной информации о заголовках запросов/ответов, кодах состояний и ограничениях изучите использование заголовка Range в API Heroku.

Запросы

Возвращайте соответствующие  коды состояний

Возвращайте соотвествующий код состояния HTTP в каждом ответе. Успешные ответы должны содержать такие коды состояний:

  • 200GET запрос завершился успешно, синхронный DELETE или PATCH запрос завершился успешно или синхронный PUT запрос обновил существующий ресурс.
  • 201 – Синхронный POST запрос завершился, синхронный PUT запрос создал новый ресурс.
  • 202 – Принят POST, PUT, DELETE или PATCH запрос, который будет обработан асинхронно.
  • 206GET запрос завершился успешно, но будет возвращен частичный ответ (см. раздел про заголовок Range).

Обратите внимание на использование кодов состояния ошибок авторизации и аутентификации:

  • 401 Unauthorized – запрос завершился с ошибкой, поскольку пользователь не прошел аутентификацию.
  • 403 Forbidden – запрос завершился с ошибкой, так как пользователь не авторизовался для получения доступа к определенному ресурсу.

Возвращайте соответствующие коды ошибок для предоставления дополнительной информации об их причинах:

  • 422 Unprocessable Entity – Ваш запрос был распознан, но содержит неверные параметры.
  • 429 Too Many Requests – Превышен лимит запросов, попробуйте позже.
  • 500 Internal Server Error – Проблема на стороне сервера, проверьте состояние сайта и/или сообщите о проблеме.

Для получения более подробной информации о кодах состояния HTTP изучите спецификацию.

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

Возвращайте пользователям вашего API полное представление ресурса (то есть объект со всеми атрибутами) во всех ответах, где это возможно. Всегда предоставляйте полную версию ресурса в ответах на запросы с кодами состояния 200 и 201, включая PUT, PATCH и DELETE запросы.

			$ curl -X DELETE \  
  https://service.com/apps/1f9b/domains/0fd4

HTTP/1.1 200 OK
Content-Type: application/json;charset=utf-8
...
{
  "created_at": "2012-01-01T12:00:00Z",
  "hostname": "subdomain.example.com",
  "id": "01234567-89ab-cdef-0123-456789abcdef",
  "updated_at": "2012-01-01T12:00:00Z"
}
		

Ответы на запросы с кодом состояния 202 не должны содержать все поля объекта

			$ curl -X DELETE \  
  https://service.com/apps/1f9b/dynos/05bd

HTTP/1.1 202 Accepted
Content-Type: application/json;charset=utf-8
...
{}
		

API должен принимать сериализованный JSON в теле запроса

И предусматривать возможность передачи сереализованного JSON в теле PUT/PATCH/POST запросов вместо, либо в дополнение к передаваемым данным формы. Таким образом создается симметрия в JSON-ответах:

			$ curl -X POST https://service.com/apps \
    -H "Content-Type: application/json" \
    -d '{"name": "demoapp"}'

{
  "id": "01234567-89ab-cdef-0123-456789abcdef",
  "name": "demoapp",
  "owner": {
    "email": "username@example.com",
    "id": "01234567-89ab-cdef-0123-456789abcdef"
  },
  ...
}
		

Построение пути к ресурсу

Названия ресурсов

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

Действия

Старайтесь проектировать такие конечные url, которые не требуют дополнительных действий для отдельных ресурсов. В случаях, когда это необходимо, добавляйте в общий путь компонент «action» для того, чтобы четко определить эти действия:

Например:

Используйте названия компонентов пути и атрибутов в нижнем регистре

Для названий компонентов пути к ресурсу используйте нижний регистр и разделяйте их при помощи дефиса.

Названия атрибутов лучше писать в нижнем регистре, а в качестве разделителя лучше использовать нижнее подчеркивание – таким образом названия полей можно писать без скобок в Javascript:

API должен поддерживать доступ к ресурсу не только по его ID

В некоторых случаях для конечных пользователей неудобен доступ к ресурсу по его идентификатору. Например, пользователю удобнее для доступа к конкретному приложению Heroku использовать название приложения, а не его UUID. В таких случаях нужно организовать доступ как по имени, так и по идентификатору:

На данный момент этот блок не поддерживается, но мы не забыли о нём!Наша команда уже занята его разработкой, он будет доступен в ближайшее время.

Сведите к минимуму  количество вложений в пути для доступа к ресурсу

В моделях данных, в которых присутствуют родительские отношения между сущностями, пути доступа к ресурсам могут иметь большой уровень вложенности:

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

Ответы

Предоставляйте UUID запрашиваемых ресурсов

У каждого ресурса по умолчанию должен быть атрибут id. В качестве значений идентификатора ресурса старайтесь всегда использовать UUID. Не используйте идентификаторы, которые не будут уникальными в масштабе вашего сервиса, особенно автоинкрементные идентификаторы.
UUID ресурса выводите в формате 8-4-4-4-12:

Предоставляйте информацию о дате создания и изменения ресурса

По умолчанию ресурс должен хранить информацию о дате его создания created_at и обновления updated_at.

Временные величины должны быть форматированы согласно ISO8601

Принимайте и возвращайте временные данные только в UTC, а выводите в формате ISO8601:

			"finished_at": "2012-01-01T12:00:00Z"
		

Отношения с внешними сущностями должны быть вынесены во вложенный объект

Внешние отношения должны быть сериализованы как вложенный объект:

А не как поле объекта:

Такой подход позволяет добавить больше информации о связанном объекте без необходимости менять структуру ответа:

Создавайте структурированные ответы в случае возникновения ошибок

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

Показывайте ограничение по количеству запросов

Ограничение по количеству запросов вводится для поддержания работоспособности системы и возможности качественного обслуживания других клиентов. Для расчета ограничений на количество запросов можно использовать алгоритм текущего ведра. Возвращайте оставшееся количество запросов для каждого запроса в заголовке ответа RateLimit-Remaining.

JSON во всех ответах должен быть минимизирован

Лишний пробел увеличивает размер ответа и многие Javascript клиенты для удобочитаемости автоматически отформатируют JSON. Поэтому лучше минимизировать JSON ответы:

вместо

Вы можете опционально добавить возможность получать более развернутый ответ, указывая дополнительный параметр (например, ?pretty=true) или задавая значения для заголовка Accept (Accept: application/vnd.heroku+json; version=3; indent=4;).

Артефакты

Предоставляйте удобную для обработки JSON-схему

Для точного описания вашего API предоставляйте JSON-схему. Для управления схемой используйте prmd, также удостоверьтесь в том, что она проходит валидацию при помощи команды prmd verify.

Предоставляйте удобочитаемую документацию

Если вы создали JSON-схему, используя prmd, как описано выше, вы можете легко сгенерировать Markdown документацию для всех конечных url, используя команду prmd doc.

Вдобавок к описанию конечных url, предоставьте обзор API, включая туда следующую информацию:

  • процесс аутентификации – получение и использование пользовательского токена;
  • стабильность API и его версию, а также информацию о том, как выбрать нужную версию API;
  • общие заголовки запросов и ответов;
  • формат выдачи ошибки;
  • примеры использования API с клиентами на разных языках;

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

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

Если вы используете prmd для создания документации, то такие примеры будут сгенерированы автоматически для каждого конечного url.

Опишите стабильность вашего API

Вы можете описать степень стабильности API или отдельных конечных url при помощи установки флагов prototype/development/production.

Для получения дополнительной информации, вы можете изучить документ Политика совместимости Heroku API.

Как только вы объявили API готовым к релизу и стабильным, не стоит совершать модификаций, которые нарушают обратную совместимость внутри этой версии. Для внесения таких изменений создайте новою ветвь API с новым индексом версии.

Выводы

Разобрались, что HTTP API позволяет получить программный доступ к функциям некоторых веб-приложений, затронули запросы, ответы и артефакты. Для полного погружения держите советы по разработке REST API.

Перевод статьи «HTTP API Design Guide»

29 июля 2021

11 515

0

Время чтения ≈ 31 минута

Содержание:

  • Что такое REST API
  • Архитектура REST
  • Исходные данные
  • Настройка бэкенда REST API
  • Создание пользовательского модуля
  • Создание модуля «auth»
  • Создание middleware-компонентов разрешений и валидации
  • Запуск и тестирование REST API с Insomnia
  • Следующие этапы

Интерфейсы прикладного программирования или API (Application Programming Interface) применяются в разработке повсеместно. Они позволяют одним программам последовательно взаимодействовать с другими — внутренними или внешними — программными компонентами. Это является ключевым условием масштабируемости, не говоря уже о возможности повторного использования приложений.

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

Применяемый при этом стандарт де-факто называется «передачей состояния представления» (REpresentational State Transfer) или сокращённо REST. Простыми словами, REST API — это набор правил, по которым серверные приложения взаимодействуют с клиентскими.

Для создания простого, но безопасного бэкенда на основе REST API может быть задействовано множество платформ и языков программирования, например ASP.NET Core, Laravel (PHP) или Bottle (Python).

В этой же статье будет использоваться следующий инструментарий:

  • js — как пример распространённой кроссплатформенной среды выполнения JavaScript.
  • Express, который значительно упрощает выполнение основных задач веб-сервера в Node.js и является стандартным инструментом для создания серверной части на основе REST API.
  • Mongoose, который будет соединять наш бэкенд с базой данных MongoDB.

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

Обратите внимание! В рамках инструкции не будет рассмотрена работа с кодовой базой фронтенда. Тем не менее, можно легко использовать код (например, объектные модели на стороне сервера и клиента), так как наш бэкенд написан на JavaScript.

Архитектура REST

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

REST API используются для доступа к данными и их обработки с помощью стандартного набора операций без сохранения состояния. Эти операции являются неотъемлемой частью протокола HTTP. Они представляют собой основные функции создания («create»), чтения («read»), модификации («update») и удаления («delete») и обозначаются акронимом CRUD.

Операциям REST API соответствуют, хотя и не полностью идентичны, следующие методы HTTP:

  • POST (создание ресурса или предоставление данных в целом).
  • GET (получение индекса ресурсов или отдельного ресурса).
  • PUT (создание и замена ресурса).
  • PATCH (обновление/изменение ресурса).
  • DELETE (удаление ресурса).

С помощью этих HTTP-методов и имени ресурса в качестве адреса, мы можем построить REST API, создав конечную точку для каждой операции. В результате мы получим стабильную и легко понятную основу, которая позволит быстро дорабатывать код и осуществлять его дальнейшее сопровождение.

Та же основа будет применяться для интеграции сторонних функций, о которых было сказано чуть выше. Большинство из них тоже использует REST API, что ускоряет такую интеграцию.

Исходные данные

В этом руководстве мы создадим самый простой REST API с нуля для ресурса под названием «users» с помощью Node.js.

У ресурса «users» будет следующая базовая структура:

  • id (UUID, что значит «автоматически сгенерированный универсальный уникальный идентификатор»).
  • firstName (Имя)
  • lastName (Фамилия)
  • email (Электронная почта)
  • password (Пароль)
  • permissionLevel (что разрешено делать данному пользователю).

Для этого ресурса будут созданы следующие операции:

  • «POST» в конечной точке «/users» (создание нового пользователя).
  • «GET» в конечной точке «/users» (вывод списка всех пользователей).
  • «GET» в конечной точке «/users/:userId» (получение конкретного пользователя).
  • «PATCH» в конечной точке «/users/:userId» (обновление данных для конкретного пользователя).
  • «DELETE» в конечной точке «/users/:userId» (удаление конкретного пользователя).

Кроме того, будет использоваться стандарт «JSON web token» для создания токенов доступа.

Поэтому мы создадим ещё один ресурс под названием «auth», который будет принимать адрес электронной почты и пароль пользователя. А в ответ — генерировать токен для аутентификации при определённых операциях.

Настройка бэкенда REST API

Прежде всего убедитесь, что у вас установлена самая последняя версия Node.js. Здесь будем использовать версию 14.9.0, однако могут подойти и более старые.

Затем позаботьтесь о том, чтобы у вас была установлена MongoDB. Не будем подробно расписывать особенности используемых здесь Mongoose и MongoDB.

Просто запустите сервер в интерактивном режиме (введя в командной строке «mongo»), а не как сервис. Дело в том, что в какой-то момент нам нужно будет взаимодействовать с MongoDB напрямую, а не через код Node.js.

Обратите внимание! С MongoDB нет необходимости создавать конкретную базу данных, как это бывает в сценариях некоторых реляционных СУБД. Первый вызов «insert» из кода Node.js инициирует её создание автоматически.

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

Перейдите к появившейся папке «rest-api-tutorial/» в терминале. Здесь находятся три папки модулей проекта:

  • «common» — все общие сервисы и информация, совместно используемая пользовательскими модулями.
  • «users» — всё, что касается пользователей.
  • «auth» — обработка генерации токенов JWT (JSON Web Token) и поток авторизации.

Теперь запустите «npm install» (или «yarn», если он у вас есть).

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

Создание пользовательского модуля

Мы будем использовать Mongoose — ODM-библиотеку для MongoDB. С её помощью создадим модель «user» (пользователь) в рамках схемы «user» (пользователь).

Первым делом нужно создать схему для библиотеки Mongoose в «/users/models/users.model.js»:

const userSchema = new Schema({
   firstName: String,
   lastName: String,
   email: String,
   password: String,
   permissionLevel: Number
});

После определения схемы можно легко присоединить её к модели «user».

const userModel = mongoose.model('Users', userSchema);

Теперь можем использовать эту модель для реализации всех операций «CRUD», которые нам нужны в конечных точках Express.

Начнём с операции создания пользователя, определив маршрут в «users/routes.config.js»:

app.post('/users', [
   UsersController.insert
]);

Этот код добавляется в основной файл «index.js» приложения на Express. Объект «UsersController» импортируется из нашего контроллера, где мы соответствующим образом хешируем пароль, определённый в «/users/controllers/users.controller.js»:

exports.insert = (req, res) => {
   let salt = crypto.randomBytes(16).toString('base64');
   let hash = crypto.createHmac('sha512',salt)
                                    .update(req.body.password)
                                    .digest("base64");
   req.body.password = salt + "$" + hash;
   req.body.permissionLevel = 1;
   UserModel.createUser(req.body)
       .then((result) => {
           res.status(201).send({id: result._id});
       });
};

Теперь мы можем протестировать нашу модель Mongoose, запустив сервер («npm start») и отправив запрос «POST» в «/users» с данными в формате JSON:

{
   "firstName" : "Marcos",
   "lastName" : "Silva",
   "email" : "marcos.henrique@toptal.com",
   "password" : "s3cr3tp4sswo4rd"
}

Для этого есть соответствующий инструментарий. Во-первых, это Insomnia (его рассмотрим далее) и Postman — популярные инструменты с графическим интерфейсом, а также curl — утилита командной строки.

Можно даже использовать один только JavaScript. Например, из встроенной консоли средств разработки вашего браузера:

fetch('http://localhost:3600/users', {
        method: 'POST',
        headers: {
            "Content-type": "application/json"
        },
        body: JSON.stringify({
            "firstName": "Marcos",
            "lastName": "Silva",
            "email": "marcos.henrique@toptal.com",
            "password": "s3cr3tp4sswo4rd"
        })
    })
    .then(function(response) {
        return response.json();
    })
    .then(function(data) {
        console.log('Request succeeded with JSON response', data);
    })
    .catch(function(error) {
        console.log('Request failed', error);
    });

Здесь результатом валидного «POST» будет только лишь идентификатор «id» от созданного пользователя:

{ 
  "id": "5b02c5c84817bf28049e58a3" 
}

Нам также нужно добавить метод «createUser» к модели в «users/models/users.model.js»:

exports.createUser = (userData) => {
    const user = new User(userData);
    return user.save();
};

Теперь надо убедиться, что пользователь существует. Для этого реализуем функцию «get user by id» для следующей конечной точки, а именно «users/:userId».

Первым делом создаём маршрут в «/users/routes/config.js»:

app.get('/users/:userId', [
    UsersController.getById
]);

Затем создаём контроллер в «/users/controllers/users.controller.js»:

exports.getById = (req, res) => {
   UserModel.findById(req.params.userId).then((result) => {
       res.status(200).send(result);
   });
};

И, наконец, добавляем метод «findById» к модели в «/users/models/users.model.js»:

exports.findById = (id) => {
    return User.findById(id).then((result) => {
        result = result.toJSON();
        delete result._id;
        delete result.__v;
        return result;
    });
};

Ответ будет примерно таким:

{
   "firstName": "Marcos",
   "lastName": "Silva",
   "email": "marcos.henrique@toptal.com",
   "password": "Y+XZEaR7J8xAQCc37nf1rw==$p8b5ykUx6xpC6k8MryDaRmXDxncLumU9mEVabyLdpotO66Qjh0igVOVerdqAh+CUQ4n/E0z48mp8SDTpX2ivuQ==",
   "permissionLevel": 1,
   "id": "5b02c5c84817bf28049e58a3"
}

Обратите внимание! Здесь мы видим хешированный пароль. В данном руководстве мы показываем пароль, но лучше никогда этого не делать, даже если пароль хеширован. Ещё у нас здесь есть «permissionLevel», который мы будем использовать для обработки разрешений пользователя.

Повторяя изложенный выше порядок действий, теперь можно добавить функциональность для обновления пользователя. Будем использовать операцию «PATCH», позволяющую отправлять только те поля, которые мы хотим изменить. Таким образом, мы будем отправлять любые поля, которые захотим изменить, по маршруту от «PATCH» к «/users/:userid».

Кроме того, потребуется провести дополнительную проверку. Ведь изменения должны затрагивать только соответствующего пользователя или администратора. И только администратор должен иметь возможность менять «permissionLevel» (уровень допуска).

Пока что оставим эту часть и вернёмся к ней после того, как реализуем модуль «auth». Сейчас наш контроллер будет выглядеть так:

exports.patchById = (req, res) => {
   if (req.body.password){
       let salt = crypto.randomBytes(16).toString('base64');
       let hash = crypto.createHmac('sha512', salt).update(req.body.password).digest("base64");
       req.body.password = salt + "$" + hash;
   }
   UserModel.patchUser(req.params.userId, req.body).then((result) => {
           res.status(204).send({});
   });
};

Здесь мы по умолчанию будем отправлять HTTP-код «204» без тела ответа, чтобы показать, что запрос был успешным.

И нужно будет добавить к модели метод «patchUser»:

exports.patchUser = (id, userData) => {
    return User.findOneAndUpdate({
        _id: id
    }, userData);
};

Список пользователей будет реализован как «GET» в «/users/» следующим контроллером:

exports.list = (req, res) => {
   let limit = req.query.limit && req.query.limit <= 100 ? parseInt(req.query.limit) : 10;
   let page = 0;
   if (req.query) {
       if (req.query.page) {
           req.query.page = parseInt(req.query.page);
           page = Number.isInteger(req.query.page) ? req.query.page : 0;
       }
   }
   UserModel.list(limit, page).then((result) => {
       res.status(200).send(result);
   })
};

Соответствующим методом модели будет:

exports.list = (perPage, page) => {
    return new Promise((resolve, reject) => {
        User.find()
            .limit(perPage)
            .skip(perPage * page)
            .exec(function (err, users) {
                if (err) {
                    reject(err);
                } else {
                    resolve(users);
                }
            })
    });
};

Ответ в результирующем списке будет иметь следующую структуру:

[
   {
       "firstName": "Marco",
       "lastName": "Silva",
       "email": "marcos.henrique@toptal.com",
       "password": "z4tS/DtiH+0Gb4J6QN1K3w==$al6sGxKBKqxRQkDmhnhQpEB6+DQgDRH2qr47BZcqLm4/fphZ7+a9U+HhxsNaSnGB2l05Oem/BLIOkbtOuw1tXA==",
       "permissionLevel": 1,
       "id": "5b02c5c84817bf28049e58a3"
   },
   {
       "firstName": "Paulo",
       "lastName": "Silva",
       "email": "marcos.henrique2@toptal.com",
       "password": "wTsqO1kHuVisfDIcgl5YmQ==$cw7RntNrNBNw3MO2qLbx959xDvvrDu4xjpYfYgYMxRVDcxUUEgulTlNSBJjiDtJ1C85YimkMlYruU59rx2zbCw==",
       "permissionLevel": 1,
       "id": "5b02d038b653603d1ca69729"
   }
]

Теперь реализуем последнюю часть, «DELETE» в «/users/:userId». Наш контроллер для удаления:

exports.removeById = (req, res) => {
   UserModel.removeById(req.params.userId)
       .then((result)=>{
           res.status(204).send({});
       });
};

Контроллер снова вернёт HTTP-код «204» с пустым телом ответа в качестве подтверждения.

Соответствующий метод модели должен выглядеть следующим образом:

exports.removeById = (userId) => {
    return new Promise((resolve, reject) => {
        User.deleteMany({_id: userId}, (err) => {
            if (err) {
                reject(err);
            } else {
                resolve(err);
            }
        });
    });
};

Теперь у нас есть все необходимые операции для манипулирования ресурсом «user» (пользователь) и готов контроллер пользователя.

Приведённый здесь код должен сформировать представление об основных принципах использования REST. К этому коду нам предстоит ещё вернуться для проведения проверок и изменения разрешений, но сначала нужно обеспечить безопасность. Для этого мы создадим модуль аутентификации.

Создание модуля «auth»

Прежде чем обезопасить модуль «users» с помощью добавления middleware-компонентов (ПО промежуточной обработки) для обеспечения разрешений и валидации, нужно создать валидный токен текущего пользователя.

В качестве токена используем JSON web token (JWT). Это стандарт для создания токенов доступа, основанный на формате JSON, который можно использовать для безопасного выполнения пользователем нескольких запросов без повторной проверки. Мы сгенерируем JWT в ответ на предоставление пользователем валидного адреса электронной почты и пароля.

Обычно у токена есть определённое время действия: для обеспечения безопасности передачи данных каждые несколько минут создаётся новый токен. Но в данном руководстве мы воздержимся от обновления токена. Для простоты ограничимся одним-единственным токеном на каждую авторизацию.

Во-первых, создадим конечную точку для POST-запросов к ресурсу «/auth». Тело запроса будет содержать адрес электронной почты пользователя и пароль:

{
   "email" : "marcos.henrique2@toptal.com",
   "password" : "s3cr3tp4sswo4rd2"
}

Прежде чем задействовать контроллер, нужно проверить пользователя в «/authorization/middlewares/verify.user.middleware.js»:

exports.isPasswordAndUserMatch = (req, res, next) => {
   UserModel.findByEmail(req.body.email)
       .then((user)=>{
           if(!user[0]){
               res.status(404).send({});
           }else{
               let passwordFields = user[0].password.split('$');
               let salt = passwordFields[0];
               let hash = crypto.createHmac('sha512', salt).update(req.body.password).digest("base64");
               if (hash === passwordFields[1]) {
                   req.body = {
                       userId: user[0]._id,
                       email: user[0].email,
                       permissionLevel: user[0].permissionLevel,
                       provider: 'email',
                       name: user[0].firstName + ' ' + user[0].lastName,
                   };
                   return next();
               } else {
                   return res.status(400).send({errors: ['Invalid email or password']});
               }
           }
       });
};

После этого можно перейти к контроллеру и сгенерировать JWT:

exports.login = (req, res) => {
   try {
       let refreshId = req.body.userId + jwtSecret;
       let salt = crypto.randomBytes(16).toString('base64');
       let hash = crypto.createHmac('sha512', salt).update(refreshId).digest("base64");
       req.body.refreshKey = salt;
       let token = jwt.sign(req.body, jwtSecret);
       let b = Buffer.from(hash);
       let refresh_token = b.toString('base64');
       res.status(201).send({accessToken: token, refreshToken: refresh_token});
   } catch (err) {
       res.status(500).send({errors: err});
   }
};

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

Теперь нам нужно лишь создать маршрут и вызвать соответствующий middleware-компонент в «/authorization/routes.config.js»:

app.post('/auth', [
    VerifyUserMiddleware.hasAuthValidFields,
    VerifyUserMiddleware.isPasswordAndUserMatch,
    AuthorizationController.login
]);

В ответе будет сгенерированный JWT (в поле «accessToken»):

{
   "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiI1YjAyYzVjODQ4MTdiZjI4MDQ5ZTU4YTMiLCJlbWFpbCI6Im1hcmNvcy5oZW5yaXF1ZUB0b3B0YWwuY29tIiwicGVybWlzc2lvbkxldmVsIjoxLCJwcm92aWRlciI6ImVtYWlsIiwibmFtZSI6Ik1hcmNvIFNpbHZhIiwicmVmcmVzaF9rZXkiOiJiclhZUHFsbUlBcE1PakZIRG1FeENRPT0iLCJpYXQiOjE1MjY5MjMzMDl9.mmNg-i44VQlUEWP3YIAYXVO-74803v1mu-y9QPUQ5VY",
   "refreshToken": "U3BDQXBWS3kyaHNDaGJNanlJTlFkSXhLMmFHMzA2NzRsUy9Sd2J0YVNDTmUva0pIQ0NwbTJqOU5YZHgxeE12NXVlOUhnMzBWMGNyWmdOTUhSaTdyOGc9PQ=="
}

Создав токен, мы можем использовать его внутри заголовка «Authorization» с помощью формы «Bearer ACCESS_TOKEN».

Создание middleware-компонентов разрешений и валидации

Первым делом нужно определить, кто может использовать ресурс «users». Вот сценарии, с которыми нам нужно будет иметь дело:

  • Общедоступный для создания пользователей (процесс регистрации). В этом сценарии JWT использоваться не будет.
  • Закрытый для авторизовавшегося пользователя и для администраторов, обновляющих этого пользователя.
  • Закрытый для администратора только для удаления учётных записей пользователей.

Определившись со сценариями, перейдём к middleware-компонентам, которые всегда проверяют, использует ли пользователь валидный JWT.

Добавить middleware компонент в «/common/middlewares/auth.validation.middleware.js» можно также легко, как в примере ниже:

    if (req.headers['authorization']) {
        try {
            let authorization = req.headers['authorization'].split(' ');
            if (authorization[0] !== 'Bearer') {
                return res.status(401).send();
            } else {
                req.jwt = jwt.verify(authorization[1], secret);
                return next();
            }
        } catch (err) {
            return res.status(403).send();
        }
    } else {
        return res.status(401).send();
    }
};

Для обработки ошибок запроса будем использовать коды ошибок HTTP:

  • «HTTP 401» для недопустимого запроса.
  • «НТТР 403» для валидного запроса с неверным токеном или для валидного токена с недопустимыми разрешениями.

Для управления разрешениями можно использовать побитовый оператор «И» (AND, &). Если возвести каждое требуемое разрешение во вторую степень, можно рассматривать каждый бит 32-битного целого числа как одно разрешение.

Администратор может получить все разрешения, установив их значение равным «2147483647». В данном случае этот пользователь будет иметь возможность получить доступ к любому маршруту.

Другой пример: пользователь, значение разрешения которого равно семи, будет иметь разрешения к правам доступа, отмеченным битами для значений 1, 2 и 4 (два в нулевой, первой и второй степени).

Middleware-компонент будет выглядеть следующим образом:

exports.minimumPermissionLevelRequired = (required_permission_level) => {
   return (req, res, next) => {
       let user_permission_level = parseInt(req.jwt.permission_level);
       let user_id = req.jwt.user_id;
       if (user_permission_level & required_permission_level) {
           return next();
       } else {
           return res.status(403).send();
       }
   };
};

Компоненты middleware универсальны. Если уровень разрешений пользователя и необходимый уровень разрешений совпадают хотя бы в одном бите, результат будет больше нуля и действие может продолжаться. В противном случае будет возвращён HTTP-код «403».

Теперь нужно добавить middleware для аутентификации к маршрутам модуля «user» в «/users/routes.config.js»:

app.post('/users', [
   UsersController.insert
]);
app.get('/users', [
   ValidationMiddleware.validJWTNeeded,
   PermissionMiddleware.minimumPermissionLevelRequired(PAID),
   UsersController.list
]);
app.get('/users/:userId', [
   ValidationMiddleware.validJWTNeeded,
   PermissionMiddleware.minimumPermissionLevelRequired(FREE),
   PermissionMiddleware.onlySameUserOrAdminCanDoThisAction,
   UsersController.getById
]);
app.patch('/users/:userId', [
   ValidationMiddleware.validJWTNeeded,
   PermissionMiddleware.minimumPermissionLevelRequired(FREE),
   PermissionMiddleware.onlySameUserOrAdminCanDoThisAction,
   UsersController.patchById
]);
app.delete('/users/:userId', [
   ValidationMiddleware.validJWTNeeded,
   PermissionMiddleware.minimumPermissionLevelRequired(ADMIN),
   UsersController.removeById
]);

На этом завершается основная часть разработки REST API. Остаётся только всё это протестировать.

Запуск и тестирование REST API с Insomnia

В Insomnia есть хорошая бесплатная версия клиента REST. Будем использовать здесь данный инструмент как приложение, помогающее понять, что происходит с нашим API.

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

Чтобы создать пользователя, нужно просто отправить с помощью «POST» необходимые поля в соответствующую конечную точку и сохранить сгенерированный идентификатор ID для последующего использования.

В ответ с API придёт идентификатор пользователя:

Теперь с помощью конечной точки «/auth/» можно сгенерировать JWT:

В ответе мы должны получить токен:

Берём «accessToken», ставим впереди него «Bearer» (не забываем о пробеле) и добавляем его в заголовки запроса внутри «Authorization»:

Если не сделать этого, то на каждый запрос, кроме регистрации, будет возвращаться HTTP-код «401». Тем более сейчас, когда мы внедрили middleware для разрешений. Но у нас есть валидный токен, поэтому от «/users/:userId» мы получаем следующий ответ:

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

Попробуем получить список пользователей:

Неожиданно мы получаем ответ «403».

У нашего пользователя нет разрешений на доступ к этой конечной точке. Придётся поменять «permissionLevel» пользователя с 1 до 7 (даже «5» будет достаточно, так как наши бесплатные и платные уровни разрешений представлены значениями «1» и «4» соответственно.)

Это можно сделать вручную. Например, в интерактивной консоли MongoDB (идентификатор ID поменяйте на свой):

db.users.update({"_id" : ObjectId("5b02c5c84817bf28049e58a3")},{$set:{"permissionLevel":5}})

Затем нужно сгенерировать новый JWT. После чего мы получим нужный ответ:

Теперь протестируем обновлённый функционал, отправив запрос «PATCH» с произвольными полями в нашу конечную точку «/users/:userId»:

В ответ должен прийти «204» в качестве подтверждения успешности операции. Однако мы можем ещё раз запросить пользователя, чтобы убедиться наверняка.

И, наконец, нужно удалить пользователя. Потребуется создать нового пользователя, как мы это уже делали выше. Не забудьте обозначить его ID и позаботьтесь, чтобы для пользователя-администратора имелся соответствующий JWT.

Новый пользователь должен будет иметь разрешения со значением «2053» (т. е. «2048» — ADMIN — плюс наши предыдущие «5»), чтобы иметь возможность также выполнить операцию удаления.

После того как всё будет готово и сгенерирован новый JWT, нужно будет обновить заголовок запроса «Authorization»:

Отправив запрос «DELETE» на «/users/:userId», мы должны получить ответ «204» в качестве подтверждения. Можно дополнительно убедиться в удалении, отправив запрос ««/users/»» для получения списка всех имеющихся пользователей.

Следующие этапы создания REST API

Теперь с помощью инструментов и методов, рассмотренных в этом руководстве, вы сможете создавать простые и безопасные REST API на Node.js. Многое из того, что не является существенным для работы с REST API, было опущено. Так что не забывайте:

  • Проводить проверки валидности формы (например, чтобы электронная почта пользователя была уникальной).
  • Внедрять модульное тестирование и отчётность об ошибках.
  • Не допускать изменения уровня разрешений самими пользователями.
  • Не допускать возможности администраторам удалять самих себя.
  • Не допускать разглашения конфиденциальной информации (например, хешированных паролей).
  • Помещать пароли к токену и ключи авторизации из «common/config/env.config.js» в механизм их распределения, находящийся во внешнем хранилище.

В заключение читатель может попробовать перейти от использования в кодовой базе промисов JavaScript к применению «async/await».

Нужна надёжная база для разработки веб-приложений? Выбирайте виртуальные сервера от Eternalhost с технической поддержкой 24/7 и бесплатной защитой от DDoS!

Автор оригинала: Marcos Henrique da Silva

Оцените материал:


[Всего голосов: 0    Средний: 0/5]

Понравилась статья? Поделить с друзьями:
  • Викасол инструкция по применению в таблетках при геморрое цена
  • Power bank 2600 mah инструкция на русском языке
  • Уралхим удобрения руководство
  • Меритон инструкция по применению в ветеринарии для коров
  • Как делать долговременную укладку бровей инструкция