buster/apps/api/documentation/rest.mdc

113 lines
5.2 KiB
Plaintext

---
description: This rule is helpful for understanding how to build our REST functions. Structure, common patterns, where to look for types, etc.
globs: src/routes/rest/**/*.rs
alwaysApply: false
---
# REST API Formatting Rules
## Directory Structure
- All REST routes should be located under `src/routes/rest/routes/`
- Each resource should have its own directory (e.g., `api_keys`, `datasets`)
- Resource directories should contain individual files for each operation
- Each resource directory should have a `mod.rs` that exports and configures the routes
Example folder structure:
```
src/routes/rest/
├── routes/
│ ├── api_keys/
│ │ ├── mod.rs # Router configuration and exports
│ │ ├── list_api_keys.rs # GET / - Contains ApiKeyInfo type definition
│ │ ├── get_api_key.rs # GET /:id
│ │ ├── post_api_key.rs # POST /
│ │ └── delete_api_key.rs # DELETE /:id
│ │
│ ├── datasets/
│ │ ├── mod.rs
│ │ ├── list_datasets.rs # GET /
│ │ ├── get_dataset.rs # GET /:id
│ │ ├── post_dataset.rs # POST /
│ │ ├── update_dataset.rs # PUT /:id
│ │ ├── patch_dataset.rs # PATCH /:id
│ │ ├── delete_dataset.rs # DELETE /:id
│ │ └── deploy_dataset.rs # POST /:id/deploy (action endpoint)
│ │
│ └── users/
│ ├── mod.rs
│ ├── list_users.rs
│ ├── get_user.rs
│ ├── post_user.rs
│ ├── update_user.rs
│ └── api_keys/ # Sub-resource example
│ ├── mod.rs
│ ├── list_user_api_keys.rs
│ └── post_user_api_key.rs
```
Note: File names should be descriptive and match their HTTP operation (list_, get_, post_, update_, patch_, delete_). For action endpoints, use a descriptive verb (deploy_, publish_, etc.).
## Route Handler Pattern
- Each REST endpoint should follow a two-function pattern:
1. Main route handler (e.g., `get_api_key`) that:
- Handles HTTP-specific concerns (status codes, request/response types)
- Calls the business logic handler
- Wraps responses in `ApiResponse`
- Handles error conversion to HTTP responses
2. Business logic handler (e.g., `get_api_key_handler`) that:
- Contains pure business logic
- Returns `Result<T>` where T is your data type
- Can be reused across different routes (REST/WebSocket)
- Handles database operations and core functionality
## Type Definitions
- Response types should be defined in the corresponding list operation file (e.g., `ApiKeyInfo` in `list_api_keys.rs`)
- These types can be reused across different operations on the same resource
- Use strong typing with Rust structs for request/response bodies
## Router Configuration
- Each resource module should have a `mod.rs` that defines its router
- Use axum's `Router::new()` to define routes
- Group related routes with `.merge()`
- Apply middleware (like auth) at the router level where appropriate
- Follow RESTful patterns for endpoints:
- Collection endpoints (no ID):
- GET / - List resources
- POST / - Create resources (accepts single item or array)
- PUT / - Bulk update resources by criteria
- DELETE / - Bulk delete resources by criteria
- Single resource endpoints (with ID):
- GET /:id - Get single resource
- PUT /:id - Full update of resource (accepts single item or array of updates)
- PATCH /:id - Partial update of resource (accepts single item or array of patches)
- DELETE /:id - Delete resources (accepts single id or array of ids)
- Sub-resource endpoints:
- GET /:id/sub_resource - List sub-resources
- POST /:id/sub_resource - Create sub-resources (accepts single item or array)
- Action endpoints (for operations that don't fit CRUD):
- POST /:id/action_name - Perform specific action
- Example: POST /datasets/:id/deploy
- Query/Filter endpoints:
- GET /search - Complex search with query params
- GET /filter - Filtered list with specific criteria
Note: All mutation endpoints (POST, PUT, PATCH, DELETE) should accept both single items and arrays by default. The handler should handle both cases seamlessly. This eliminates the need for separate /bulk endpoints.
## Example Implementation
See @src/routes/rest/routes/api_keys/get_api_key.rs for a reference implementation that demonstrates:
- Separation of HTTP and business logic
- Error handling pattern
- Type usage and database operations
- Clean abstraction of business logic for potential reuse
## Error Handling
- Business logic handlers should return `Result<T>`
- REST handlers should convert errors to appropriate HTTP status codes
- Use `ApiResponse` enum for consistent response formatting
- Include appropriate error logging using `tracing`
## Middleware
- Most the time, every new route should be authenticated, unless specified differently by the user.
- Apply authentication and other middleware at the router level
- Use `route_layer` to apply middleware to groups of routes
- Keep middleware configuration in the resource's `mod.rs`