4 Commits

Author SHA1 Message Date
2ed228b7fb Hallucinate a short little readme on index.html (/) 2026-01-07 21:23:00 +01:00
5e4c9c533e Add a purge endpoint and add more header controls 2026-01-07 21:12:30 +01:00
256c14fece Get rid of the header
What was I thinking????????
2026-01-07 20:52:14 +01:00
3b202226a2 Tidy shit up 2026-01-07 20:49:26 +01:00
5 changed files with 131 additions and 50 deletions

View File

@@ -1,11 +1,12 @@
FROM nginx:alpine
# Copy nginx configuration
# Copy nginx configuration and HTML
COPY nginx.conf /etc/nginx/nginx.conf
COPY index.html /usr/share/nginx/html/index.html
# Create cache directory
RUN mkdir -p /var/cache/nginx && \
chown nginx:nginx /var/cache/nginx
# Create data directories
RUN mkdir -p /etc/nginx/data/cache /etc/nginx/data/temp && \
chown -R nginx:nginx /etc/nginx/data
# Expose port
EXPOSE 3000

View File

@@ -1,45 +1,40 @@
# Nginx Cache Proxy
An nginx proxy server that caches requests only when explicitly requested via the `X-Cache: 1` header.
Navigate to `http://localhost:3000/` for interactive usage with URL builder.
## Quick Start
```bash
# Build the image
./build.sh
# Run with docker-compose (uses the built image)
docker-compose up
# Build and run
./build.sh && docker-compose up
# Or run directly
docker run -p 3000:3000 docker.site.quack-lab.dev/nginx-cache-proxy:latest
```
## Configuration
The nginx configuration implements an inverted caching logic:
- **Default behavior**: Requests are NOT cached
- **Cached behavior**: Only requests with `X-Cache: 1` header are cached
## Usage
```bash
# Proxy a URL
# Proxy and cache any URL
curl "http://localhost:3000/?url=https://api.example.com/data"
# Enable caching with X-Cache header
curl -H "X-Cache: 1" "http://localhost:3000/?url=https://api.example.com/data"
# Skip cache for this request
curl -H "X-NoCache: 1" "http://localhost:3000/?url=https://api.example.com/data"
# Cache custom status codes (e.g., 400s)
curl -H "X-Status: 400" "http://localhost:3000/?url=https://api.example.com/bad"
# Purge cache for specific URL
curl "http://localhost:3000/purge/?url=https://api.example.com/data"
```
## Features
- Cache path: `/var/cache/nginx`
- Cache zone: `api_cache` (10MB)
- Max cache size: 1GB
- Cache validity: 365 days for 200 responses
- Cache status header: `X-Cache-Status` shows cache hit/miss status
- HTTPS support with proper SSL/TLS headers
## In n8n
Add the `X-Cache: 1` header only to requests you want cached. All other requests will bypass the cache completely.
- **Always caches** 2xx status codes for 1 year
- Cache size: 100GB max
- Request size: 128MB max
- X-Cache-Status header shows cache status
- X-NoCache header bypasses cache
- X-Status header caches custom status codes
- Interactive web interface at root path
- Cache purge endpoint

View File

@@ -9,16 +9,11 @@ DOCKER_REPO="docker.site.quack-lab.dev"
IMAGE_NAME="nginx-cache-proxy"
# ============================================================================
# VALIDATE CONFIGURATION
# BUILD PROJECT
# ============================================================================
echo "Validating nginx configuration..."
docker run --rm -v "$(pwd)/nginx.conf:/etc/nginx/nginx.conf:ro" nginx:alpine nginx -t
if [ $? -ne 0 ]; then
echo "Error validating nginx configuration"
exit 1
fi
echo "Building application..."
# No build step needed for nginx
# ============================================================================
# DOCKER BUILD AND TAG

89
index.html Normal file
View File

@@ -0,0 +1,89 @@
<!DOCTYPE html>
<html>
<head>
<title>Nginx Cache Proxy</title>
<style>
body { font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; }
.usage { background: #f5f5f5; padding: 15px; border-radius: 5px; margin: 10px 0; }
.copy-field { margin: 20px 0; }
input { width: 100%; padding: 10px; font-size: 16px; }
button { background: #007cba; color: white; border: none; padding: 10px 20px; cursor: pointer; }
button:hover { background: #005a87; }
.status { margin-top: 10px; color: green; }
</style>
</head>
<body>
<h1>Nginx Cache Proxy</h1>
<p>Proxy and cache any HTTP/HTTPS URL with automatic caching.</p>
<div class="copy-field">
<h3>Quick URL Builder</h3>
<input type="text" id="urlInput" placeholder="Enter target URL (e.g., https://api.example.com/data)">
<button onclick="copyUrl()">Copy Proxy URL</button>
<div id="status" class="status"></div>
</div>
<h2>Usage</h2>
<div class="usage">
<h3>Basic Proxy</h3>
<pre>curl "http://localhost:3000/?url=https://api.example.com/data"</pre>
</div>
<div class="usage">
<h3>Skip Cache</h3>
<pre>curl -H "X-NoCache: 1" "http://localhost:3000/?url=https://api.example.com/data"</pre>
</div>
<div class="usage">
<h3>Cache Custom Status Codes</h3>
<pre>curl -H "X-Status: 400" "http://localhost:3000/?url=https://api.example.com/bad"</pre>
</div>
<div class="usage">
<h3>Purge Cache</h3>
<pre>curl "http://localhost:3000/purge/?url=https://api.example.com/data"</pre>
</div>
<h2>Features</h2>
<ul>
<li>Always caches 2xx status codes for 1 year</li>
<li>100GB max cache size</li>
<li>128MB max per request</li>
<li>X-Cache-Status header shows hit/miss</li>
<li>X-NoCache header bypasses cache</li>
<li>X-Status header caches custom status codes</li>
<li>Purge endpoint for cache management</li>
</ul>
<script>
function copyUrl() {
const input = document.getElementById('urlInput');
const status = document.getElementById('status');
if (!input.value.trim()) {
status.textContent = 'Please enter a URL first';
status.style.color = 'red';
return;
}
const proxyUrl = window.location.origin + '/?url=' + encodeURIComponent(input.value);
navigator.clipboard.writeText(proxyUrl).then(() => {
status.textContent = 'Proxy URL copied to clipboard!';
status.style.color = 'green';
}).catch(err => {
// Fallback for older browsers
const textArea = document.createElement('textarea');
textArea.value = proxyUrl;
document.body.appendChild(textArea);
textArea.select();
document.execCommand('copy');
document.body.removeChild(textArea);
status.textContent = 'Proxy URL copied to clipboard!';
status.style.color = 'green';
});
}
</script>
</body>
</html>

View File

@@ -9,20 +9,20 @@ http {
uwsgi_temp_path /etc/nginx/data/temp;
scgi_temp_path /etc/nginx/data/temp;
proxy_cache_path /etc/nginx/data/cache levels=1:2 keys_zone=api_cache:10m max_size=1g inactive=365d;
proxy_cache_path /etc/nginx/data/cache levels=1:2 keys_zone=api_cache:10m max_size=100g inactive=365d;
error_log /dev/stdout debug;
error_log /dev/stdout warn;
access_log /dev/stdout;
# Use Docker's internal DNS
resolver 127.0.0.11 valid=10s;
resolver 127.0.0.11 valid=60s;
server {
listen 3001;
listen 3000;
location / {
# If no url parameter, serve the readme
if ($arg_url = "") {
return 400 "Missing url parameter";
rewrite ^ /index.html last;
}
proxy_pass $arg_url;
@@ -31,15 +31,16 @@ http {
proxy_ssl_server_name on;
proxy_cache api_cache;
proxy_cache_valid 200 365d;
proxy_cache_bypass $http_x_cache_inverse;
proxy_no_cache $http_x_cache_inverse;
proxy_cache_valid 200 201 202 203 204 205 206 207 208 226 365d;
proxy_cache_bypass $http_x_nocache;
proxy_no_cache $http_x_nocache;
set $http_x_cache_inverse 1;
if ($http_x_cache) {
set $http_x_cache_inverse 0;
}
add_header X-Cache-Status $upstream_cache_status always;
}
location = /index.html {
root /usr/share/nginx/html;
}
}
}