0eac08394c22a7f0e1b4b03cb770d5bbabe7f991
Reset multiple connection flags (content_type_checked, is_textual_content, response_headers_parsed, original_content_length, content_length_delta, patch_blocked) when reusing connection for internal route keep-alive. Add immediate handling of any buffered read data after state reset to prevent stale data blocking subsequent requests. Add comprehensive test verifying second request processing on internal dashboard route via Unix socket pair.
feat: enable keep-alive for internal routes by resetting connection state and handling pending reads
feat: enable keep-alive for internal routes by resetting connection state and handling pending reads
feat: enable keep-alive for internal routes by resetting connection state and handling pending reads
rproxy
Author: retoor retoor@molodetz.nl
A high-performance reverse proxy server written in C. Routes HTTP and WebSocket requests to upstream services based on hostname, with support for SSL/TLS connections and real-time monitoring.
Features
- Reverse proxy routing by hostname
- SSL/TLS support for upstream connections with certificate verification
- WebSocket proxying
- Connection pooling and idle timeout management
- Real-time monitoring and statistics
- Web-based dashboard for metrics visualization
- SQLite-based persistent statistics storage
- Epoll-based event handling for high concurrency
- Graceful shutdown with connection draining
- Live configuration reload via SIGHUP
- Per-route authentication (HTTP Basic Auth)
- Dashboard authentication
- Rate limiting per client IP
- Health checks for upstream servers
- Automatic upstream connection retries
- File logging support
- Stream data patching/rewriting for textual content
Dependencies
- GCC
- OpenSSL (libssl, libcrypto)
- SQLite3
- pthreads
- cJSON (bundled)
Build
make
Compiles the source files in src/ and produces the rproxy executable.
Testing
make test # Run unit tests
make coverage # Run tests with coverage report (minimum 69% required)
make coverage-html # Generate HTML coverage report
make valgrind # Run tests with memory leak detection
Test Results
Test Results: 741/741 passed
HEAP SUMMARY:
in use at exit: 0 bytes in 0 blocks
total heap usage: 155,794 allocs, 155,794 frees, 13,900,573 bytes allocated
All heap blocks were freed -- no leaks are possible
ERROR SUMMARY: 0 errors from 0 contexts
Configuration
Configuration is defined in proxy_config.json:
{
"port": 9998,
"reverse_proxy": [
{
"hostname": "example.com",
"upstream_host": "127.0.0.1",
"upstream_port": 5000,
"use_ssl": false,
"rewrite_host": true,
"use_auth": true,
"username": "admin",
"password": "secret",
"patch": {
"old_string": "new_string",
"blocked_content": null
}
}
]
}
Route Options
| Option | Type | Description |
|---|---|---|
hostname |
string | Host header to match for routing |
upstream_host |
string | Target server hostname or IP |
upstream_port |
integer | Target server port (1-65535) |
use_ssl |
boolean | Enable SSL/TLS for upstream connection |
rewrite_host |
boolean | Rewrite Host header to upstream hostname |
use_auth |
boolean | Enable HTTP Basic Auth for this route |
username |
string | Authentication username |
password |
string | Authentication password |
patch |
object | Stream data patching rules |
Data Patching
The patch configuration allows rewriting or blocking content in HTTP streams. Patch rules are applied to textual content only. Binary content passes through unmodified.
{
"patch": {
"find_this": "replace_with_this",
"another_string": "replacement",
"blocked_term": null
}
}
- String replacement: Each key-value pair defines a find-replace rule
- Content blocking: Setting value to
nullblocks the entire response/request when the key is found - Bidirectional: Patches apply to both requests and responses
Blocked responses return 502 Bad Gateway. Blocked requests return 403 Forbidden.
Supported textual content types:
text/*application/jsonapplication/xmlapplication/javascriptapplication/x-www-form-urlencoded- Content types with
+xmlor+jsonsuffix
Environment Variables
| Variable | Description |
|---|---|
DEBUG |
Enable debug logging (set to 1) |
LOG_FILE |
Path to log file (default: stdout) |
RATE_LIMIT |
Max requests per minute per IP |
DASHBOARD_USER |
Dashboard authentication username |
DASHBOARD_PASS |
Dashboard authentication password |
SSL_VERIFY |
Disable SSL verification (set to 0) |
SSL_CA_FILE |
Path to custom CA certificate file |
SSL_CA_PATH |
Path to CA certificate directory |
Usage
./rproxy [config_file]
If no config file is specified, defaults to proxy_config.json.
./rproxy
./rproxy /etc/rproxy/config.json
DEBUG=1 ./rproxy
LOG_FILE=/var/log/rproxy.log ./rproxy
RATE_LIMIT=100 ./rproxy
DASHBOARD_USER=admin DASHBOARD_PASS=secret ./rproxy
SSL_VERIFY=0 ./rproxy
kill -HUP $(pidof rproxy) # Reload configuration
Endpoints
| Path | Description |
|---|---|
/rproxy/dashboard |
Web-based monitoring dashboard |
/rproxy/api/stats |
JSON API for statistics |
Signals
| Signal | Action |
|---|---|
SIGINT |
Graceful shutdown |
SIGTERM |
Graceful shutdown |
SIGHUP |
Reload configuration |
Architecture
| Module | Description |
|---|---|
main.c |
Entry point, event loop, signal handling |
connection.c |
Connection management, epoll handling |
http.c |
HTTP request/response parsing |
ssl_handler.c |
SSL/TLS connection handling |
monitor.c |
System and per-vhost statistics collection |
dashboard.c |
Web dashboard generation |
config.c |
JSON configuration parsing with hot-reload |
buffer.c |
Circular buffer implementation |
logging.c |
Logging utilities |
rate_limit.c |
Per-IP rate limiting with sliding window |
auth.c |
HTTP Basic Auth implementation |
health_check.c |
Upstream health monitoring |
patch.c |
Stream data patching engine |
License
See LICENSE file for details.
Languages
C
98.6%
Makefile
1.4%