TopDev

API là gì? Hướng dẫn toàn diện từ cơ bản đến nâng cao cho lập trình viên

topdev 📖 33 phút đọc 💬 1 phản hồi ✎ đã sửa

API là gì? Khái niệm cơ bản về Application Programming Interface#

API (Application Programming Interface) là giao diện lập trình ứng dụng - một tập hợp các quy tắc, giao thức và công cụ cho phép các ứng dụng phần mềm giao tiếp với nhau. Nói một cách đơn giản, API hoạt động như một cầu nối, cho phép các hệ thống khác nhau trao đổi dữ liệu và chức năng mà không cần biết chi tiết bên trong của nhau.

Tại sao API quan trọng trong phát triển phần mềm?#

API đóng vai trò thiết yếu trong kiến trúc phần mềm hiện đại vì:

  • Tăng tốc độ phát triển: Tái sử dụng các dịch vụ có sẵn thay vì xây dựng từ đầu

  • Tích hợp dễ dàng: Kết nối các hệ thống và ứng dụng khác nhau

  • Bảo mật tốt hơn: Kiểm soát quyền truy cập và bảo vệ dữ liệu nhạy cảm

  • Mở rộng linh hoạt: Phát triển và nâng cấp các thành phần độc lập

Các loại API phổ biến#

REST API: Sử dụng giao thức HTTP, dễ hiểu và triển khai, phù hợp cho web services.

SOAP API: Giao thức nghiêm ngặt với cấu trúc XML, thường dùng trong môi trường doanh nghiệp.

GraphQL API: Cho phép client yêu cầu chính xác dữ liệu cần thiết, giảm over-fetching.

WebSocket API: Hỗ trợ giao tiếp hai chiều real-time giữa client và server.

Top 100 câu hỏi về API thường gặp nhất#

Câu hỏi cơ bản về API (1-20)#

  • API là gì và nó hoạt động như thế nào? API là giao diện cho phép các ứng dụng giao tiếp thông qua các request và response theo định dạng chuẩn.

  • Sự khác biệt giữa API và Web Service? Web Service là một loại API sử dụng giao thức mạng, nhưng không phải API nào cũng là Web Service.

  • REST API là gì? REST (Representational State Transfer) là kiến trúc API sử dụng HTTP methods và stateless communication.

  • HTTP methods trong API là gì? GET (lấy dữ liệu), POST (tạo mới), PUT (cập nhật toàn bộ), PATCH (cập nhật một phần), DELETE (xóa).

  • Endpoint trong API là gì? Endpoint là URL cụ thể nơi API có thể được truy cập để thực hiện một chức năng nhất định.

  • JSON là gì và tại sao nó phổ biến trong API? JSON (JavaScript Object Notation) là định dạng dữ liệu nhẹ, dễ đọc và phân tích cú pháp.

  • Authentication trong API là gì? Là quá trình xác thực danh tính người dùng hoặc ứng dụng trước khi cho phép truy cập API.

  • Authorization khác Authentication như thế nào? Authentication xác định "bạn là ai", Authorization xác định "bạn được phép làm gì".

  • API Key là gì? Là mã định danh duy nhất được sử dụng để xác thực requests đến API.

  • Rate limiting trong API là gì? Là giới hạn số lượng requests một client có thể thực hiện trong khoảng thời gian nhất định.

Câu hỏi về REST API (21-40)#

  • RESTful API cần tuân thủ những nguyên tắc nào? Stateless, client-server architecture, cacheable, uniform interface, layered system.

  • Status code trong API nghĩa là gì? Mã số báo hiệu kết quả của request: 2xx (thành công), 3xx (redirect), 4xx (lỗi client), 5xx (lỗi server).

  • Sự khác biệt giữa PUT và PATCH? PUT thay thế toàn bộ resource, PATCH chỉ cập nhật các trường được chỉ định.

  • CRUD operations trong API là gì? Create (POST), Read (GET), Update (PUT/PATCH), Delete (DELETE).

  • Query parameters và path parameters khác nhau như thế nào? Path parameters là phần của URL path, query parameters được thêm sau dấu "?" để lọc/sắp xếp.

  • Idempotent trong API nghĩa là gì? Một request là idempotent nếu gọi nhiều lần cho kết quả giống gọi một lần.

  • HATEOAS là gì? Hypermedia As The Engine Of Application State - nguyên tắc REST cung cấp links để navigate API.

  • Versioning API là gì và tại sao cần thiết? Là cách quản lý các phiên bản API khác nhau để đảm bảo backward compatibility.

  • Content negotiation trong API là gì? Cho phép client và server thỏa thuận định dạng dữ liệu (JSON, XML) thông qua headers.

  • Stateless trong REST API nghĩa là gì? Server không lưu trữ state của client, mỗi request phải chứa đầy đủ thông tin cần thiết.

Câu hỏi về bảo mật API (41-60)#

  • OAuth 2.0 là gì? Là framework authorization cho phép ứng dụng truy cập tài nguyên thay mặt người dùng mà không cần mật khẩu.

  • JWT (JSON Web Token) hoạt động như thế nào? JWT chứa thông tin được mã hóa và ký số, dùng để xác thực và truyền thông tin an toàn.

  • CORS là gì và tại sao quan trọng? Cross-Origin Resource Sharing cho phép hoặc hạn chế tài nguyên được truy cập từ domain khác.

  • API Gateway là gì? Là điểm vào duy nhất cho tất cả API requests, xử lý routing, authentication, rate limiting.

  • HTTPS quan trọng như thế nào cho API? HTTPS mã hóa dữ liệu truyền tải, bảo vệ khỏi man-in-the-middle attacks.

  • SQL Injection trong API là gì? Là kỹ thuật tấn công bằng cách chèn mã SQL độc hại vào API requests.

  • Input validation trong API là gì? Là quá trình kiểm tra và làm sạch dữ liệu đầu vào để ngăn chặn tấn công.

  • API throttling là gì? Là kỹ thuật kiểm soát tốc độ requests để bảo vệ server khỏi quá tải.

  • Bearer token là gì? Là loại access token được gửi trong Authorization header để xác thực requests.

  • Refresh token khác access token như thế nào? Access token có thời gian sống ngắn, refresh token dùng để lấy access token mới mà không cần đăng nhập lại.

Câu hỏi về GraphQL (61-80)#

  • GraphQL khác REST API như thế nào? GraphQL cho phép client chỉ định chính xác dữ liệu cần thiết, REST trả về cấu trúc cố định.

  • Schema trong GraphQL là gì? Schema định nghĩa types, queries, mutations và relationships giữa dữ liệu.

  • Query và Mutation trong GraphQL khác nhau ra sao? Query dùng để đọc dữ liệu, Mutation dùng để thay đổi dữ liệu.

  • Resolver trong GraphQL là gì? Resolver là hàm xử lý logic để fetch hoặc compute dữ liệu cho từng field.

  • Over-fetching và Under-fetching là gì? Over-fetching: nhận thừa dữ liệu. Under-fetching: cần nhiều requests để lấy đủ dữ liệu.

Câu hỏi về Testing API (81-100)#

  • Integration testing cho API là gì? Kiểm tra tương tác giữa các components và external services.

  • Postman được dùng để làm gì? Tool phổ biến để test, document và monitor APIs.

  • Contract testing trong API là gì? Đảm bảo API provider và consumer tuân thủ cùng một contract đã thỏa thuận.

  • Mock API là gì? Là phiên bản giả lập của API dùng cho testing và development.

  • Load testing API quan trọng như thế nào? Kiểm tra hiệu suất API dưới tải cao để đảm bảo khả năng mở rộng.

[Tiếp tục với 60 câu hỏi còn lại về monitoring, documentation, microservices, webhooks, caching, performance optimization...]

  • API documentation quan trọng ra sao? Documentation giúp developers hiểu cách sử dụng API, giảm support requests.

  • Swagger/OpenAPI là gì? Là specification để mô tả RESTful APIs với công cụ tự động generate documentation.

  • Webhooks khác API như thế nào? Webhooks là event-driven (push), API thường là request-driven (pull).

  • Pagination trong API là gì? Chia dữ liệu lớn thành nhiều trang nhỏ để cải thiện performance.

  • Caching trong API hoạt động ra sao? Lưu trữ tạm thời response để giảm load server và tăng tốc độ response.

  • ETag trong HTTP là gì? Identifier cho phiên bản cụ thể của resource, dùng cho conditional requests.

  • Circuit breaker pattern trong API là gì? Ngăn chặn cascading failures bằng cách tạm dừng requests đến service lỗi.

  • API rate limit thường được set như thế nào? Dựa vào user tier, endpoint sensitivity, và infrastructure capacity.

  • Microservices architecture ảnh hưởng đến API như thế nào? Mỗi service có API riêng, cần API gateway để quản lý và route requests.

  • Service mesh là gì? Infrastructure layer quản lý service-to-service communication trong microservices.

  • API versioning strategies nào phổ biến? URI versioning, header versioning, query parameter versioning.

  • Deprecation policy cho API là gì? Kế hoạch thông báo và loại bỏ các API versions cũ một cách có kiểm soát.

  • Batch requests trong API là gì? Gom nhiều requests vào một call duy nhất để giảm network overhead.

  • Long polling vs WebSocket? Long polling giữ connection mở chờ data, WebSocket là full-duplex real-time communication.

  • API proxy là gì? Trung gian giữa client và server, có thể thêm security, caching, logging.

  • BFF (Backend for Frontend) pattern là gì? Tạo API riêng biệt cho từng loại client (web, mobile) để tối ưu hóa.

  • API composition là gì? Kết hợp responses từ nhiều APIs thành một response duy nhất.

  • Idempotency key là gì? Unique identifier đảm bảo request chỉ được xử lý một lần dù gửi nhiều lần.

  • API monitoring cần track những metrics nào? Response time, error rate, throughput, availability, latency.

  • Blue-green deployment cho API là gì? Chạy đồng thời hai versions, chuyển đổi traffic khi version mới ổn định.

  • Canary deployment trong API là gì? Release version mới cho một nhóm nhỏ users trước khi rollout toàn bộ.

  • API health check endpoint là gì? Endpoint đặc biệt báo cáo trạng thái hoạt động của API service.

  • Request/Response logging nên bao gồm gì? Timestamp, user ID, endpoint, status code, response time, error messages.

  • Compression trong API response làm gì? Giảm kích thước payload bằng gzip/brotli để tăng tốc transfer.

  • Hypermedia controls trong API là gì? Links và actions được nhúng trong response để guide client behavior.

  • Content-Type header quan trọng ra sao? Chỉ định định dạng dữ liệu được gửi, giúp server/client parse đúng.

  • API sandbox environment là gì? Môi trường testing tách biệt để developers thử nghiệm mà không ảnh hưởng production.

  • Partial response trong API là gì? Cho phép client chỉ định fields cụ thể cần trả về để giảm payload.

  • ETL và API có liên quan gì? APIs thường được dùng để extract data trong ETL pipelines.

  • Serverless và API integration ra sao? API Gateway triggers serverless functions (Lambda, Cloud Functions) on-demand.

  • gRPC khác REST API như thế nào? gRPC sử dụng Protocol Buffers, HTTP/2, nhanh hơn và hiệu quả hơn cho inter-service communication.

  • API federation là gì? Kết hợp nhiều APIs thành một unified interface cho clients.

  • Schema validation trong API là gì? Kiểm tra request/response tuân thủ schema đã định nghĩa trước khi xử lý.

  • API analytics thu thập những insights gì? Usage patterns, popular endpoints, user demographics, performance bottlenecks.

  • Middleware trong API là gì? Functions xử lý request/response trước khi đến route handlers (auth, logging, validation).

  • API rate limit strategies phổ biến? Token bucket, leaky bucket, fixed window, sliding window.

  • Mutual TLS (mTLS) trong API là gì? Cả client và server xác thực lẫn nhau bằng certificates.

  • API payload encryption là gì? Mã hóa request/response body ngoài HTTPS transport encryption.

  • Webhook security best practices? Signature verification, IP whitelisting, HTTPS only, idempotency.

  • API deprecation header là gì? HTTP header thông báo endpoint sắp bị loại bỏ và thời gian còn lại.

  • Consumer-driven contracts là gì? Consumers định nghĩa expectations, providers phải tuân thủ contracts này.

  • API marketplace là gì? Platform discover, integrate và monetize APIs từ nhiều providers.

  • Synthetic monitoring cho API là gì? Automated tests liên tục kiểm tra API availability và performance từ nhiều locations.

  • API error handling best practices? Consistent error format, meaningful messages, proper status codes, detailed logging.

  • Asynchronous API patterns nào tồn tại? Callbacks, webhooks, long polling, server-sent events, WebSockets.

  • API request signing là gì? Tạo signature từ request data để verify integrity và authenticity.

  • Scope trong OAuth là gì? Permissions granular xác định access token có quyền gì.

  • API backward compatibility đạt được như thế nào? Optional fields, additive changes only, maintain old endpoints, clear versioning.

  • Bulkhead pattern trong APIs là gì? Cách ly resources để failures trong một component không ảnh hưởng toàn bộ system.

  • API orchestration vs choreography? Orchestration: central controller điều phối. Choreography: services tự phối hợp dựa trên events.

  • API specification formats phổ biến? OpenAPI (Swagger), RAML, API Blueprint, GraphQL Schema.

  • Retry logic trong API clients nên như thế nào? Exponential backoff, max retry attempts, idempotent requests only.

  • API timeout settings cần cân nhắc gì? Network latency, processing time, client experience, resource management.

  • Streaming APIs hoạt động ra sao? Server gửi data continuously qua persistent connection thay vì single response.

  • API change management process là gì? Workflow review, approve, communicate và deploy API changes safely.

  • Multi-tenancy trong APIs như thế nào? Một API instance phục vụ nhiều tenants với data isolation.

  • API security testing bao gồm gì? Penetration testing, vulnerability scanning, authentication/authorization testing.

  • Field-level encryption trong APIs là gì? Encrypt specific sensitive fields thay vì toàn bộ payload.

  • API governance framework bao gồm gì? Standards, policies, lifecycle management, security requirements.

  • API observability khác monitoring như thế nào? Monitoring tracks metrics, observability hiểu "why" through logs, traces, metrics.

Top 10 câu hỏi phỏng vấn về API và cách trả lời xuất sắc#

1. Giải thích REST API và các ràng buộc RESTful#

Câu trả lời mẫu: REST (Representational State Transfer) là architectural style cho distributed systems. Các ràng buộc RESTful bao gồm:

  • Client-Server: Tách biệt concerns, client xử lý UI, server xử lý data

  • Stateless: Mỗi request độc lập, chứa đầy đủ thông tin cần thiết

  • Cacheable: Responses phải khai báo cacheable hay không

  • Uniform Interface: Standardized communication qua HTTP methods

  • Layered System: Client không biết connect trực tiếp server hay qua intermediaries

  • Code on Demand (optional): Server có thể extend client functionality

2. Phân biệt PUT và PATCH methods#

Câu trả lời mẫu: PUT dùng để thay thế hoàn toàn một resource, yêu cầu gửi toàn bộ representation. PATCH dùng để cập nhật một phần resource, chỉ gửi các fields cần thay đổi.

Ví dụ: Để update email của user, PUT cần gửi full user object (name, email, age...), còn PATCH chỉ cần {"email": "new@email.com"}. PUT là idempotent, PATCH có thể không idempotent tùy implementation.

3. Làm thế nào để bảo mật API?#

Câu trả lời mẫu: Tôi áp dụng security theo nhiều layers:

  • Authentication: Implement OAuth 2.0 hoặc JWT cho identity verification

  • Authorization: Role-based access control (RBAC) cho permissions

  • Encryption: HTTPS mandatory cho all endpoints, encrypt sensitive data at rest

  • Input Validation: Sanitize và validate mọi inputs để prevent injection attacks

  • Rate Limiting: Protect khỏi DDoS và brute force attacks

  • API Keys/Tokens: Rotate regularly, store securely

  • CORS Policy: Restrict allowed origins

  • Security Headers: Implement CSP, HSTS, X-Frame-Options

  • Logging & Monitoring: Track suspicious activities và security events

4. Giải thích cách implement pagination trong API#

Câu trả lời mẫu: Có ba approaches phổ biến:

Offset-based pagination: GET /api/users?limit=20&offset=40 Đơn giản nhưng performance kém với large datasets và có thể skip/duplicate records.

Cursor-based pagination: GET /api/users?limit=20&cursor=eyJpZCI6MTAwfQ== Consistent results, performance tốt hơn, nhưng không thể jump to arbitrary pages.

Page-based pagination: GET /api/users?page=3&per_page=20 User-friendly, dễ implement navigation UI.

Tôi thường chọn cursor-based cho feeds/streams và page-based cho admin interfaces.

5. Xử lý API versioning như thế nào?#

Câu trả lời mẫu: Có nhiều strategies:

URI Versioning: /api/v1/users - Rõ ràng, dễ route nhưng có thể duplicate code Header Versioning: Accept: application/vnd.company.v1+json - Cleaner URLs nhưng less visible Query Parameter: /api/users?version=1 - Flexible nhưng có thể conflict với other params

Tôi prefer URI versioning vì transparency và ease of testing. Quan trọng là maintain backward compatibility, deprecate versions gradually với clear timeline, và document migration paths chi tiết.

6. HTTP status codes quan trọng và khi nào dùng?#

Câu trả lời mẫu:

  • 200 OK: Successful GET, PUT, PATCH hoặc DELETE

  • 201 Created: Successful POST tạo resource mới

  • 204 No Content: Successful request không cần return data

  • 400 Bad Request: Invalid syntax hoặc validation errors

  • 401 Unauthorized: Missing hoặc invalid authentication

  • 403 Forbidden: Authenticated nhưng không có permission

  • 404 Not Found: Resource không tồn tại

  • 409 Conflict: Request conflicts với current state (duplicate entry)

  • 429 Too Many Requests: Rate limit exceeded

  • 500 Internal Server Error: Unhandled server error

  • 503 Service Unavailable: Temporary downtime hoặc maintenance

7. Thiết kế API để handle concurrent requests và race conditions#

Câu trả lời mẫu: Tôi sử dụng nhiều techniques:

Optimistic Locking: Sử dụng version numbers hoặc ETags. Client gửi current version, server chỉ update nếu version matches.

Pessimistic Locking: Lock resource trong transaction, nhưng có thể cause bottlenecks.

Idempotency Keys: Client gửi unique key, server track processed keys để avoid duplicate operations.

Database Transactions: ACID properties đảm bảo consistency cho related operations.

Message Queues: Serialize concurrent requests cho sensitive operations.

Ví dụ cho payment API, tôi combine idempotency keys với database transactions để guarantee exactly-once processing.

8. Giải thích caching strategies cho APIs#

Câu trả lời mẫu: Caching giảm latency và server load:

Client-side caching: Browser cache dựa trên Cache-Control, ETag, Last-Modified headers.

CDN caching: Distribute static hoặc rarely-changing content globally.

Application-level caching: Redis/Memcached cache computed results, database queries.

HTTP caching directives:

  • Cache-Control: public, max-age=3600 cho public data

  • Cache-Control: private, max-age=300 cho user-specific data

  • Cache-Control: no-store cho sensitive data

Cache invalidation: Implement strategies như TTL, event-based invalidation, hoặc cache-aside pattern. Remember: "There are only two hard things in Computer Science: cache invalidation and naming things."

9. Xử lý errors và exceptions trong API như thế nào?#

Câu trả lời mẫu: Consistent error handling structure:

{ "error": { "code": "VALIDATION_ERROR", "message": "Invalid input data", "details": [ { "field": "email", "issue": "Invalid email format" } ], "request_id": "req_abc123" } }

Best practices tôi follow:

  • Use appropriate HTTP status codes

  • Provide machine-readable error codes cho programmatic handling

  • Include human-readable messages

  • Add detailed field-level errors cho validation

  • Include request_id để tracing và debugging

  • Log errors với sufficient context nhưng không expose sensitive data

  • Document possible errors trong API documentation

  • Implement global exception handlers để catch unhandled errors

10. Thiết kế API cho microservices architecture#

Câu trả lời mẫu: Trong microservices, API design critical cho service communication:

API Gateway Pattern: Single entry point route requests đến appropriate services, handle cross-cutting concerns (auth, rate limiting, logging).

Service-to-Service Communication:

  • Synchronous: REST/gRPC cho immediate responses

  • Asynchronous: Message queues (RabbitMQ, Kafka) cho loosely coupled communication

API Composition: Aggregate data từ multiple services, careful về performance implications.

Contract Testing: Ensure provider và consumer agree on API contracts, prevent breaking changes.

Circuit Breaker Pattern: Prevent cascading failures khi một service down.

Service Discovery: Dynamic routing đến healthy service instances.

Backward Compatibility: Critical vì services deploy independently với different schedules.

1 phản hồi

  1. topdev #1

    Các lỗi thường gặp khi lập trình viên code API#

    1. Không validate input data đầy đủ#

    Vấn đề: Tin tưởng client data mà không kiểm tra dẫn đến security vulnerabilities, data corruption, và system crashes.

    Hậu quả: SQL injection, XSS attacks, invalid data trong database, server crashes.

    Giải pháp:

    • Implement comprehensive input validation cho tất cả endpoints

    • Sử dụng validation libraries như Joi, Yup, hoặc built-in framework validators

    • Validate data type, format, length, range constraints

    • Sanitize inputs để remove malicious code

    • Never trust client-side validation alone

    Ví dụ code (Node.js/Express): ` const { body, validationResult } = require('express-validator');

    app.post('/api/users', [ body('email').isEmail().normalizeEmail(), body('age').isInt({ min: 18, max: 120 }), body('name').trim().isLength({ min: 2, max: 50 }) ], (req, res) => { const errors = validationResult(req); if (!errors.isEmpty()) { return res.status(400).json({ errors: errors.array() }); } // Process valid data }); `

    2. Sử dụng sai HTTP status codes#

    Vấn đề: Trả về 200 OK cho mọi response, hoặc sử dụng không nhất quán status codes khiến clients khó handle errors.

    Ví dụ sai lầm:

    • Trả 200 với {"success": false} thay vì proper error code

    • Dùng 500 cho validation errors (should be 400)

    • Dùng 401 khi có permission (should be 403)

    Giải pháp: Follow HTTP semantics chính xác:

    • 2xx cho success

    • 4xx cho client errors (bad request, unauthorized, not found)

    • 5xx cho server errors (internal error, service unavailable)

    3. Không implement proper error handling#

    Vấn đề: Expose stack traces và sensitive information trong error responses, hoặc generic errors không giúp debugging.

    Ví dụ lỗi: // BAD: Exposes internal details try { await database.query(sql); } catch (error) { res.status(500).json({ error: error.message }); // Might expose SQL query, file paths }

    Giải pháp đúng: // GOOD: Structured error handling try { await database.query(sql); } catch (error) { logger.error('Database query failed', { error, userId }); res.status(500).json({ error: 'An unexpected error occurred', requestId: req.id }); }

    4. Bỏ qua pagination cho large datasets#

    Vấn đề: Trả về toàn bộ records trong một response gây memory issues, slow response times, và poor user experience.

    Hậu quả: Server crashes với large datasets, timeouts, excessive bandwidth usage.

    Giải pháp: Always implement pagination cho list endpoints: ` // Good pagination implementation app.get('/api/products', async (req, res) => { const page = parseInt(req.query.page) || 1; const limit = Math.min(parseInt(req.query.limit) || 20, 100); const offset = (page - 1) * limit;

    const products = await db.products .findMany({ skip: offset, take: limit }); const total = await db.products.count();

    res.json({ data: products, pagination: { page, limit, total, totalPages: Math.ceil(total / limit) } }); }); `

    5. Không secure endpoints đúng cách#

    Vấn đề: Thiếu authentication/authorization cho sensitive endpoints, weak token management, không encrypt sensitive data.

    Lỗi phổ biến:

    • Public endpoints có thể modify hoặc delete data

    • Token không expire hoặc không có refresh mechanism

    • Store passwords plain text hoặc use weak hashing

    • Không implement rate limiting

    Giải pháp:

    ` // Proper authentication middleware const authenticateToken = (req, res, next) => { const authHeader = req.headers['authorization']; const token = authHeader && authHeader.split(' ')[1];

    if (!token) { return res.status(401).json({ error: 'Access token required' }); }

    jwt.verify(token, process.env.JWT_SECRET, (err, user) => { if (err) { return res.status(403).json({ error: 'Invalid or expired token' }); } req.user = user; next(); }); };

    // Authorization middleware const authorize = (...roles) => { return (req, res, next) => { if (!roles.includes(req.user.role)) { return res.status(403).json({ error: 'Insufficient permissions' }); } next(); }; };

    // Usage app.delete('/api/users/:id', authenticateToken, authorize('admin'), deleteUser ); `

    6. Hardcode configuration và credentials#

    Vấn đề: Lưu API keys, database passwords, secrets trực tiếp trong code dẫn đến security breaches khi code leak.

    Ví dụ sai: ` // NEVER DO THIS const dbConnection = mysql.createConnection({ host: 'localhost', user: 'root', password: 'admin123', // Hardcoded password database: 'production_db' });

    const apiKey = 'sk_live_abc123xyz'; // Exposed API key `

    Giải pháp đúng: ` // Use environment variables require('dotenv').config();

    const dbConnection = mysql.createConnection({ host: process.env.DB_HOST, user: process.env.DB_USER, password: process.env.DB_PASSWORD, database: process.env.DB_NAME });

    const apiKey = process.env.STRIPE_API_KEY; `

    7. Không handle race conditions và concurrent requests#

    Vấn đề: Multiple simultaneous requests modifying cùng resource gây data inconsistency, duplicate records, hoặc lost updates.

    Ví dụ kịch bản: ` // BAD: Race condition in inventory management app.post('/api/orders', async (req, res) => { const product = await db.products.findById(req.body.productId);

    if (product.stock >= req.body.quantity) { // Time gap here - another request might also pass this check await db.products.update(product.id, { stock: product.stock - req.body.quantity }); await db.orders.create(req.body); res.json({ success: true }); } }); `

    Giải pháp với transactions và locking: ` // GOOD: Use database transactions app.post('/api/orders', async (req, res) => { const transaction = await db.transaction();

    try { const product = await db.products.findById( req.body.productId, { transaction, lock: true } // Pessimistic lock );

    if (product.stock < req.body.quantity) {
      await transaction.rollback();
      return res.status(400).json({ 
        error: 'Insufficient stock' 
      });
    }
    
    await db.products.update(product.id, {
      stock: product.stock - req.body.quantity
    }, { transaction });
    
    await db.orders.create(req.body, { transaction });
    await transaction.commit();
    
    res.status(201).json({ success: true });
    

    } catch (error) { await transaction.rollback(); throw error; } }); `

    8. Poor database query optimization#

    Vấn đề: N+1 queries, missing indexes, loading unnecessary data làm API chậm và tốn resources.

    Ví dụ N+1 problem: ` // BAD: N+1 queries app.get('/api/posts', async (req, res) => { const posts = await db.posts.findMany(); // 1 query

    for (let post of posts) { // N queries (one for each post) post.author = await db.users.findById(post.authorId); post.comments = await db.comments.findByPostId(post.id); }

    res.json(posts); }); `

    Giải pháp optimized: ` // GOOD: Eager loading với joins app.get('/api/posts', async (req, res) => { const posts = await db.posts.findMany({ include: { author: true, comments: { select: { id: true, content: true, createdAt: true } } } });

    res.json(posts); });

    // Add indexes for frequently queried fields // CREATE INDEX idx_posts_author ON posts(author_id); // CREATE INDEX idx_comments_post ON comments(post_id); `

    9. Không implement rate limiting#

    Vấn đề: API dễ bị abuse, DDoS attacks, và excessive usage từ một client ảnh hưởng tất cả users.

    Hậu quả: Server overload, increased costs, poor performance cho legitimate users.

    Giải pháp với rate limiting: ` const rateLimit = require('express-rate-limit'); const RedisStore = require('rate-limit-redis');

    // Basic rate limiting const limiter = rateLimit({ windowMs: 15 * 60 * 1000, // 15 minutes max: 100, // limit each IP to 100 requests per windowMs message: 'Too many requests, please try again later', standardHeaders: true, legacyHeaders: false, // Use Redis for distributed systems store: new RedisStore({ client: redisClient, prefix: 'rl:' }) });

    // Apply to all routes app.use('/api/', limiter);

    // Stricter limits for sensitive endpoints const strictLimiter = rateLimit({ windowMs: 60 * 60 * 1000, // 1 hour max: 5 });

    app.post('/api/auth/login', strictLimiter, loginHandler); `

    10. Inconsistent naming conventions#

    Vấn đề: Mixed naming styles (camelCase, snake_case, PascalCase) trong URLs, parameters, và response fields gây confusion.

    Ví dụ inconsistent: ` // BAD: Mixed conventions GET /api/Users // PascalCase GET /api/user-posts // kebab-case POST /api/createOrder // camelCase with verb

    Response: { UserID: 123, // PascalCase first_name: "John", // snake_case emailAddress: "..." // camelCase } `

    Giải pháp consistent: ` // GOOD: Consistent RESTful conventions GET /api/users // lowercase, plural nouns GET /api/users/:id/posts // nested resources POST /api/orders // noun, not verb

    Response: { userId: 123, firstName: "John", emailAddress: "john@example.com" // All camelCase consistently } `

    11. Không log và monitor API properly#

    Vấn đề: Khi có issues, không có đủ information để debug. Không track API performance và usage patterns.

    Giải pháp comprehensive logging: ` const winston = require('winston');

    const logger = winston.createLogger({ level: 'info', format: winston.format.json(), transports: [ new winston.transports.File({ filename: 'error.log', level: 'error' }), new winston.transports.File({ filename: 'combined.log' }) ] });

    // Request logging middleware app.use((req, res, next) => { const startTime = Date.now();

    res.on('finish', () => { const duration = Date.now() - startTime; logger.info({ method: req.method, url: req.url, statusCode: res.statusCode, duration, userAgent: req.get('user-agent'), ip: req.ip, userId: req.user?.id }); });

    next(); });

    // Error logging app.use((err, req, res, next) => { logger.error({ message: err.message, stack: err.stack, url: req.url, method: req.method, userId: req.user?.id });

    res.status(500).json({ error: 'Internal server error', requestId: req.id }); }); `

    12. Returning quá nhiều hoặc quá ít data#

    Vấn đề: Over-fetching (trả về toàn bộ object với sensitive fields) hoặc under-fetching (client cần nhiều requests).

    Ví dụ over-fetching: // BAD: Exposing sensitive data app.get('/api/users/:id', async (req, res) => { const user = await db.users.findById(req.params.id); res.json(user); // Includes password hash, ssn, etc. });

    Giải pháp selective fields: ` // GOOD: Select only necessary fields app.get('/api/users/:id', async (req, res) => { const user = await db.users.findById(req.params.id, { select: { id: true, name: true, email: true, avatar: true, createdAt: true // Exclude password, ssn, etc. } });

    res.json(user); });

    // Support field selection via query params app.get('/api/users/:id', async (req, res) => { const allowedFields = ['id', 'name', 'email', 'avatar']; const fields = req.query.fields ? req.query.fields.split(',').filter(f => allowedFields.includes(f)) : allowedFields;

    const user = await db.users.findById(req.params.id, { select: fields.reduce((obj, field) => { obj[field] = true; return obj; }, {}) });

    res.json(user); }); `

    13. Không version API từ đầu#

    Vấn đề: Breaking changes phá vỡ existing clients, không có cách để maintain backward compatibility.

    Giải pháp: ` // Implement versioning from the start const v1Router = express.Router(); const v2Router = express.Router();

    // Version 1 v1Router.get('/users', async (req, res) => { const users = await db.users.findMany({ select: { id: true, name: true, email: true } }); res.json(users); });

    // Version 2 with additional fields v2Router.get('/users', async (req, res) => { const users = await db.users.findMany({ select: { id: true, name: true, email: true, avatar: true, preferences: true } }); res.json({ data: users, version: '2.0' }); });

    app.use('/api/v1', v1Router); app.use('/api/v2', v2Router);

    // Deprecation warnings for old versions v1Router.use((req, res, next) => { res.set('Warning', '299 - "API v1 is deprecated. Please migrate to v2"'); next(); }); `

    14. Không test API thoroughly#

    Vấn đề: Bugs in production, unexpected behaviors, security vulnerabilities không được phát hiện trước deployment.

    Giải pháp comprehensive testing: ` // Unit tests describe('User API', () => { it('should create a new user', async () => { const response = await request(app) .post('/api/users') .send({ name: 'John Doe', email: 'john@example.com', password: 'SecurePass123!' }) .expect(201);

    expect(response.body).toHaveProperty('id');
    expect(response.body.email).toBe('john@example.com');
    expect(response.body).not.toHaveProperty('password');
    

    });

    it('should return 400 for invalid email', async () => { await request(app) .post('/api/users') .send({ name: 'John Doe', email: 'invalid-email', password: 'SecurePass123!' }) .expect(400); });

    it('should require authentication', async () => { await request(app) .get('/api/users/profile') .expect(401); });

    it('should handle rate limiting', async () => { const requests = Array(101).fill().map(() => request(app).get('/api/public') );

    const responses = await Promise.all(requests);
    const rateLimited = responses.filter(r => r.status === 429);
    expect(rateLimited.length).toBeGreaterThan(0);
    

    }); }); `

    15. Bỏ qua CORS configuration#

    Vấn đề: Browser blocks requests từ frontend, hoặc CORS quá permissive tạo security risks.

    Giải pháp proper CORS setup: ` const cors = require('cors');

    // Development - more permissive if (process.env.NODE_ENV === 'development') { app.use(cors()); }

    // Production - strict configuration if (process.env.NODE_ENV === 'production') { const corsOptions = { origin: function (origin, callback) { const allowedOrigins = [ 'https://yourdomain.com', 'https://app.yourdomain.com' ];

      if (!origin || allowedOrigins.indexOf(origin) !== -1) {
        callback(null, true);
      } else {
        callback(new Error('Not allowed by CORS'));
      }
    },
    credentials: true,
    methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH'],
    allowedHeaders: ['Content-Type', 'Authorization'],
    exposedHeaders: ['X-Total-Count'],
    maxAge: 86400 // 24 hours
    

    };

    app.use(cors(corsOptions)); } `

    Nghiên cứu và thực hành API#

    Tài nguyên học tập chất lượng cao#

    Documentation và Specifications

    • OpenAPI Specification: Standard để define RESTful APIs

    • MDN Web Docs: HTTP protocol, methods, status codes chi tiết

    • REST API Tutorial: restfulapi.net - best practices và patterns

    • GraphQL Documentation: Official GraphQL guides và tutorials

    Courses và Learning Platforms

    • Udemy: "REST API Design, Development & Management"

    • Pluralsight: API development tracks với hands-on labs

    • FreeCodeCamp: Free tutorials về RESTful APIs

    • Postman Learning Center: Interactive API testing tutorials

    Books nên đọc

    • "RESTful Web APIs" by Leonard Richardson

    • "Designing Data-Intensive Applications" by Martin Kleppmann

    • "Building Microservices" by Sam Newman

    • "API Design Patterns" by JJ Geewax

    Lab thực hành từ cơ bản đến nâng cao#

    Lab 1: Xây dựng REST API cơ bản (Beginner)

    Mục tiêu: Tạo simple CRUD API cho blog posts

    Setup project: mkdir blog-api && cd blog-api npm init -y npm install express body-parser dotenv npm install --save-dev nodemon

    Implement basic endpoints: ` // server.js const express = require('express'); const app = express();

    app.use(express.json());

    let posts = [ { id: 1, title: 'First Post', content: 'Hello World', createdAt: new Date() } ];

    // GET all posts app.get('/api/posts', (req, res) => { res.json({ data: posts, count: posts.length }); });

    // GET single post app.get('/api/posts/:id', (req, res) => { const post = posts.find(p => p.id === parseInt(req.params.id)); if (!post) return res.status(404).json({ error: 'Post not found' }); res.json(post); });

    // CREATE post app.post('/api/posts', (req, res) => { const { title, content } = req.body;

    if (!title || !content) { return res.status(400).json({ error: 'Title and content required' }); }

    const newPost = { id: posts.length + 1, title, content, createdAt: new Date() };

    posts.push(newPost); res.status(201).json(newPost); });

    // UPDATE post app.put('/api/posts/:id', (req, res) => { const post = posts.find(p => p.id === parseInt(req.params.id)); if (!post) return res.status(404).json({ error: 'Post not found' });

    post.title = req.body.title || post.title; post.content = req.body.content || post.content; post.updatedAt = new Date();

    res.json(post); });

    // DELETE post app.delete('/api/posts/:id', (req, res) => { const index = posts.findIndex(p => p.id === parseInt(req.params.id)); if (index === -1) return res.status(404).json({ error: 'Post not found' });

    posts.splice(index, 1); res.status(204).send(); });

    const PORT = process.env.PORT || 3000; app.listen(PORT, () => console.log(Server running on port ${PORT})); `

    Thực hành với Postman/cURL: `

    Create post

    curl -X POST http://localhost:3000/api/posts
    -H "Content-Type: application/json"
    -d '{"title":"My Post","content":"This is content"}'

    Get all posts

    curl http://localhost:3000/api/posts

    Get specific post

    curl http://localhost:3000/api/posts/1

    Update post

    curl -X PUT http://localhost:3000/api/posts/1
    -H "Content-Type: application/json"
    -d '{"title":"Updated Title"}'

    Delete post

    curl -X DELETE http://localhost:3000/api/posts/1 `

    Lab 2: Authentication và Authorization (Intermediate)

    Mục tiêu: Implement JWT authentication và role-based access control

    ` const jwt = require('jsonwebtoken'); const bcrypt = require('bcryptjs');

    // User database (in-memory for demo) const users = [];

    // Register endpoint app.post('/api/auth/register', async (req, res) => { try { const { username, email, password, role } = req.body;

    // Validation
    if (!username || !email || !password) {
      return res.status(400).json({ error: 'All fields required' });
    }
    
    // Check existing user
    if (users.find(u => u.email === email)) {
      return res.status(409).json({ error: 'User already exists' });
    }
    
    // Hash password
    const hashedPassword = await bcrypt.hash(password, 10);
    
    const user = {
      id: users.length + 1,
      username,
      email,
      password: hashedPassword,
      role: role || 'user',
      createdAt: new Date()
    };
    
    users.push(user);
    
    // Remove password from response
    const { password: _, ...userWithoutPassword } = user;
    res.status(201).json(userWithoutPassword);
    

    } catch (error) { res.status(500).json({ error: 'Registration failed' }); } });

    // Login endpoint app.post('/api/auth/login', async (req, res) => { try { const { email, password } = req.body;

    const user = users.find(u => u.email === email);
    if (!user) {
      return res.status(401).json({ error: 'Invalid credentials' });
    }
    
    const validPassword = await bcrypt.compare(password, user.password);
    if (!validPassword) {
      return res.status(401).json({ error: 'Invalid credentials' });
    }
    
    // Generate tokens
    const accessToken = jwt.sign(
      { id: user.id, email: user.email, role: user.role },
      process.env.JWT_SECRET,
      { expiresIn: '15m' }
    );
    
    const refreshToken = jwt.sign(
      { id: user.id },
      process.env.JWT_REFRESH_SECRET,
      { expiresIn: '7d' }
    );
    
    res.json({ accessToken, refreshToken, user: {
      id: user.id,
      username: user.username,
      email: user.email,
      role: user.role
    }});
    

    } catch (error) { res.status(500).json({ error: 'Login failed' }); } });

    // Authentication middleware const authenticateToken = (req, res, next) => { const authHeader = req.headers['authorization']; const token = authHeader && authHeader.split(' ')[1];

    if (!token) { return res.status(401).json({ error: 'Access token required' }); }

    jwt.verify(token, process.env.JWT_SECRET, (err, user) => { if (err) { return res.status(403).json({ error: 'Invalid or expired token' }); } req.user = user; next(); }); };

    // Authorization middleware const authorize = (...allowedRoles) => { return (req, res, next) => { if (!req.user) { return res.status(401).json({ error: 'Unauthorized' }); }

    if (!allowedRoles.includes(req.user.role)) {
      return res.status(403).json({ error: 'Insufficient permissions' });
    }
    
    next();
    

    }; };

    // Protected routes examples app.get('/api/profile', authenticateToken, (req, res) => { const user = users.find(u => u.id === req.user.id); const { password, ...userWithoutPassword } = user; res.json(userWithoutPassword); });

    app.delete('/api/users/:id', authenticateToken, authorize('admin'), (req, res) => { // Only admins can delete users const index = users.findIndex(u => u.id === parseInt(req.params.id)); if (index === -1) { return res.status(404).json({ error: 'User not found' }); } users.splice(index, 1); res.status(204).send(); } ); `

    Lab 3: Database Integration và Advanced Features (Advanced)

    Setup với PostgreSQL và Prisma: npm install @prisma/client npm install --save-dev prisma npx prisma init

    Prisma schema: ` // schema.prisma datasource db { provider = "postgresql" url = env("DATABASE_URL") }

    generator client { provider = "prisma-client-js" }

    model User { id Int @id @default(autoincrement()) email String @unique name String? posts Post[] createdAt DateTime @default(now()) updatedAt DateTime @updatedAt }

    model Post { id Int @id @default(autoincrement()) title String content String? published Boolean @default(false) author User @relation(fields: [authorId], references: [id]) authorId Int createdAt DateTime @default(now()) updatedAt DateTime @updatedAt

    @@index([authorId]) } `

    API với pagination, filtering, sorting: ` const { PrismaClient } = require('@prisma/client'); const prisma = new PrismaClient();

    app.get('/api/posts', async (req, res) => { try { const { page = 1, limit = 10, sortBy = 'createdAt', order = 'desc', search, published } = req.query;

    const skip = (parseInt(page) - 1) * parseInt(limit);
    const take = parseInt(limit);
    
    // Build where clause
    const where = {};
    if (search) {
      where.OR = [
        { title: { contains: search, mode: 'insensitive' } },
        { content: { contains: search, mode: 'insensitive' } }
      ];
    }
    if (published !== undefined) {
      where.published = published === 'true';
    }
    
    // Execute queries in parallel
    const [posts, total] = await Promise.all([
      prisma.post.findMany({
        where,
        skip,
        take,
        orderBy: { [sortBy]: order },
        include: {
          author: {
            select: {
              id: true,
              name: true,
              email: true
            }
          }
        }
      }),
      prisma.post.count({ where })
    ]);
    
    res.json({
      data: posts,
      pagination: {
        page: parseInt(page),
        limit: parseInt(limit),
        total,
        totalPages: Math.ceil(total / parseInt(limit))
      }
    });
    

    } catch (error) { console.error('Error fetching posts:', error); res.status(500).json({ error: 'Failed to fetch posts' }); } }); `

    Project Ideas để practice#

    1. Task Management API Features: Users, projects, tasks, comments, file attachments, notifications, real-time updates with WebSockets.

    2. E-commerce API Features: Products, categories, cart, orders, payments (Stripe integration), inventory management, reviews.

    3. Social Media API Features: Users, posts, likes, comments, follows, feed algorithm, image uploads (S3), notifications.

    4. Weather Aggregation API Features: Integrate multiple weather APIs, caching, location-based queries, historical data, forecasts.

    5. URL Shortener API Features: Create short URLs, analytics, custom aliases, expiration, rate limiting, QR codes.

    Tools cần thành thạo#

    API Development

    • Postman: Testing, documentation, collections

    • Insomnia: Alternative REST client

    • Thunder Client: VS Code extension

    Documentation

    • Swagger/OpenAPI: Interactive API documentation

    • Redoc: Beautiful API reference documentation

    • API Blueprint: Markdown-based API documentation

    Monitoring & Testing

    • Newman: Run Postman collections in CI/CD

    • Artillery: Load testing và performance

    • Jest/Mocha: Unit và integration testing

    • Supertest: HTTP assertions

    Debugging & Analysis

    • Wireshark: Network protocol analyzer

    • Charles Proxy: HTTP proxy cho debugging

    • ngrok: Expose local APIs cho testing webhooks

    Best practices checklist#

    Security

    • Implement authentication và authorization

    • Use HTTPS everywhere

    • Validate và sanitize all inputs

    • Implement rate limiting

    • Keep dependencies updated

    Performance

    • Use database indexes properly

    • Implement caching strategies

    • Enable compression

    • Optimize queries (avoid N+1)

    • Use pagination for large datasets

    Reliability

    • Implement proper error handling

    • Use database transactions

    • Add request timeouts

    • Implement retry logic with backoff

    • Monitor và log everything

    Maintainability

    • Follow consistent naming conventions

    • Write comprehensive tests

    • Document your API thoroughly

    • Version your API

    • Use environment variables for config

    User Experience

    • Provide clear error messages

    • Return appropriate status codes

    • Include helpful metadata in responses

    • Support filtering, sorting, searching

    • Keep responses consistent



    Kết luận: API development là kỹ năng cốt lõi cho mọi backend developer. Bằng cách hiểu rõ concepts, tránh common mistakes, và thực hành thường xuyên với real-world projects, bạn sẽ xây dựng được APIs robust, scalable và maintainable. Hãy bắt đầu với basics, sau đó gradually tackle advanced topics như authentication, caching, và microservices architecture.

Bài liên quan trong #Học Lập Trình

✓ Đã sao chép link