rs-mock-server 🦀
A simple, zero-configuration mock server built in Rust. Spin up a realistic REST API for local development or testing just by creating folders and files.
It works by scanning a directory and mapping its structure directly to API routes, with clever filename conventions for handling HTTP methods, dynamic parameters, and static assets.
Features
- 🚀 File-System Routing: Your folder structure defines your API routes. No config files needed.
- 🧩 Dynamic Path Generation: Create routes with parameters (
{id}), specific values ({admin}), and even numeric ranges ({1-10}) right from the filename. - ⚙️ Full HTTP Method Support: Define
GET,POST,PUT,DELETE,PATCH, andOPTIONSendpoints. - 🔗 In-Memory REST API: Create fully functional CRUD APIs with automatic ID generation and data persistence during runtime using special
rest.jsonfiles. - 🔐 JWT Authentication: Automatic authentication system with login/logout endpoints and route protection using special
{auth}files. - 📤 File Upload & Download: Create upload endpoints with automatic file handling and download capabilities using special
{upload}folders. - 🖼️ Static File Serving: Automatically serves any file (like images, CSS, or JS) with its correct
Content-Typeif the filename doesn't match a method pattern. - 🌐 Public Directory Serving: Serve a directory of static files (e.g., a frontend build) from a root public folder, or map a folder like public-assets to a custom /assets route.
- 🔧 Configurable: Easily change the port and mock directory via command-line arguments.
- ⚡ Lightweight & Fast: Built with Rust for minimal resource usage and maximum performance.
How It Works
The server recursively scans a root directory (defaults to ./mocks) and translates the file and folder paths into API endpoints.
Folder Structure → URL Path
The path of each folder becomes the base URL for the routes within it.
- A folder at
./mocks/api/userscreates the base route/api/users. - A nested folder at
./mocks/api/users/profilescreates the base route/api/users/profiles.
Filename Conventions → Endpoints
The name of a file determines the HTTP method and the final URL segment. The content of the file is served as the response body.
The following table shows how different filename patterns are mapped to routes, assuming they are inside a ./mocks/api/users directory:
| Filename Pattern | Example File | Generated Route(s) | Description |
|---|---|---|---|
[method] |
get.json |
GET /api/users |
Creates a route for a standard HTTP method. |
[method]{id} |
get{id}.json |
GET /api/users/{id} |
A dynamic segment that accepts any value in that position. |
[method]{value} |
get{admin}.json |
GET /api/users/admin |
Matches a specific, hardcoded value. |
[method]{start-end} |
get{1-5}.json |
GET /api/users/1GET /api/users/2...GET /api/users/5 |
A numeric range that generates multiple distinct routes. |
rest[{params}] |
rest.json |
GET /api/usersPOST /api/usersGET /api/users/{id}PUT /api/users/{id}PATCH /api/users/{id}DELETE /api/users/{id} |
In-Memory REST API. Creates a full CRUD API with automatic ID generation, data persistence, and initial data loading from the JSON array in the file. |
{auth} |
{auth}.json |
POST /api/loginPOST /api/logout |
JWT Authentication. Creates login and logout endpoints with JWT token generation and validation middleware for route protection. |
[filename].[ext] |
avatar.png |
GET /api/users/ avatar |
Static File. Any filename that doesn't match the patterns above is served as a static asset. The Content-Type header is automatically set based on the file's extension. |
In-Memory REST API
For rapid prototyping and testing, you can create fully functional CRUD APIs using special rest.json files. When the server detects a file named rest.json or rest{params}.json, it automatically:
- Loads initial data from the JSON array in the file
- Creates a complete REST API with all CRUD operations
- Maintains data in memory during the server's lifetime
- Handles ID generation automatically for new items (except for None ID Type)
REST File Naming Convention
The {params} in the filename configures the ID field behavior:
| Filename Pattern | ID Key | ID Type | Example Usage |
|---|---|---|---|
rest.json |
id |
UUID | Default configuration |
rest{none}.json |
id |
None | Explicit None type |
rest{uuid}.json |
id |
UUID | Explicit UUID type |
rest{int}.json |
id |
Integer | Integer IDs starting from 1 |
rest{_id}.json |
_id |
UUID | Custom ID field name with UUID |
rest{_id:none}.json |
_id |
None | Custom ID field name with explicit None type |
rest{_id:uuid}.json |
_id |
UUID | Custom ID field name with explicit UUID type |
rest{_id:int}.json |
_id |
Integer | Custom ID field name with integer type |
Generated Endpoints
For a rest.json file in ./mocks/api/products/, the following endpoints are automatically created:
| Method | Route | Description |
|---|---|---|
| GET | /api/products |
List all products |
| POST | /api/products |
Create a new product (auto-generates ID) |
| GET | /api/products/{id} |
Get a specific product by ID |
| PUT | /api/products/{id} |
Update an entire product (replaces all fields) |
| PATCH | /api/products/{id} |
Partially update a product (merges fields) |
| DELETE | /api/products/{id} |
Delete a product by ID |
Initial Data Format
The JSON file should contain an array of objects, where each object represents an item with the configured ID field:
For integer IDs using rest{_id:int}.json:
JWT Authentication
For applications requiring user authentication, you can create a complete JWT-based authentication system using special {auth} files. When the server detects a file named {auth}.json, it automatically:
- Loads user credentials from the JSON array in the file
- Creates authentication endpoints for login and logout
- Generates JWT tokens with secure cookies
- Provides middleware for protecting routes with authentication
Authentication File Detection
Only one authentication route is allowed per server instance. The {auth} file creates authentication endpoints based on its folder location:
| File Location | Generated Routes | Description |
|---|---|---|
./mocks/account/{auth}.json |
POST /account/loginPOST /account/logout |
Authentication for account management |
./mocks/api/auth/{auth}.json |
POST /api/auth/loginPOST /api/auth/logout |
API authentication endpoints |
./mocks/{auth}.json |
POST /loginPOST /logout |
Root-level authentication |
Credentials File Format
The {auth}.json file should contain an array of user objects with username and password as required fields:
Authentication Endpoints
Login Endpoint - POST /{folder}/login
- Request: JSON with
usernameandpassword - Response: JWT token and user info (password excluded)
- Cookie: Sets HTTP-only
auth_tokencookie for 24 hours
Logout Endpoint - POST /{folder}/logout
- Request: JWT token via Authorization header or cookie
- Response: Success message
- Action: Revokes the token from valid tokens list
Route Protection
To protect routes with authentication, prefix folder names or filenames with $:
Protected Files
mocks/
├── api/
│ ├── cities/
│ │ └── $get.json # Protected: GET /api/cities
│ └── users/
│ └── get.json # Public: GET /api/users
Protected Folders (protects all children)
mocks/
├── $admin/ # All routes under /admin are protected
│ ├── users/
│ │ └── rest.json # Protected: Full CRUD at /admin/users/*
│ └── settings/
│ └── get.json # Protected: GET /admin/settings
└── open/
└── info.json # Public: GET /open/info
Authentication Examples
Login Request
Login Response
Accessing Protected Routes
Option A: Authorization Header
Option B: Cookie (automatic)
Logout Request
- It is not possible to protect a
publicfolder
Security Features
- JWT Tokens: 24-hour expiration with HS256 signing
- HTTP-Only Cookies: Prevents XSS attacks
- Token Revocation: Logout invalidates tokens
- Dual Authentication: Supports Authorization header and cookies
- Password Protection: Login responses exclude password fields
- Route-Level Protection: Granular control over protected endpoints
Special "Public" Folder for Static Serving
To serve a directory of static assets (like a frontend app), you can use a specially named public folder in your mock directory root.
-
publicfolder: If you create a folder namedpublic, all its contents will be served from the/publicroute../mocks/public/home.html→GET /public/home.html
-
public-<alias>folder: You can customize the URL path by adding a dash. A folder namedpublic-staticwill serve its files from the/staticroute../mocks/public-static/style.css→GET /static/style.css
Special "{upload}" Folder for File Handling
For file upload and download functionality, you can create a specially named {upload} folder. When detected, the server automatically creates endpoints for uploading and downloading files.
Basic Upload Folder
-
{upload}folder: Creates upload and download endpoints at/upload.- POST
/upload- Upload files (multipart/form-data) - GET
/upload- List all uploaded files - GET
/upload/{filename}- Download files by name
- POST
Upload Folder Configuration
The {upload} folder supports additional configuration through special naming patterns:
| Folder Pattern | Upload Route | List Route | Download Route | Temporary Files | Description |
|---|---|---|---|---|---|
{upload} |
POST /upload |
GET /upload |
GET /upload/{filename} |
No | Basic upload/download |
{upload}{temp} |
POST /upload |
GET /upload |
GET /upload/{filename} |
Yes | Files deleted on server stop |
{upload}-files |
POST /files |
GET /files |
GET /files/{filename} |
No | Custom route name |
{upload}{temp}-docs |
POST /docs |
GET /docs |
GET /docs/{filename} |
Yes | Custom route + temporary |
Examples
- Basic:
./mocks/{upload}/createsPOST /upload,GET /upload, andGET /upload/{filename} - Temporary:
./mocks/{upload}{temp}/- same endpoints, but files are cleaned up when server stops - Custom Route:
./mocks/{upload}-files/createsPOST /files,GET /files, andGET /files/{filename} - Combined:
./mocks/{upload}{temp}-upfiles/createsPOST /upfiles,GET /upfiles, andGET /upfiles/{filename}with automatic cleanup
All uploaded files are saved in the detected folder with their original filenames, and downloads include proper Content-Type and Content-Disposition headers.
Installation
With Cargo
You can install it directly:
From Source
Alternatively, you can clone the repository and build it yourself:
# Clone the repository
# Navigate into the project directory
# Build the project for release
# The executable will be at ./target/release/rs-mock-server
Usage
You can run the server using the rs-mock-server executable.
To start the server with default settings:
(This will use the ./mocks folder and run on port 4520)
To specify a custom port and mock directory:
Command-Line Options
Example Walkthrough
Imagine you have the following directory structure:
mocks/
├── api/
│ ├── users/
│ │ ├── get.json # Contains a JSON array of all users
│ │ ├── post.json # Contains a success message for user creation
│ │ └── get{id}.json # Contains a single user object template
│ ├── products/
│ │ ├── rest{_id:int}.json # In-memory REST API with integer IDs
│ │ ├── get{1-3}.json # Contains a product template for IDs 1, 2, 3
│ │ └── get{special}.json# Contains a specific "special" product
│ ├── companies/
│ │ └── rest.json # In-memory REST API with UUID IDs
│ ├── auth/
│ │ └── {auth}.json # JWT authentication with user credentials
│ └── status.txt # Contains the plain text "API is running"
├── $admin/ # Protected folder - requires authentication
│ └── settings/
│ └── get.json # Protected admin settings
├── assets/
│ └── logo.svg # An SVG image file
├── {upload}/ # Upload folder for file handling
├── {upload}{temp}-docs/ # Temporary upload folder with custom route
└── public-static/
├── image.jpg # An JPG image file
└── css/
└── style.css # A stylesheet
Running rs-mock-server in the same directory will create the following endpoints:
| Method | Route | Response Body From... | Content-Type |
Description |
|---|---|---|---|---|
| GET | /api/users |
mocks/api/users/get.json |
application/json |
Static response |
| POST | /api/users |
mocks/api/users/post.json |
application/json |
Static response |
| GET | /api/users/{id} |
mocks/api/users/get{id}.json |
application/json |
Static response |
| GET | /api/products |
In-memory data from rest{_id:int}.json |
application/json |
REST API - List all products |
| POST | /api/products |
In-memory database | application/json |
REST API - Create new product |
| GET | /api/products/{_id} |
In-memory database | application/json |
REST API - Get product by ID |
| PUT | /api/products/{_id} |
In-memory database | application/json |
REST API - Update product |
| PATCH | /api/products/{_id} |
In-memory database | application/json |
REST API - Partial update |
| DELETE | /api/products/{_id} |
In-memory database | application/json |
REST API - Delete product |
| GET | /api/products/1 |
mocks/api/products/get{1-3}.json |
application/json |
Static response |
| GET | /api/products/2 |
mocks/api/products/get{1-3}.json |
application/json |
Static response |
| GET | /api/products/3 |
mocks/api/products/get{1-3}.json |
application/json |
Static response |
| GET | /api/products/special |
mocks/api/products/get{special}.json |
application/json |
Static response |
| GET | /api/companies |
In-memory data from rest.json |
application/json |
REST API - List all companies |
| POST | /api/companies |
In-memory database | application/json |
REST API - Create new company |
| GET | /api/companies/{id} |
In-memory database | application/json |
REST API - Get company by ID |
| PUT | /api/companies/{id} |
In-memory database | application/json |
REST API - Update company |
| PATCH | /api/companies/{id} |
In-memory database | application/json |
REST API - Partial update |
| DELETE | /api/companies/{id} |
In-memory database | application/json |
REST API - Delete company |
| GET | /api/status |
mocks/api/status.txt |
text/plain |
Static file |
| POST | /api/auth/login |
JWT authentication | application/json |
Auth - Login with credentials |
| POST | /api/auth/logout |
JWT token revocation | application/json |
Auth - Logout and revoke token |
| GET | /admin/settings |
mocks/$admin/settings/get.json |
application/json |
Protected - Requires authentication |
| GET | /assets/logo |
mocks/assets/logo.svg |
image/svg+xml |
Static file |
| POST | /upload |
File upload handling | text/plain |
Upload - Upload files |
| GET | /upload |
List of uploaded files | application/json |
Upload - List uploaded files |
| GET | /upload/{filename} |
Files from {upload}/ folder |
varies | Download - Download files |
| POST | /docs |
File upload handling (temporary) | text/plain |
Upload - Upload files (temp) |
| GET | /docs |
List of uploaded files (temporary) | application/json |
Upload - List uploaded files |
| GET | /docs/{filename} |
Files from {upload}{temp}-docs/ folder |
varies | Download - Download files (temp) |
| GET | /static/image.jpg |
mocks/public-static/image.svg |
image/jpg |
Static file |
| GET | /static/css/style.css |
mocks/public-static/css/style.css |
text/css |
Static file |
Note:
- The REST API endpoints provide full CRUD functionality with automatic ID generation, data persistence during runtime, and initial data loading from the JSON files.
- Authentication endpoints provide JWT-based login/logout with secure token management and route protection capabilities.
- Protected routes (prefixed with
$) require valid JWT tokens via Authorization header or auth_token cookie. - Upload endpoints handle multipart/form-data file uploads and preserve original filenames.
- Download endpoints serve files with proper Content-Type detection and Content-Disposition headers.
- Temporary upload folders (
{temp}) automatically clean up all files when the server stops. - You can interact with all endpoints using any HTTP client, and data will persist until the server is restarted.
Development
Getting Started
-
Clone the repository:
-
Install dependencies:
-
Set up development environment:
Development Commands
The project includes a Makefile with convenient development commands:
# Run tests
# Run tests in watch mode (requires cargo-watch)
# Run all quality checks (tests, clippy, formatting)
# Format code
# Run Clippy linter
# Build the project
# Run the application
# Set up Git hooks
Pre-commit Hooks
This project uses Git pre-commit hooks to ensure code quality. The hooks automatically:
- ✅ Run all tests before each commit
- ❌ Block commits if tests fail
- 🎯 Ensure consistent code quality
Automatic setup: Pre-commit hooks are installed automatically when you run make dev-setup or make setup-hooks.
Manual bypass (not recommended): If you need to commit without running tests:
Configuration: You can customize the pre-commit checks by editing .git/hooks/pre-commit. The hook supports:
- Running tests (enabled by default)
- Running Clippy checks (disabled by default)
- Checking code formatting (disabled by default)
Testing
The project includes comprehensive test coverage:
# Run all tests
# Run specific test module
# Run tests with output
Contributing
- Fork the repository
- Create a feature branch:
git checkout -b feature-name - Make your changes and ensure tests pass
- Commit your changes (pre-commit hooks will run automatically)
- Push to your fork and submit a pull request
Code Quality: All contributions must:
- Pass existing tests
- Include tests for new functionality
- Follow Rust formatting standards (
cargo fmt) - Pass Clippy linting (
cargo clippy)