This project is a reverse proxy built using the Echo framework in Golang. It supports modifying request and response headers, removing unwanted headers, and dynamically configuring upstream services via environment variables.
- Proxy multiple upstream services based on the
Hostheader. - Modify request and response headers.
- Remove specific headers from responses.
- Rewrite request paths using regex patterns.
- Conditional proxying based on headers or query parameters.
- Configuration via
jsonfile. - Supports Docker deployment.
You can use this project as a library in your own Go application:
import (
"github.com/roketid/echo-proxy"
)
func main() {
configs := echoproxy.LoadConfig()
port := "8080"
echoproxy.RunProxy(configs, port)
}- Install Go
- Clone this repository:
git clone https://github.com/roketid/echo-proxy.git cd echoproxy - Build and run with config file:
go build -o proxy-server ./cmd/main.go ./proxy-server -config config.json
- Or run with base64-encoded config from environment:
# Encode your config.json as base64 export PROXY_CONFIG=$(base64 -w 0 < config.json) ./proxy-server -config-env PROXY_CONFIG
Create a config.json file with the following example configuration:
{
"example.com": {
"upstream": "https://example.com",
"host_override": "",
"request_headers": {"X-Custom-Header": "MyValue"},
"response_headers": {"X-Response-Header": "ResponseValue"},
"remove_headers": ["Server", "X-Powered-By", "Set-Cookie"],
"condition": {
"header": "X-Api-Key",
"value": "secret-key"
},
"fallback_behavior": "404"
},
"another.com": {
"upstream": "https://another.com",
"host_override": "",
"request_headers": {"X-Another-Header": "AnotherValue"},
"response_headers": {"X-Another-Response": "AnotherResponseValue"},
"remove_headers": ["Server", "Set-Cookie"]
}
}
You can also pass your configuration as a base64-encoded JSON string via an environment variable. This is useful for containerized deployments:
# Encode your config.json as base64
export PROXY_CONFIG=$(base64 -w 0 < config.json)
# Run the proxy with ENV config
./proxy-server -config-env PROXY_CONFIGExample with inline config:
# Create base64 config
CONFIG_JSON='{"example.com": {"upstream": "https://example.com"}}'
export PROXY_CONFIG=$(echo -n "$CONFIG_JSON" | base64 -w 0)
# Run the proxy
./proxy-server -config-env PROXY_CONFIGThis approach is ideal for Kubernetes, Docker, and other containerized environments where you want to pass configuration through environment variables.
You can add a condition object to a host config to only proxy requests that match a specific header or query parameter value. Only equality is supported:
- To match a header:
"condition": { "header": "X-Api-Key", "value": "secret-key" }
- To match a query parameter:
"condition": { "query_param": "token", "value": "mytoken" }
If the condition is not met, the proxy will use the fallback_behavior (e.g., "404", "bad_gateway", or proxy to a fallback upstream if fallback_upstream is set).
You can rewrite request paths using regex patterns by adding path_rewrite_regex and path_rewrite_replacement to your host config:
{
"api.example.com": {
"upstream": "https://backend.example.com",
"path_rewrite_regex": "^/v1/(.*)",
"path_rewrite_replacement": "/api/$1"
}
}This configuration will rewrite requests from /v1/users to /api/users before forwarding to the upstream server.
Common use cases:
-
Add prefix: Transform
/users→/api/v2/users"path_rewrite_regex": "^/(.*)", "path_rewrite_replacement": "/api/v2/$1"
-
Remove prefix: Transform
/v1/users→/users"path_rewrite_regex": "^/v1/(.*)", "path_rewrite_replacement": "/$1"
-
Replace path segment: Transform
/old/path→/new/path"path_rewrite_regex": "^/old/(.*)", "path_rewrite_replacement": "/new/$1"
You can configure timeout settings for each upstream service (all values in seconds):
{
"api.example.com": {
"upstream": "https://backend.example.com",
"dial_timeout": 30, // Connection establishment timeout
"read_timeout": 30, // Read operation timeout
"write_timeout": 30, // Write operation timeout
"idle_timeout": 90 // Connection idle timeout
}
}Default timeouts are:
dial_timeout: 30 secondsread_timeout: 30 secondswrite_timeout: 30 secondsidle_timeout: 90 seconds
The proxy includes several optimizations for handling high-traffic scenarios:
- Pre-compiled regex patterns: Path rewriting regex patterns are compiled once at startup, not per-request
- Pre-parsed URLs: Upstream URLs are parsed once at initialization
- Connection pooling: Configurable HTTP connection pooling with persistent connections
- Max 100 concurrent connections per host
- Max 100 idle connections
- 30-second keep-alive interval
- Efficient header management: Fast header modification and removal
- Concurrent request handling: Full support for concurrent requests with proper resource management
docker build -f docker/Dockerfile -t roketid/echo-proxy .
docker run -p 8080:8080 -v $(PWD)/config.json:/app/config.json roketid/echo-proxyThe Docker image automatically detects if PROXY_CONFIG environment variable is set and uses it:
# Encode your config to base64
CONFIG_B64=$(base64 -w 0 < config.json)
# Run with base64 config
docker run -p 8080:8080 -e PROXY_CONFIG="$CONFIG_B64" roketid/echo-proxy# With config file
docker run -p 8080:8080 -v $(PWD)/config.json:/app/config.json ghcr.io/roketid/echo-proxy:main
# With base64 config from environment
docker run -p 8080:8080 -e PROXY_CONFIG="$CONFIG_B64" ghcr.io/roketid/echo-proxy:mainThe Dockerfile CMD automatically selects the right approach:
- If
PROXY_CONFIGenvironment variable is set → uses-config-env PROXY_CONFIG - Otherwise → uses config file from
CONFIG_PATH(default:/app/config.json)
This makes it flexible for both traditional volume-mounted configs and containerized deployments using environment variables.
This project includes a GitHub Actions workflow that builds and pushes the Docker image to GitHub Container Registry when changes are pushed to the main branch.
Feel free to submit issues or pull requests for improvements.
MIT License