Mục lục
Mục Tiêu Bài Học
Sau bài học, bạn sẽ:
- Định nghĩa được REST là gì, phân biệt nó với protocol và với framework.
- Biết Roy Fielding và bản luận án tiến sĩ năm 2000 tại UC Irvine — gốc rễ của REST.
- Nắm 6 constraint cốt lõi của REST: client-server, stateless, cacheable, uniform interface, layered system, code-on-demand.
- Phân biệt REST với RPC, gRPC, SOAP qua mô hình tư duy và payload.
- Biết khi nào nên chọn REST, khi nào nên chuyển sang gRPC hay GraphQL.
- Hiểu series này sẽ xây dự án gì: Shop E-commerce API với ~60 endpoint, 17 bảng PostgreSQL, workspace 7 crate.
REST Là Gì?
REST viết tắt của Representational State Transfer (truyền trạng thái dạng biểu diễn). Nó là một architectural style (kiểu kiến trúc) cho hệ thống phân tán trên nền HTTP — không phải một protocol, không phải một framework, không phải một thư viện.
Nói chính xác hơn: REST là một tập hợp các constraint (ràng buộc) mà nếu hệ thống tuân theo, nó được gọi là RESTful. Có sáu constraint chính, sẽ trình bày chi tiết ở mục 4. Bất kỳ implementation nào — dùng Rust, Node, Go, Java đều như nhau — miễn thoả mãn đủ constraint là REST.
REST không phải:
- Một protocol như HTTP, TCP, hay WebSocket. HTTP là phương tiện truyền tải; REST là cách tổ chức tư duy trên HTTP.
- Một spec do IETF hay W3C ban hành. Không có "RFC REST" chính thức; chỉ có luận án tiến sĩ năm 2000 của Roy Fielding mô tả lại nguyên tắc.
- Đồng nghĩa với "API trả về JSON". Một endpoint trả về JSON nhưng vi phạm stateless hoặc uniform interface thì vẫn không phải REST.
- Cố định ràng buộc URL phải có dạng
/resource/:id. Đó là convention thường gặp, không phải định nghĩa.
Một câu mô tả ngắn thường được nhắc tới trong cộng đồng: "the web is RESTful" — vì toàn bộ World Wide Web vốn được thiết kế trên những nguyên tắc mà sau này Fielding gọi tên là REST. Nói cách khác, REST chính là HTTP được dùng đúng cách.
Roy Fielding Và Năm 2000
Roy Thomas Fielding là một trong những kiến trúc sư chính của giao thức HTTP. Ông tham gia soạn thảo RFC 2616 (HTTP/1.1, năm 1999) và sau này là RFC 7230–7235 (bản chia nhỏ của HTTP/1.1, năm 2014). Khi vừa nắm phần lớn lý do tại sao HTTP được thiết kế như vậy, ông đem chính kinh nghiệm đó làm chủ đề nghiên cứu tiến sĩ.
Năm 2000, tại Đại học California, Irvine (UC Irvine), Fielding bảo vệ luận án "Architectural Styles and the Design of Network-based Software Architectures". Chương 5 của luận án mang tên "Representational State Transfer (REST)" — đây là lần đầu thuật ngữ REST xuất hiện trên giấy.
Một điểm quan trọng cần nhấn mạnh: Fielding không phát minh REST từ con số không. Ông quan sát web đã hoạt động ổn định trên quy mô toàn cầu suốt nửa thập kỷ, tìm ra những đặc tính chung khiến nó scale được, rồi đặt tên cho tập hợp đặc tính đó. REST do vậy là một mô tả descriptive hơn là một thiết kế prescriptive.
Vai trò kép của Fielding — đồng tác giả HTTP và tác giả REST — giải thích tại sao hai khái niệm này khớp nhau tới mức gần như không tách rời. Khi đọc spec HTTP/1.1, bạn sẽ thấy mỗi quyết định (verb idempotent, status code họ 2xx/4xx/5xx, cache header) đều phục vụ một constraint REST cụ thể. Đó không phải trùng hợp.
6 Constraint Của REST
Sáu constraint dưới đây là phần lõi của luận án Fielding. Năm constraint đầu bắt buộc; constraint thứ sáu là optional nhưng vẫn được liệt kê đầy đủ trong spec.
1. Client-Server
Tách rõ vai trò: client lo giao diện và trải nghiệm người dùng, server lo dữ liệu và logic. Hai bên giao tiếp qua một interface ổn định và có thể tiến hoá độc lập. Đây là nguyên tắc separation of concerns (tách quan tâm) ở mức kiến trúc — cho phép thay frontend React bằng iOS native mà không cần đụng vào backend.
2. Stateless
Mỗi request từ client phải chứa đủ thông tin để server xử lý — token, body, header, query đầy đủ. Server không lưu session context giữa các request. Hệ quả: bất kỳ instance nào trong cluster cũng phục vụ được mọi request; thêm node mới là tăng throughput tuyến tính. Đây là nền tảng cho horizontal scaling.
3. Cacheable
Response phải tự khai báo rõ ràng nó có cache được hay không qua các header như Cache-Control, ETag, Last-Modified. Client hoặc proxy trung gian sau đó có thể reuse response cũ thay vì hỏi server lần nữa. Đây là lý do CDN, browser cache, reverse proxy hoạt động xuyên suốt mà không cần coordinate gì với origin.
4. Uniform Interface
Constraint quan trọng nhất, gồm bốn sub-constraint:
- Resource identification: mỗi tài nguyên có một URI duy nhất, ví dụ
/api/v1/products/42. - Manipulation through representation: client tác động lên resource qua một biểu diễn (JSON, XML, ...) chứ không trực tiếp lên dữ liệu nội bộ server.
- Self-descriptive messages: mỗi message mang đủ metadata (Content-Type, status code) để bên nhận hiểu, không phụ thuộc context ngoài.
- HATEOAS (Hypermedia as the Engine of Application State): response chứa link tới các action kế tiếp. Phần lớn API thực tế bỏ qua HATEOAS, nhưng đây vẫn là một phần của REST gốc.
5. Layered System
Client không cần biết nó đang nói chuyện trực tiếp với server hay đi qua các lớp trung gian (load balancer, reverse proxy, API gateway, cache layer). Mỗi lớp chỉ thấy lớp kề bên. Hệ quả: thêm CDN, thêm WAF, thêm rate limiter ở giữa không phá vỡ contract client–server.
6. Code-On-Demand (optional)
Server có thể gửi kèm code thực thi để client chạy — ví dụ điển hình là JavaScript trong response HTML. Đây là constraint duy nhất được Fielding đánh dấu optional; một API thuần JSON không vi phạm REST khi bỏ qua constraint này.
REST vs RPC vs SOAP
Ba paradigm chính cho API trên mạng, mô hình tư duy hoàn toàn khác nhau.
- RPC (Remote Procedure Call): tư duy như gọi function. Endpoint kiểu
POST /getUser,POST /createOrder. Variant phổ biến: JSON-RPC, XML-RPC, và mới hơn là gRPC dùng Protocol Buffers trên HTTP/2. - SOAP (Simple Object Access Protocol): chuẩn nặng từ đầu những năm 2000, payload là XML envelope, đi kèm họ spec WS-* (WS-Security, WS-Addressing, WS-ReliableMessaging). Vẫn còn dùng trong tài chính, viễn thông, ngân hàng cũ.
- REST: tư duy resource. Endpoint là tài nguyên (
/products/42), thao tác bằng HTTP verb (GET,POST,PUT,DELETE). Payload thường là JSON.
Bảng so sánh nhanh:
REST gRPC SOAP
Mô hình Resource Function call Function call
Transport HTTP/1.1, HTTP/2 HTTP/2 HTTP, SMTP, JMS
Payload JSON (thường) Protobuf binary XML envelope
Schema OpenAPI tùy chọn .proto bắt buộc WSDL bắt buộc
Browser-native Có Cần grpc-web Không
Cacheable Có (HTTP cache) Khó Không
Streaming SSE, WebSocket Bidirectional Không
Độ nặng Nhẹ Trung bình Nặng
REST thắng trong phần lớn use case public API vì ba lý do: đơn giản đọc hiểu (JSON người ta nhìn vào hiểu ngay), tận dụng được hạ tầng HTTP có sẵn (cache, CDN, load balancer), và browser hỗ trợ native không cần lib bổ sung. gRPC mạnh hơn cho service-to-service nội bộ nhờ binary và HTTP/2 multiplexing; SOAP gần như chỉ còn được duy trì trong các hệ thống enterprise legacy.
Khi Nào Dùng REST, Khi Nào Không
Không có "best protocol" cho mọi tình huống. Lựa chọn phụ thuộc vào domain, client, và yêu cầu phi chức năng.
REST phù hợp khi:
- API CRUD-heavy, domain map gọn vào resource: user, product, order, post, comment.
- Public API cho bên thứ ba — REST có rào cản học rất thấp, dev nào cũng debug được bằng curl.
- Client là browser, mobile app, hoặc nhiều ngôn ngữ khác nhau — JSON là mẫu số chung.
- Cần tận dụng cache HTTP, CDN, proxy ở mọi lớp.
gRPC phù hợp khi:
- Microservice nội bộ giao tiếp với nhau, yêu cầu thông lượng cao và latency thấp.
- Cần streaming hai chiều (chat, telemetry, AI inference).
- Team chấp nhận đầu tư schema-first qua
.protovà toolchain code-gen.
GraphQL phù hợp khi:
- Client cần tự chọn field để giảm payload (mobile data sparing).
- Có nhiều client khác nhau (web, iOS, Android, TV) muốn shape data riêng từ cùng backend.
- Domain có quan hệ phức tạp, REST sinh ra over-fetching hoặc N+1 endpoint.
Trade-off chính: REST đơn giản nhưng dễ over-fetch và under-fetch; gRPC nhanh nhưng khó debug và không browser-native; GraphQL linh hoạt nhưng cache và authorization phức tạp hơn nhiều. Trong series này, REST là lựa chọn vì Shop API là public-facing, đa client (web + mobile + admin dashboard), và cần leverage HTTP cache.
Series Sẽ Xây Gì
Toàn bộ 316 bài xây dựng một dự án duy nhất tên shop — một REST API e-commerce production-grade. Mỗi bài thêm hoặc refactor code trên cùng codebase, mô phỏng đúng quy trình một sản phẩm thật được lớn lên qua thời gian.
Domain bao gồm: user (customer + admin), product với variant và inventory, category dạng cây phân cấp, cart per-user, order với status flow pending → paid → shipping → delivered, payment qua webhook Stripe-like, review có verified purchase, notification email + real-time qua WebSocket, audit log cho admin action. Tổng cộng ~60 endpoint và 17 bảng PostgreSQL khi hoàn thành.
Tech stack chính:
- Framework:
axum0.8+ trên nềntower. - Async runtime:
tokiomulti-thread. - Database: PostgreSQL 16+ truy cập qua
sqlxcompile-time check. - Cache & queue: Redis 7+ cho session, cache, rate limit, job queue.
- Auth: JWT (HS256/RS256), OAuth2 (Google, GitHub), session cookie.
- Observability:
tracing, OpenTelemetry, Prometheus, Grafana. - Test:
axum-test,testcontainers,criterion, k6. - Deploy: Docker multi-stage, docker-compose, fly.io/k8s preview.
Workspace được tổ chức production-style ngay từ đầu, gồm 7 crate: shop-api (binary HTTP server), shop-core (domain logic + trait), shop-db (PostgreSQL adapter), shop-cache (Redis adapter), shop-worker (background job), shop-cli (admin CLI), shop-common (config, error, telemetry shared). Mọi entity, trait, naming convention sẽ được lock từ những bài đầu tiên và giữ nguyên xuyên suốt 316 bài. Bài kế tiếp đi sâu vào HTTP method — viên gạch xây dựng đầu tiên của uniform interface.
Tổng Kết
- REST là architectural style, không phải protocol, được định nghĩa bởi 6 constraint chứ không phải một spec cụ thể.
- Roy Fielding bảo vệ luận án tiến sĩ tại UC Irvine năm 2000, đặt tên cho tập nguyên tắc mà web đã vận hành sẵn; ông đồng thời là co-author của HTTP/1.1 RFC 2616.
- 6 constraint: client-server, stateless, cacheable, uniform interface, layered system, và code-on-demand (optional).
- Uniform interface là cốt lõi: resource identification qua URI, manipulation qua representation, self-descriptive message, HATEOAS.
- Stateless cho phép scale ngang tuyến tính — mỗi instance phục vụ được mọi request mà không cần coordinate session.
- REST thắng RPC và SOAP cho public HTTP API nhờ tính đơn giản, browser-native, và tận dụng được HTTP cache.
- Series xây Shop E-commerce API: ~60 endpoint, 17 bảng PostgreSQL, workspace 7 crate, production-grade với axum + sqlx + Redis + JWT + Docker.
Bài Tập Củng Cố
Tự trả lời, đáp án ở cuối:
- REST có phải protocol không? Nếu không, nó là gì và quan hệ với HTTP ra sao?
- Liệt kê 6 constraint của REST. Constraint nào là optional theo luận án Fielding?
- Stateless trong REST nghĩa là gì? Vì sao nó là điều kiện tiên quyết cho horizontal scaling?
- So sánh REST với gRPC ở ba khía cạnh: payload format, browser support, cacheability. Khi nào chọn cái nào?
- Shop API series xây một dự án duy nhất hay nhiều demo lẻ? Workspace có bao nhiêu crate, kể tên cả 7.
Đáp án
- REST không phải protocol. Nó là architectural style — tập 6 ràng buộc cho hệ thống phân tán. HTTP là protocol truyền tải; REST là cách tổ chức tư duy trên HTTP. Một câu mô tả ngắn: REST chính là HTTP được dùng đúng cách.
- Sáu constraint: client-server, stateless, cacheable, uniform interface, layered system, code-on-demand. Constraint cuối — code-on-demand — là optional; một API thuần JSON không vi phạm REST khi bỏ qua.
- Stateless nghĩa là mỗi request mang đủ context (token, body, header), server không lưu session giữa các request. Hệ quả: bất kỳ instance nào trong cluster cũng phục vụ được mọi request — thêm node mới là tăng throughput tuyến tính, không cần sticky session hay shared session store ở mức server.
- Payload: REST dùng JSON text, gRPC dùng Protobuf binary. Browser support: REST native, gRPC cần grpc-web proxy. Cache: REST tận dụng HTTP cache (Cache-Control, ETag, CDN); gRPC khó cache. Chọn REST cho public API, đa client browser/mobile, CRUD-heavy. Chọn gRPC cho service-to-service nội bộ cần thông lượng cao, latency thấp, hoặc streaming hai chiều.
- Một dự án duy nhất tên
shop, xuyên suốt 316 bài. Workspace có 7 crate:shop-api(HTTP server binary),shop-core(domain + trait),shop-db(PostgreSQL adapter),shop-cache(Redis adapter),shop-worker(background job binary),shop-cli(admin CLI binary),shop-common(config/error/telemetry shared library).
Bài Tiếp Theo
Bài 2: HTTP Methods: GET, POST, PUT, PATCH, DELETE, ... — đi sâu vào 9 HTTP method, idempotency, safe vs unsafe, quy ước REST.
