A Spring Boot application for managing multiple MockServer instances with support for TLS/mTLS and global response headers.
- Multiple MockServer Instances: Create and manage multiple mock servers in a single process
- File-based Configuration: Configure servers via JSON/JSONMC configuration file at startup
- Relay/Proxy Mode: Forward requests to remote servers with optional OAuth2 authentication
- Kubernetes Tunnel Support: Establish kubectl port-forward tunnels to Kubernetes pods
- TLS/HTTPS Support: Enable HTTPS with custom certificates
- Mutual TLS (mTLS): Client certificate validation with CA certificate
- Basic Authentication: HTTP Basic Auth protection for mock servers
- Global Headers: Apply headers to all responses from a server
- Header Merging: Intelligent merge of global and expectation-specific headers
The following call tree illustrates how a typical HTTP request is processed by the MockServer Manager when an enhanced expectation is matched:
Incoming HTTP Request (MockServer Port)
│
└── EnhancedResponseCallback.handle(HttpRequest)
│
├── Extract context (path variables, cookies, params)
│
├── Find matching Strategy (supports(config) == true)
│ │
│ ├── StaticResponseStrategy.handle(...)
│ │ └── Return pre-configured HttpResponse
│ │
│ ├── DynamicFileStrategy.handle(...)
│ │ ├── evaluateFilePathTemplate()
│ │ ├── findFirstFileWithPrefix() (Glob search)
│ │ └── Process via FreemarkerTemplateService (if template)
│ │
│ ├── SSEResponseStrategy.handle(...)
│ │ └── Format messages into text/event-stream
│ │
│ └── RelayResponseStrategy.handle(...)
│ └── RelayService.relayRequest()
│ └── OAuth2TokenService.getAccessToken() (if configured)
│
├── mergeGlobalHeaders(response)
│ └── Apply server-level global headers
│
└── Return final HttpResponse to Client
┌─────────────────────────────────────────────────────────┐
│ Spring Boot Application │
│ (runs in background until CTRL+C) │
├─────────────────────────────────────────────────────────┤
│ ConfigurationLoaderService │
│ - Loads config from file or base64 │
│ - Creates servers on startup │
├─────────────────────────────────────────────────────────┤
│ MockServerManager │ EnhancedResponseCallback │
│ - Server registry │ - Strategy Router │
│ - Lifecycle mgmt │ - Global Header Merging │
│ - Tunnel management │ │
├─────────────────────────────────────────────────────────┤
│ Response Strategies │
│ - Static - Dynamic File - SSE - Relay │
│ - Kubernetes Tunnel │
└─────────────────────────────────────────────────────────┘
│ │
▼ ▼
┌─────────────┐ ┌─────────────┐
│ MockServer │ │ MockServer │
│ Port 1080 │ │ Port 1443 │
│ (HTTP) │ │ (HTTPS) │
└─────────────┘ └─────────────┘
- Java 21 or higher
- Maven 3.8+
# Build the project
mvn clean package
# Run the application
mvn spring-boot:run
# Run the hybrid executable (no .jar extension)
./target/fast_mock_server
# Or run as a regular JAR
java -jar target/fast_mock_server.jar
# Run with configuration file
./target/fast_mock_server -f server-config.json
java -Dmock.server.config.file=server-config.json -jar target/fast_mock_server.jar
# Or with Maven
mvn spring-boot:run -Dspring-boot.run.jvmArguments="-Dmock.server.config.file=server-config.json"fast-mock-server — Mock servers, relay proxies, and tunnels for local testing
Usage: fast-mock-server [options]
Options:
-f, --config <file> Start server with the given config file
-g, --generate <type> Generate a template config to stdout
-g, --generate <type> -o, --output <file> Generate to a file
-l, --list List available config types
-h, --help Show this help message
Quickly generate a starter config for any supported feature:
# List all available config types
mvn spring-boot:run -Dspring-boot.run.jvmArguments="-l"
# Print a template to stdout
mvn spring-boot:run -Dspring-boot.run.jvmArguments="-g simple"
# Generate a config to a file
mvn spring-boot:run -Dspring-boot.run.jvmArguments="-g relay -o ./relay.json"
# Then start the server with it
mvn spring-boot:run -Dspring-boot.run.jvmArguments="-f ./relay.json"| Type | Description |
|---|---|
simple |
Basic API mock server |
multi |
HTTP + HTTPS multi-server with TLS |
basicauth |
Basic authentication (username/password) |
mtls |
Mutual TLS (mTLS) with client certs |
pathvars |
Path variables and FreeMarker templates |
sse |
Server-Sent Events (SSE) streaming |
relay |
Relay proxy with OAuth2 authentication |
relay-no-auth |
Relay proxy without authentication |
files |
File download server |
files-inline |
File inline server (serve content as body) |
uploads |
File upload server (multipart/form-data) |
tunnel |
Kubernetes pod tunnel relay |
The application runs as a background process until you press CTRL+C. All server configuration is done via file-based configuration at startup.
You can automatically create servers and configure expectations at startup by providing a JSON configuration file. This is useful for:
- Consistent test environments
- CI/CD pipelines
- Automated testing setups
- Quick server setup without API calls
- Docker containers
Create a JSON file (e.g., server-config.json) with an array of server configurations:
[
{
"server": {
"serverId": "api-server",
"port": 8081,
"description": "API Mock Server",
"globalHeaders": [
{
"name": "X-API-Version",
"value": "1.0"
}
]
},
"expectations": [
{
"httpRequest": {
"method": "GET",
"path": "/api/users"
},
"httpResponse": {
"statusCode": 200,
"body": "{\"users\": [{\"id\": 1, \"name\": \"John Doe\"}]}"
}
}
]
}
]Specify the configuration file path using the mock.server.config.file system property:
# Using java command
java -Dmock.server.config.file=/path/to/server-config.json -jar target/fast_mock_server.jar
# Using Maven
mvn spring-boot:run -Dspring-boot.run.jvmArguments="-Dmock.server.config.file=./server-config.json"
# Using relative path
java -Dmock.server.config.file=./config/servers.json -jar target/fast_mock_server.jarWhen running inside a Docker container, place your configuration file at /server.jsonmc in the container filesystem. The application will automatically detect and load it:
# Build the JAR
mvn clean package -DskipTests
# Build Docker image with config
docker build -t mock-server .
# (Ensure server.jsonmc is copied to root of container)
# Run the container - config at /server.jsonmc will be auto-loaded
# Note: Use --net=host due to dynamic port mappings for mock servers
docker run --net=host mock-serverImportant: Due to the complexity of managing multiple dynamic ports for mock servers (each server can use different ports), you must run the container with --net=host. This allows the mock servers to bind directly to host ports without Docker port mapping overhead.
Format Support: Both JSON and JSONMC formats are supported. The system auto-detects JSONMC format by looking for comment markers (// or /*) in the file content.
Note: If no configuration file is specified and no /server.jsonmc exists, the application starts without pre-configured servers.
The application supports file glob patterns for flexible file matching in both configuration loading and file response callbacks. This feature allows you to specify file path prefixes instead of exact file paths, making it easier to work with dynamic file names or when the exact file name is not known in advance.
When loading server configurations at startup, you can specify a file path prefix using the mock.server.config.file system property. The system will search for the first file that starts with the specified prefix:
# Instead of exact file path
java -Dmock.server.config.file=/path/to/server-config.json -jar target/fast_mock_server.jar
# You can use a prefix - finds first file starting with "server-config"
java -Dmock.server.config.file=/path/to/server-config -jar target/fast_mock_server.jarExamples:
- Prefix:
server-config→ matchesserver-config.json,server-config-example.json,server-config-v2.json, etc. - Prefix:
config/servers→ matchesconfig/servers.json,config/servers-prod.json, etc. - Prefix:
test-config→ matchestest-config.jsonmc,test-config-backup.json, etc.
The search is performed recursively from the current directory, and the first matching file is used.
When configuring expectations with file responses, you can use glob patterns to specify file path prefixes. The system will find the first file that starts with the specified prefix:
{
"httpRequest": {
"method": "GET",
"path": "/api/download/report"
},
"httpResponse": {
"statusCode": 200,
"file": "/path/to/documents/report"
}
}Examples:
- Prefix:
/path/to/documents/report→ matchesreport.pdf,report-v2.pdf,report-final.pdf, etc. - Prefix:
/data/exports/user-data→ matchesuser-data.csv,user-data-2024.csv,user-data-backup.json, etc. - Prefix:
/tmp/cache/api-response→ matchesapi-response.json,api-response.xml, etc.
- Flexible File Matching: No need to know exact file names in advance
- Dynamic File Selection: Works well with generated or timestamped files
- Simplified Configuration: Reduces the need for exact file path specifications
- Environment Agnostic: Easier to work across different environments where file names might vary
- Glob pattern matching searches recursively from the current working directory
- Only the first matching file is used (alphabetically by file path)
- If no matching file is found, the system returns a 404 error
- Glob patterns work with both regular files and FreeMarker template expressions
- The search includes all subdirectories and is case-sensitive on most filesystems
Each server configuration object contains:
- server (required): Server creation parameters
serverId: Unique identifierport: Port number (1024-65535)description: Optional descriptiontlsConfig: Optional TLS/HTTPS configurationglobalHeaders: Optional global response headersrelays: Optional relay/tunnel configuration
- expectations (optional): Array of expectations to configure on this server
Note: This application does not expose a REST API for server management. All configuration is loaded from the configuration file at startup.
See src/test/examples/server-config-example.jsonmc for a complete example with multiple servers and various configurations.
- Reproducible Environments: Same configuration across all environments
- Version Control: Track configuration changes in Git
- Quick Setup: Start multiple servers with expectations in one command
- CI/CD Integration: Easily integrate with automated testing pipelines
- No API Calls: Servers and expectations ready immediately on startup
To create and configure mock servers, use the file-based configuration:
# Run with a configuration file
mvn spring-boot:run -Dspring-boot.run.jvmArguments="-Dmock.server.config.file=./server-config.jsonmc"See src/test/examples/server-config-example.jsonmc for a complete configuration example with multiple servers.
When a server has global headers configured, they are automatically merged with expectation-specific headers:
Global Headers (configured at server creation):
{
"globalHeaders": [
{"name": "X-Service-Version", "value": "1.0.0"},
{"name": "X-Environment", "value": "test"}
]
}Expectation Headers:
{
"headers": {
"Content-Type": ["application/json"],
"X-Service-Version": ["2.0.0"]
}
}Final Response Headers (expectation headers override global):
Content-Type: application/json(from expectation)X-Service-Version: 2.0.0(from expectation - overrides global)X-Environment: test(from global)
Create a configuration file server-config.jsonmc:
[
{
"server": {
"serverId": "user-service",
"port": 1080,
"description": "User Service Mock",
"globalHeaders": [
{"name": "X-Service-Name", "value": "user-service"},
{"name": "X-Mock-Server", "value": "true"}
]
},
"expectations": [
{
"httpRequest": {
"method": "GET",
"path": "/users/123"
},
"httpResponse": {
"statusCode": 200,
"headers": {
"Content-Type": ["application/json"]
},
"body": {
"id": 123,
"name": "John Doe"
}
}
}
]
}
]Start the server:
mvn spring-boot:run -Dspring-boot.run.jvmArguments="-Dmock.server.config.file=./server-config.jsonmc"Test the mock:
curl http://localhost:1080/users/123Response:
{
"id": 123,
"name": "John Doe"
}Response Headers:
Content-Type: application/json
X-Service-Name: user-service
X-Mock-Server: true
# Generate private key
openssl genrsa -out server.key 2048
# Generate certificate
openssl req -new -x509 -key server.key -out server.crt -days 365 \
-subj "/CN=localhost"
# View certificate content
cat server.crt
cat server.keyUse a configuration file:
{
"server": {
"serverId": "https-service",
"port": 1443,
"tlsConfig": {
"certificate": "-----BEGIN CERTIFICATE-----\nMIID...\n-----END CERTIFICATE-----",
"privateKey": "-----BEGIN PRIVATE KEY-----\nMIIE...\n-----END PRIVATE KEY-----"
}
}
}curl -k https://localhost:1443/test# Create CA
openssl genrsa -out ca.key 2048
openssl req -new -x509 -key ca.key -out ca.crt -days 365 \
-subj "/CN=Test CA"
# Create server cert signed by CA
openssl genrsa -out server.key 2048
openssl req -new -key server.key -out server.csr -subj "/CN=localhost"
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key \
-CAcreateserial -out server.crt -days 365
# Create client cert signed by CA
openssl genrsa -out client.key 2048
openssl req -new -key client.key -out client.csr -subj "/CN=client"
openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key \
-CAcreateserial -out client.crt -days 365Use a configuration file:
{
"server": {
"serverId": "mtls-service",
"port": 1444,
"tlsConfig": {
"certificate": "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----",
"privateKey": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----",
"mtlsConfig": {
"caCertificate": "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----",
"requireClientAuth": true
}
}
}
}Test with Client Certificate:
curl -k https://localhost:1444/test \
--cert client.crt \
--key client.keyThe relay server feature allows you to create a mock server that acts as a proxy, forwarding all incoming requests to a remote server. This is useful for testing against real APIs, adding authentication layers, or creating simple proxy servers.
- Optional OAuth2 Authentication: Automatically obtains and manages OAuth2 access tokens
- Token Caching: Caches tokens to minimize token endpoint calls
- Custom Headers: Add custom headers to all relayed requests
- No Authentication Mode: Relay requests without any authentication
- Full Request Forwarding: Forwards method, path, query params, headers, and body
- Transparent Response: Returns exact response from remote server
Simple relay without authentication:
{
"server": {
"serverId": "simple-relay",
"port": 8090,
"relays": [{
"remoteUrl": "https://api.example.com"
}]
}
}Relay with OAuth2:
{
"server": {
"serverId": "oauth-relay",
"port": 8090,
"relays": [{
"remoteUrl": "https://api.example.com",
"tokenUrl": "https://auth.example.com/oauth/token",
"clientId": "client-id",
"clientSecret": "client-secret"
}]
}
}Relay with custom headers:
{
"server": {
"serverId": "custom-relay",
"port": 8090,
"relays": [{
"remoteUrl": "https://api.example.com",
"headers": {
"X-API-Version": "v2",
"X-Client-App": "test-suite"
}
}]
}
}Once the server is started with the configuration file, any request to the relay server is automatically forwarded to the remote server:
# Request to relay server
curl http://localhost:8090/users/123
# This is forwarded to: https://api.example.com/users/123
# (with OAuth2 token if configured)Required:
remoteUrl: Base URL of the remote server
OAuth2 Authentication (all three required if using OAuth2):
tokenUrl: OAuth2 token endpointclientId: OAuth2 client IDclientSecret: OAuth2 client secret
Optional:
prefixes: List of path prefixes to match (default:["/**"])scope: OAuth2 scope to requestgrantType: OAuth2 grant type (default: "client_credentials")headers: Custom headers to add to all relayed requests
- When relay is enabled, expectations are ignored - all requests are forwarded
- Multiple relays can be configured with different prefixes. The longest matching prefix is selected
- OAuth2 is completely optional - omit token parameters for no authentication
- If providing OAuth2 config, all three parameters (
tokenUrl,clientId,clientSecret) must be provided - Tokens are automatically cached and refreshed when expired
See src/test/examples/server-config-relay-example.jsonmc and src/test/examples/server-config-relay-no-auth-example.jsonmc for complete examples.
For detailed relay configuration documentation, see docs/RELAY_CONFIGURATION.md.
The relay feature also supports establishing kubectl port-forward tunnels to Kubernetes pods. This enables access to services running inside a Kubernetes cluster without exposing them publicly.
Key Features:
- Automatic Pod Discovery: Finds pods using prefix filter
- Auto-assigned Ports: Host port automatically assigned from range 9000-11000
- Sequential Creation: Multiple tunnels created one at a time
- Graceful Shutdown: Tunnels automatically killed on server stop
Example Configuration:
{
"server": {
"serverId": "k8s-tunnel",
"port": 9001,
"relays": [{
"tunnelConfig": {
"namespace": "production",
"podPrefix": "api-service-",
"podPort": 8080
},
"prefixes": ["/api/**"]
}]
}
}For detailed tunnel configuration documentation, see docs/RELAY_CONFIGURATION.md.
All errors return a consistent format:
{
"errorCode": "SERVER_NOT_FOUND",
"message": "Server not found with ID: unknown-server",
"timestamp": "2025-10-02T21:30:00"
}Error Codes:
SERVER_NOT_FOUND(404) - Server ID not foundSERVER_ALREADY_EXISTS(409) - Server ID already in useINVALID_CERTIFICATE(400) - Certificate validation failedSERVER_CREATION_FAILED(500) - Server creation errorINVALID_EXPECTATION(400) - Invalid expectation JSONVALIDATION_FAILED(400) - Request validation errors
Edit src/main/resources/application.properties:
# Certificate temp directory
mockserver.cert.temp-dir=/tmp/mockserver-certs
# Auto-cleanup certificates on shutdown
mockserver.cert.cleanup-on-shutdown=true
# Logging level
logging.level.io.github.anandb.mockserver=DEBUG- Spring Boot 3.5.3
- MockServer Netty (no-dependencies) 5.15.0
- Lombok
- Jackson (JSON processing)
- FreeMarker (Templating engine)
This project is provided as-is for demonstration purposes.
For issues or questions, please refer to: