REST API v Node.js

REST API v Node.js

Proč stavět REST API v Node.js a Express.js

Node.js nabízí jednovláknový, event-driven běhový model s vysokou propustností I/O, což z něj dělá ideální volbu pro síťové služby. Express.js je minimalistický framework, který přidává routing, middleware architekturu a ekosystém rozšíření. Kombinace je vhodná pro RESTful API díky jednoduchosti, výkonu a velké komunitě.

Zásady REST: zdroje, reprezentace, uniformní rozhraní

  • Zdroj: doménový objekt (např. /users, /orders), identifikovaný URI.
  • Reprezentace: nejčastěji JSON s hlavičkou Content-Type: application/json.
  • Metody: GET (čtení), POST (vytvoření), PUT/PATCH (aktualizace), DELETE (mazání).
  • Bezstavovost: každý požadavek nese veškerý kontext (autentizace, parametry).
  • Hypermedia a odkazy (volitelné): např. pole _links s navigací.
  • Cacheovatelnost: hlavičky ETag, Cache-Control, Last-Modified.

Struktura projektu: modularita a vrstvy

  • src/app.js: konfigurace Expressu, middleware, mount routů.
  • src/routes/*.js: definice cest, mapování na kontrolery.
  • src/controllers/*.js: orchestrace požadavků, validace, odpovědi.
  • src/services/*.js: aplikační logika, pravidla domény.
  • src/repositories/*.js: přístup k datům (DB/externí API).
  • src/middlewares/*.js: autentizace, rate-limit, logování.
  • src/schemas/*.js: validační schémata (Joi/Zod).
  • src/config: proměnné prostředí, konfigurace.
  • tests/: integrační a jednotkové testy.

Inicializace a závislosti

  • Inicializace: npm init -y
  • Základ: npm i express dotenv
  • Bezpečnost a utilitky: npm i helmet cors morgan express-rate-limit
  • Validace: npm i zod nebo npm i joi
  • Testy: npm i -D jest supertest
  • DB (příklady): MongoDB npm i mongoose, PostgreSQL s ORM npm i @prisma/client (+ npm i -D prisma)

Spuštění Expressu a základní middleware

V src/app.js nastavte jádro: JSON parsování, CORS, bezpečnostní hlavičky, rate-limit a logování.

  • app.use(express.json({ limit: "1mb" })) – bezpečné parsování těla požadavku.
  • app.use(cors()) – řízení původu; ve výrobě omezte na povolené domény.
  • app.use(helmet()) – bezpečnostní hlavičky (XSS, clickjacking).
  • app.use(morgan("combined")) – HTTP logy.
  • rateLimit({ windowMs: 60_000, max: 100 }) – omezení zneužití.

Routing a kontrolery: čisté oddělení

Route definuje tvar API; kontroler řeší validaci, volá službu a vrací odpověď.

  • Příklad cesty: router.get("/users", userController.list)
  • Kontroler: načte req.query (filtr, stránkování), zavolá userService.findAll, vrátí 200 s JSON.
  • Pro vytvoření: router.post("/users", validate(userSchema), userController.create)

Validace vstupů a sanitace

Validujte query, params i body. Udržujte schémata vedle doménových entit. Příklad se Zod:

  • const createUserSchema = z.object({ email: z.string().email(), name: z.string().min(2) })
  • function validate(schema) { return (req, res, next) => { const p = schema.safeParse(req.body); if (!p.success) return res.status(400).json({ errors: p.error.issues }); next(); } }

Chybové stavy a jednotný error handler

  • Vlastní chyby: class AppError extends Error { constructor(message, status=400, code="BAD_REQUEST"){ super(message); this.status=status; this.code=code; } }
  • Globální handler: app.use((err, req, res, next) => { const status = err.status || 500; res.status(status).json({ error: err.code || "INTERNAL", message: err.message }); })
  • Nechytané chyby/Promises: připojte posluchače process.on("unhandledRejection") a process.on("uncaughtException").

Asynchronní řetězení: async/await a middleware

Zabalte asynchronní kontrolery do helperu, aby nepadaly do unhandled stavů: const asyncH = fn => (req,res,next) => Promise.resolve(fn(req,res,next)).catch(next). Aplikujte na všechny kontrolery.

Persistenční vrstva: Mongoose vs. Prisma

  • Mongoose (MongoDB): flexibilní dokumentové modely; rychlý vývoj, schemaless přístup s validací na úrovni modelu.
  • Prisma (SQL): typová bezpečnost, migrace, kompozice dotazů; vhodné pro Postgres/MySQL/SQLite.
  • Repository pattern: userRepository.findById(id) kapsuluje detaily DB a usnadňuje testování.

Filtrování, stránkování a řazení

  • Parametry: ?page=1&limit=20&sort=-createdAt&filter[name]=john
  • Výstup: metadata total, page, limit, hasNext, a pole items.
  • Indexy: navrhujte podle nejčastějších dotazů; u Mongo využijte compound indexy, u SQL btree/GIN dle typu.

Konvence HTTP kódů a odpovědí

  • 200 OK pro čtení, 201 Created + hlavička Location pro vytvoření.
  • 204 No Content pro úspěšné DELETE.
  • 400/422 validace, 401 neautentizovaný, 403 bez oprávnění, 404 nenalezeno.
  • Konzistentní tvar chyby: { "error": "VALIDATION_ERROR", "message": "...", "details": [...] }

Autentizace a autorizace (JWT, session, API klíče)

  • JWT: krátká expirace (např. 15 min), refresh token s rotací; hlavička Authorization: Bearer <jwt>.
  • Scopes/role: claims scope nebo roles v JWT; middleware authorize("orders:read").
  • API klíče: pro server-to-server; uložení hashovaně, throttling podle klíče.
  • Session: pro webové aplikace; zvážte cookie s HttpOnly, SameSite, Secure.

Bezpečnost: CORS, hlavičky, rate-limit, input hardening

  • Omezte CORS na whitelist domén a použijte credentials jen pokud je nutné.
  • helmet() upraví klíčové hlavičky; doplňte Cross-Origin-Resource-Policy a Cross-Origin-Opener-Policy dle potřeby.
  • Rate-limit a slowdown pro veřejné endpointy (login, registrace).
  • Sanitace vstupů: validace typů, whitelist polí, prevence NoSQL/SQL injection (parametrizace, operátorové whitelisty).

Verzování API a kontrakty

  • URI verzování: /v1/..., /v2/... pro evoluční změny.
  • Kontrakty: OpenAPI specifikace (yaml/json) generuje dokumentaci a slouží k validaci schémat.
  • Deprecation: hlavičky Deprecation a Sunset s termínem ukončení, odkaz na migrační návod.

Dokumentace: OpenAPI/Swagger a živé testování

  • Generujte OpenAPI ručně nebo z anotací; publikujte na /docs jen v chráněném režimu.
  • Udržujte příklady požadavků/odpovědí a chybové scénáře; doplňte schémata pro components/schemas.

Idempotence, bezpečné opakování a integrace

  • Idempotence: PUT by měl být idempotentní; pro POST použijte idempotency key v hlavičce pro platební/externí operace.
  • Time-outs a retry: nastavte klientská i serverová časová omezení; exponenciální backoff.
  • Transakce: u SQL wrapujte kritické operace; u DB bez transakcí použijte outbox pattern a message broker.

Cacheování, ETag a podmíněné dotazy

  • ETag: generujte hash reprezentace; klient pošle If-None-Match, server vrátí 304 Not Modified.
  • Cache-Control: pro veřejné read-only zdroje; invalidujte na změnu.
  • Redis: krátkodobá cache opakovaných dotazů, rate-limit metriky, session store.

Logování, korelace a observabilita

  • Strukturované logy: JSON s poli level, msg, timestamp, requestId.
  • Correlation ID: middleware, které generuje request-id (např. z X-Request-ID).
  • Health checks: /healthz (základní), /readyz (závislosti – DB, cache).
  • Metriky: export do Promethea (latence, RPS, chybovost, využití paměti).

Testování: jednotkové, integrační a kontraktační

  • Jednotkové: izolujte služby a repozitáře (mock DB).
  • Integrační: supertest proti app bez síťového portu; seed testovacích dat.
  • Kontrakty: ověřte shodu s OpenAPI (pact testing, schema validation).
  • Coverage: klíčové happy-path i edge-case (neplatné vstupy, prázdné výsledky, chybějící oprávnění).

Konfigurace a prostředí

  • 12-factor: konfigurace z process.env, nikoli z kódu.
  • dotenv: pouze pro lokální vývoj; ve výrobě použijte tajemství z secret manageru.
  • Feature flags: řízení behavioru bez redeploye.

Výkon a škálování

  • Node cluster nebo PM2 pro využití více jader CPU.
  • Reverse proxy (NGINX) s keep-alive, gzip/br; TLS terminace.
  • DB optimalizace: správné indexy, limitované SELECTy, projekce polí.
  • Horizontální škálování: stateless instance, sticky sessions jen pokud nezbytné.

Nasazení a CI/CD

  • Docker: multi-stage build (instalace, build, runtime s node:alpine), neprivilegovaný uživatel.
  • CI: lint, testy, build image, sken zranitelností, deploy do stagingu/produkce.
  • Migrace: automaticky spouštěné při startu (Prisma migrate deploy), rollback strategie.

Versioning databáze a evoluce schémat

  • Prisma migrations nebo Knex skripty pro SQL; pro Mongo řízené změny pomocí migračního nástroje (Migrate/Mongock).
  • Bezpečná evoluce: expand–migrate–contract (přidej pole → piš do obou → čti z nového → odstraň staré).

Pozor na časté chyby

  • Mixování vrstev (SQL v kontroleru, validace v repozitáři) – porušení separace zodpovědností.
  • Nekonzistentní chybové kódy a tvary odpovědí – těžko se debuguje a integruje.
  • Chybějící timeouty externích volání – hromadění visících socketů.
  • Přehnaně velké payloady – nastavte limity a kompresi.
  • Nesprávně nastavené CORS – buď příliš široké (bezpečnost), nebo blokující legitimní klienty.

Checklist před publikací

  • Validace všech vstupů, sanitace, limit velikosti těla.
  • Jednotný error model a mapování HTTP kódů.
  • Autentizace/autorizační middleware na chráněných trasách.
  • Rate-limit a helmet aktivní; CORS výslovně povolené domény.
  • OpenAPI pokrývá všechny endpointy; verze API uvedena.
  • Logy korelované request-id; healthz/readyz dostupné.
  • Testy (unit/integration) a automatizované nasazení.

Ukázkové konvence odpovědí

  • List: { "items": [...], "page": 1, "limit": 20, "total": 134 }
  • Detail: { "id": "...", "name": "...", "_links": { "self": "/v1/users/..." } }
  • Chyba: { "error": "RESOURCE_NOT_FOUND", "message": "User not found" }

Závěr

REST API v Node.js s Express.js těží z jednoduché architektury, bohatého ekosystému a vysoké propustnosti. Dodržujte vrstvovou strukturu, důslednou validaci, jednotné chyby, bezpečnostní zásady a kontraktní dokumentaci. S promyšleným testováním, observabilitou a CI/CD získáte spolehlivou platformu, kterou lze bezpečně a rychle rozvíjet.

Pridaj komentár

Vaša e-mailová adresa nebude zverejnená. Vyžadované polia sú označené *