Як писати REST API на Node.js правильно

7 хв. читання

В цій статті я опишу кращі практики при написанні REST API на Node.js. Як краще називати методи вашого API, як організувати аутентифікацію тощо.

1. Використовуйте HTTP-методи

Уявіть, що вам потрібно написати API для створення, редагування та видалення користувачів. І для отримання їх даних, звісно. Для цих операцій вже існують відповідні HTTP-методи: POST, PUT, GET, PATCH та DELETE, не вигадуйте велосипед.

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

  • POST /user чи PUT /user/:id щоб створити нового користувача
  • GET /user щоб отримати список користувачів
  • GET /user/:id щоб отримати дані одного користувача
  • PATCH /user/:id для редагування даних користувача
  • DELETE /user/:id для видалення користувача.

2. Використовуйте HTTP-статуси коректно

Правильно використовуйте статус-коди:

  • 2xx якщо запит успішно оброблено.
  • 3xx якщо ресурс було переміщено.
  • 4xx якщо є помилка в запиті (наприклад, запит неіснуючого ресурсу).
  • 5xx якщо щось пішло не так на стороні API.

Якщо ви використовуєте Express, то це зробити досить просто:

res.status(500).send({error: 'Internal server error happened'})

Те ж саме з Restify:

res.status(201)

Список всіх статус-кодів є на вікіпедії.

3. Використовуйте заголовки для метаданих

Щоб додати метадані до вашої відповіді, слід використовувати HTTP-заголовки. Наприклад, для передачі інформації про пагінацію, ліміт звернень чи аутентифікацію.

Список стандартизованих заголовків можна знайти тут.

Якщо вам потрібно передати якісь нестандартні дані, то для таких заголовків прийнято використовувати префікс X-. Наприклад, для передачі CSRF-токену може використовуватися заголовок X-Csrf-Token. Але з іншої сторони RFC 6648 оголошує такий підхід застарілим. Сучасні додатки повинні назв для заголовків, що можуть конфліктувати з іншими додатками. OpenStack, наприклад, використовує унікальний префікс:

OpenStack-Identity-Account-ID  
OpenStack-Networking-Host-Name  
OpenStack-Object-Storage-Policy  

Зауважте, що стандарт HTTP не накладає ніяких обмежень на розмір заголовків, але сама Node.js встановлює обмеження в 80KB. Це зроблено для захисту від DOS-атак.

4. Оберіть підходящий фреймворк

Важливо обрати фреймворк, що якнайкраще вдовольняє ваші потреби.

Express, Koa, Hapi

Express, Koa та Hapi використовуються для написання браузерних додатків, вони підтримують шаблонізатори і рендеринг. І якщо ви плануєте писати повноцінний бекенд для сервісу на Node, вони будуть гарним вибором.

Restify

В противагу фреймворкам вище можна поставити Restify. Він концентрується на написанні потужного та гнучкого API. Також він із коробки підтримує DTrace для всіх обробників.

ktretiak в коментарах підказав, що DTrace вже не актуальний і Node.js має власний модуль для цих цілей.

Restify використовують такі відомі додатки як npm та Netflix.

5. Тестуйте ваш API

Одним з найкращих способів протестувати API — уявити його у вигляді чорного ящика.

Тестування по стратегії чорного ящика — спосіб тестування, коли функціонал додатку розглядається без знання про внутрішню будову.

Одним з модулів, що дозволяє виконувати таке тестування є supertest. Простий тест на отримання даних користувача з використанням mocha:

const request = require('supertest')

describe('GET /user/:id', function() {  
  it('returns a user', function() {
    return request(app)
      .get('/user')
      .set('Accept', 'application/json')
      .expect(200, {
        id: '1',
        name: 'John Math'
      }, done)
  })
})

Це все круто, але зовсім не означає, що вам слід забути про юніт-тести! Вони теж важливі і потрібні.

6. Використовуйте аутентифікацію на основі JWT, без збереження стану

Як ви знаєте, REST API не повинен зберігати стан. І наш механізм авторизації теж. Для цього ідеально підходять JWT (JSON Web Token).

JWT складається з трьох частин:

  • Заголовок, де зберігається тип токену та алгоритм хешування.

  • Тіло, де зберігається вся інформація.

  • Сигнатура (JWT не шифрує тіло, а лише підписує його).

Додати підтримку JWT-аутентифікації до вашого додатку досить просто:

const koa = require('koa')  
const jwt = require('koa-jwt')

const app = koa()

app.use(jwt({  
  secret: 'very-secret' 
}))

// Захищена middleware
app.use(function *(){  
  // тіло токену доступне в об'єкті this.state.user
  this.body = {
    secret: '42'
  }
})

Після цього, всі методи вашого API будуть захищені JWT і для доступу до них вам потрібно передавати заголовок Authorization:

curl --header "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ" my-website.com  

JWT не залежить від бази даних і може містити «час життя».

Не забудьте впевнитися в тому, що доступ до вашого API проходить по протоколу HTTPS.

7. Використовуйте умовні запити

Умовні запити — HTTP-запити, що оброблюються по різному в залежності від заголовків.

Такі заголовки перевіряють чи відрізняється поточна версія ресурсі від тієї, що збережена у користувача. Це може бути часова мітка останньої модифікації чи тег, що унікальний для кожної версії.

Ось ці заголовки:

  • Last-Modified щоб дізнатися коли ресурс було змінено
  • Etag — унікальний тег
  • If-Modified-Since використовується разом з Last-Modified
  • If-None-Match використовується з Etag

Давайте розглянемо на прикладі!

У клієнта немає ніякої версії ресурсу doc, він робить запит, не використовуючи If-Modified-Since та If-None-Match. Потім сервер відправляє ресурс з заголовками Etag та Last-Modified.

Як писати REST API на Node.js правильно

Клієнт може встановити заголовки If-Modified-Since and If-None-Match коли намагається отримати ресурс. Якщо ресурс не змінився — сервер відповідає статусом 304 - Not Modified, а не відправляє ресурс ще раз.

Як писати REST API на Node.js правильно

8. Обмежте кількість запитів від одного користувача

RPS (requests per second) — обмеження на кількість запитів від користувача за одну секунду. Щоб показати користувачу скільки запитів він може ще зробити за допомогою цих заголовків:

  • X-Rate-Limit-Limit — кількість запитів, дозволених в заданий інтервал.

  • X-Rate-Limit-Remaining — скільки ще запитів можна виконати в поточному інтервалі.

  • X-Rate-Limit-Reset — час, коли обмеження буде скинуте.

Більшість HTTP фреймворків підтримують це з коробки (або за допомогою плагінів). Для Koa, наприклад, є пакунок koa-ratelimit.

9. Напишіть зрозумілу документацію

Ви пишете API щоб дозволити іншим скористатися перевагами вашого сервісу, і тому мати зрозумілу документацію дуже важливо.

Ось ці проекти з відкритим кодом допоможуть вам створити документацію:

Ну або ви можете скористуватися онлайн сервісом, наприклад Apiary

10. Не пропустіть майбутнє API

В останні роки набули поширення дві мови запитів: GraphQL від Facebook та Falcor від Netflix. Але навіщо вони нам?

Уявіть ось такий запит ресурсу:

/org/1/space/2/docs/1/collaborators?include=email&page=1&limit=10

Саме тут нам і приходять на допомогу GraphQL та Falcor.

Про GraphQL

GraphQL — це мова запитів для API. Вона надає зрозумілий опис ваших даних, дозволяючи клієнту вирішувати які дані йому потрібні.

Про Falcor

Falcor — це інноваційна платформа, на якій працює UI Netflix. Falcor дозволяє вам моделювати дані на стороні бекенду в один віртуальний JSON-об'єкт, а клієн працює з ним як зі звичайним JSON, використовуючи звичні операції get, set та call. Якщо ви знаєте свої дані, ви знаєте свій API

Круті API для натхнення

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

Помітили помилку? Повідомте автору, для цього достатньо виділити текст з помилкою та натиснути Ctrl+Enter
Codeguida 5.8K
Приєднався: 8 місяців тому
Коментарі (0)

    Ще немає коментарів

Щоб залишити коментар необхідно авторизуватися.

Вхід / Реєстрація