feat: adding new skills, including testing patterns and methodologies, along with bundled resources for better usability.

This commit is contained in:
duthaho
2026-03-30 12:18:00 +07:00
parent 0ff5ae4082
commit 7fa9a48c6c
89 changed files with 25808 additions and 923 deletions
@@ -0,0 +1,175 @@
# HTTP Status Codes for REST APIs
Quick reference for selecting the correct HTTP status code in REST API responses.
---
## 2xx Success
| Code | Name | When to Use |
|------|------|-------------|
| `200` | OK | General success. GET returns data, PUT/PATCH returns updated resource. |
| `201` | Created | POST successfully created a resource. Include `Location` header. |
| `202` | Accepted | Request accepted for async processing. Return a job/task ID. |
| `204` | No Content | DELETE success or PUT/PATCH with no response body needed. |
**Guidelines:**
- `200` is the default success response for GET, PUT, PATCH
- `201` must be used when a new resource is created (POST)
- `204` is preferred for DELETE (no body to return)
- `202` signals "we got it, processing later" -- return a status URL
```json
// 201 Created response
{
"id": "usr_abc123",
"name": "Jane Doe",
"created_at": "2025-01-15T10:30:00Z"
}
// Header: Location: /api/v1/users/usr_abc123
```
---
## 3xx Redirection
| Code | Name | When to Use |
|------|------|-------------|
| `301` | Moved Permanently | Resource URL changed permanently. Clients should update bookmarks. |
| `302` | Found | Temporary redirect. Original URL still valid. |
| `304` | Not Modified | Conditional GET -- resource unchanged since `If-None-Match`/`If-Modified-Since`. |
| `307` | Temporary Redirect | Like 302 but preserves HTTP method. Use for API redirects. |
| `308` | Permanent Redirect | Like 301 but preserves HTTP method. |
**Guidelines:**
- Prefer `307`/`308` over `302`/`301` in APIs (method preservation)
- `304` reduces bandwidth when clients cache responses
- Always include `Location` header with redirect responses
---
## 4xx Client Errors
| Code | Name | When to Use |
|------|------|-------------|
| `400` | Bad Request | Malformed syntax, invalid JSON, failed validation. |
| `401` | Unauthorized | Missing or invalid authentication credentials. |
| `403` | Forbidden | Authenticated but lacks permission for this resource. |
| `404` | Not Found | Resource does not exist at this URL. |
| `405` | Method Not Allowed | HTTP method not supported on this endpoint. |
| `409` | Conflict | Request conflicts with current state (duplicate, version mismatch). |
| `410` | Gone | Resource existed but has been permanently deleted. |
| `415` | Unsupported Media Type | Content-Type header not supported. |
| `422` | Unprocessable Entity | Valid JSON but semantically invalid (business rule violation). |
| `429` | Too Many Requests | Rate limit exceeded. Include `Retry-After` header. |
**Guidelines:**
- `400` for structural issues (bad JSON, missing required fields)
- `422` for business logic failures (email already taken, invalid state transition)
- `401` means "who are you?" -- `403` means "I know who you are, but no"
- `409` for optimistic locking failures and unique constraint violations
- `429` must include `Retry-After` header with seconds until retry
```json
// 422 Unprocessable Entity
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Request validation failed",
"details": [
{ "field": "email", "message": "Email already registered" },
{ "field": "age", "message": "Must be 18 or older" }
]
}
}
```
```json
// 429 Too Many Requests
// Header: Retry-After: 60
{
"error": {
"code": "RATE_LIMITED",
"message": "Rate limit exceeded. Try again in 60 seconds."
}
}
```
---
## 5xx Server Errors
| Code | Name | When to Use |
|------|------|-------------|
| `500` | Internal Server Error | Unhandled exception. Generic server failure. |
| `501` | Not Implemented | Endpoint exists but functionality not built yet. |
| `502` | Bad Gateway | Upstream service returned invalid response. |
| `503` | Service Unavailable | Server overloaded or in maintenance. Include `Retry-After`. |
| `504` | Gateway Timeout | Upstream service did not respond in time. |
**Guidelines:**
- `500` should never expose stack traces in production
- `503` should include `Retry-After` header and a maintenance message
- Log all 5xx errors with request context for debugging
- Return a consistent error body format for all 5xx responses
```json
// 500 Internal Server Error (production)
{
"error": {
"code": "INTERNAL_ERROR",
"message": "An unexpected error occurred. Please try again.",
"request_id": "req_7f3a9b2c"
}
}
```
---
## Decision Flowchart
```
Request received
|
+-- Is it valid syntax? -- NO --> 400 Bad Request
|
+-- Is caller authenticated? -- NO --> 401 Unauthorized
|
+-- Is caller authorized? -- NO --> 403 Forbidden
|
+-- Does resource exist? -- NO --> 404 Not Found
|
+-- Is it rate-limited? -- YES --> 429 Too Many Requests
|
+-- Does it pass business rules? -- NO --> 422 Unprocessable Entity
|
+-- Any conflicts? -- YES --> 409 Conflict
|
+-- Server error? -- YES --> 500 Internal Server Error
|
+-- Success!
GET --> 200 OK
POST --> 201 Created
PUT --> 200 OK
PATCH --> 200 OK
DELETE --> 204 No Content
```
---
## Standard Error Response Format
Use a consistent structure across all error responses:
```json
{
"error": {
"code": "MACHINE_READABLE_CODE",
"message": "Human-readable description",
"details": [],
"request_id": "req_..."
}
}
```
*Reference: [RFC 9110 - HTTP Semantics](https://httpwg.org/specs/rfc9110.html), [RFC 9457 - Problem Details](https://www.rfc-editor.org/rfc/rfc9457)*
@@ -0,0 +1,196 @@
# REST API Naming Conventions
Guidelines for consistent, predictable REST endpoint design.
---
## Core Rules
1. **Use plural nouns** for resource collections
2. **Use kebab-case** for multi-word resources
3. **Use path parameters** for identity, query parameters for filtering
4. **Never use verbs** in URLs (HTTP methods convey the action)
5. **Use lowercase** exclusively
---
## Resource Naming
| Pattern | Example | Notes |
|---------|---------|-------|
| Collection | `/users` | Plural noun |
| Single resource | `/users/{id}` | Path parameter |
| Multi-word resource | `/order-items` | Kebab-case |
| Nested resource | `/users/{id}/orders` | Parent-child relationship |
| Deep nesting (avoid) | `/users/{id}/orders/{oid}/items` | Max 2 levels deep |
| Singleton sub-resource | `/users/{id}/profile` | One-to-one relationship |
### Good
```
GET /users
GET /users/123
POST /users
PUT /users/123
DELETE /users/123
GET /users/123/orders
GET /order-items
GET /user-profiles/123
```
### Bad
```
GET /getUsers # verb in URL
GET /user/123 # singular collection
GET /Users # uppercase
POST /users/create # redundant verb
GET /user_profiles # snake_case
DELETE /users/123/delete # verb in URL
```
---
## CRUD Mapping
| Action | Method | Endpoint | Request Body | Response |
|--------|--------|----------|-------------|----------|
| List | `GET` | `/resources` | None | `200` + array |
| Create | `POST` | `/resources` | Resource data | `201` + created |
| Read | `GET` | `/resources/{id}` | None | `200` + object |
| Update (full) | `PUT` | `/resources/{id}` | Full resource | `200` + updated |
| Update (partial) | `PATCH` | `/resources/{id}` | Partial data | `200` + updated |
| Delete | `DELETE` | `/resources/{id}` | None | `204` |
---
## Nested Resources
Use nesting to express clear parent-child relationships.
```
# User's orders (user owns orders)
GET /users/{userId}/orders
POST /users/{userId}/orders
# Order's line items
GET /orders/{orderId}/items
```
**When to nest vs. top-level:**
| Scenario | Approach | Example |
|----------|----------|---------|
| Resource only exists under parent | Nest | `/users/{id}/sessions` |
| Resource is independently accessible | Top-level with filter | `/orders?user_id=123` |
| Shallow relationship | Top-level | `/comments?post_id=456` |
**Rule of thumb:** Never nest more than 2 levels. Use query parameters or top-level endpoints instead.
```
# Too deep -- avoid
GET /users/{id}/orders/{oid}/items/{iid}/reviews
# Better alternatives
GET /order-items/{iid}/reviews
GET /reviews?order_item_id={iid}
```
---
## Query Parameters
### Filtering
```
GET /products?category=electronics&brand=acme
GET /users?status=active&role=admin
GET /orders?created_after=2025-01-01&created_before=2025-02-01
```
| Convention | Example |
|-----------|---------|
| Exact match | `?status=active` |
| Date range | `?created_after=2025-01-01` |
| Multiple values | `?status=active,pending` |
| Search | `?q=search+term` |
### Sorting
```
GET /products?sort=price # ascending (default)
GET /products?sort=-price # descending (prefix -)
GET /products?sort=-created_at,name # multi-field
```
### Pagination
```
# Offset-based (simple, common)
GET /products?page=2&per_page=25
# Cursor-based (better for large datasets)
GET /products?cursor=eyJpZCI6MTAwfQ&limit=25
```
**Response envelope for paginated results:**
```json
{
"data": [...],
"pagination": {
"page": 2,
"per_page": 25,
"total": 150,
"total_pages": 6
}
}
```
### Field Selection
```
GET /users/123?fields=id,name,email
```
---
## Non-CRUD Actions
Some operations do not map cleanly to CRUD. Use sub-resources with a noun or POST with an action resource.
| Action | Approach | Example |
|--------|----------|---------|
| Send an email | POST to action resource | `POST /users/{id}/verification-email` |
| Archive | PATCH with status | `PATCH /orders/{id} { "status": "archived" }` |
| Bulk delete | POST to action | `POST /users/bulk-delete { "ids": [...] }` |
| Export | GET with format | `GET /reports/sales?format=csv` |
| Search (complex) | POST with body | `POST /products/search { "filters": {...} }` |
---
## Versioning
| Strategy | Example | Pros | Cons |
|----------|---------|------|------|
| URL path | `/api/v1/users` | Simple, explicit | URL pollution |
| Header | `Accept: application/vnd.api.v1+json` | Clean URLs | Hidden |
| Query param | `/users?version=1` | Easy to test | Caching issues |
**Recommended:** URL path versioning (`/api/v1/`) for public APIs due to simplicity.
---
## Summary Checklist
- [ ] Resources are plural nouns (`/users` not `/user`)
- [ ] URLs are kebab-case and lowercase
- [ ] No verbs in URLs
- [ ] Nesting limited to 2 levels
- [ ] Filtering uses query parameters
- [ ] Sorting supports `-field` for descending
- [ ] Pagination included on all list endpoints
- [ ] API version in URL path for public APIs
- [ ] Consistent error response format
*Reference: [Google API Design Guide](https://cloud.google.com/apis/design), [Microsoft REST Guidelines](https://github.com/microsoft/api-guidelines)*