REST


API - способ доступа к программному продукту

SOAP - запаковка в текстовый формат(XML) и удаленный вызов процедуры REST - архитектурный стиль для построения сетевых архитектур

  1. client-server
  2. запросы без состояний (запросы должны быть независимы с полной информацией)
  3. кэширование
  4. однообразный интерфейс
  5. многослойная система (всякие кеширующие сервера, прокси и т.д.)
  6. доставка кода по требованию (обновление кода по http протоколу) - на практике нет

Суть http протокола:
Открываем соединение, отправляем некоторые текстовые данные, закрываем соединение (request, response)

curl https://api.github.com --verbase

Нестандартные заголовки помечаются X- в начале

URI - unique resource identifier

Level 0 - используем http как транспорт, перекидываемся текстом, статус всегда 200, даже ошибка завернута в текст
Level 1 - то же + ресурсы доступны uri Level 2 - add more HTTP stuff, для логики используем http коды Level 3 - all links and make data live

Hypermedia or HATEOAS

Express

var express = require('express');
var app = express();

app.get('/', function(req, res) {
  res.send('Hello World!');
});

app.listen(3000, function() {
  console.log('Example app listening on port 3000');
});

app.get('/users/:userId', function(req, res) {});

// users.js
let userRouter = express.Router();

// items.js
let itemRouter = express.Router();

// app.js
import userRouter from './users';
import itemRouter from './item';
app.use('/users', userRouter);
app.use('/items', itemRouter);

Middleware - функции с 3 или 4 параметрами, которые обрабатывают наш запрос

function printMethod(req, res, next) {
  console.log('Method is ', req.method);
  next();
}

router.use('/', validateToken, checkPermissions);
router.post('/users', [validateInput, handleUserCreate]);

Error handling

if(err) return next(err);

app.use(function(err, req, res, next) {
  console.error(err.stack);
  res.status(500).send('Something broke!');
});

Protect your API

pm2 for build

Project structure

doc/
config/
migrations/ - изменения в бд в виде скриптов
routes/
services/ | models/
test/
  unit/
  api/
app.js
run.js
package.json

route grouping

rootRouter.get(url.add("self", "/api/root"), (req, res, next) => {
  res.apiResponse({
    links: {
      users: url.get("users"),
      profile: url.get("profile")
    }
  });
});

versioning
client send req with header
Accept: application/vnd.mycompany.myapp-v2+json

rootRouter.get(url.add("self", "/api/root"), (req, res, next) => {
  let mediaType = req.get('Accept');
  res.apiResponse({
    links: getLinks(mediaType)
  });
});

Tests
Mocha + Supertest

describe('GET /users', function() {
  it('respond with json', function(done) {
    request(app)
      .get('/users')
      .set('Accept', 'application/json')
      .expect(200)
      .end(function(err, res) {
        if (err) return done(err)
        done()
      })
  })
  it('should return array of users', function(done) {})
});

Tools