Skip to content

Instantly share code, notes, and snippets.

@iTrooz
Last active May 29, 2024 10:05
Show Gist options
  • Save iTrooz/0192ab377b504dfb9a04f387cda91c84 to your computer and use it in GitHub Desktop.
Save iTrooz/0192ab377b504dfb9a04f387cda91c84 to your computer and use it in GitHub Desktop.
varnish_httpcache
#!/usr/bin/env python3
# Easier Frontend for varnishd
# Example: ./httpcache.py -u google.com
# Then, requests to localhost:8080 forwarded to google.com and cached
# Licence: MIT
import os
import tempfile
import subprocess
import shutil
import argparse
def parse_upstream(upstream: str) -> tuple[str, str]:
# handle protocol
defPort = "80"
if upstream.startswith("http://"):
upstream = upstream[7:]
defPort = "80"
elif upstream.startswith("https://"):
upstream = upstream[8:]
defPort = "443"
# handle port
port_index = upstream.find(":")
if port_index == -1:
return upstream, defPort
else:
return upstream[:port_index], upstream[port_index+1:]
# Parse command line arguments
parser = argparse.ArgumentParser(description='HTTP Cache with Varnish')
parser.add_argument('--upstream', '-u', type=str, required=True, help='Backend host')
parser.add_argument('--port', '-p', type=str, default='8080', help='Varnish port')
parser.add_argument('--verbose', '-v', action="count")
args = parser.parse_args()
# Configuration
upstream_host, upstream_port = parse_upstream(args.upstream)
# VCL template with placeholders
vcl_content = """
vcl 4.0;
backend default {
.host = "{upstream_host}";
.port = "{upstream_port}";
.host_header = "{upstream_host}:{upstream_port}";
}
sub vcl_backend_fetch {
unset bereq.http.host;
}
sub vcl_recv {
# Add custom logic here if needed
}
sub vcl_backend_response {
set beresp.ttl = 24h; # Set TTL for cached objects
}
sub vcl_deliver {
if (obj.hits > 0) {
set resp.http.X-Cache = "HIT";
} else {
set resp.http.X-Cache = "MISS";
}
}
"""
vcl_content = vcl_content.replace("{upstream_host}", upstream_host)
vcl_content = vcl_content.replace("{upstream_port}", upstream_port)
tmpdir = tempfile.TemporaryDirectory(delete=False).name
if args.verbose:
print("Varnish tmp folder:", tmpdir)
# Create a temporary VCL file
tmp_vcl_file = os.path.join(tmpdir, "file.vcl")
with open(tmp_vcl_file, "wb") as file:
file.write(vcl_content.encode('utf-8'))
try:
print(f"Varnish started on port {args.port} with backend {upstream_host}:{upstream_port}")
proc = subprocess.run([
"varnishd",
"-F",
"-a", f":{args.port}",
"-f", tmp_vcl_file,
"-s", "malloc,256m",
"-n", os.path.join(tmpdir, "cache")
], check=False, capture_output=not args.verbose)
# Process has finished
if not args.verbose and proc.returncode != 0:
print("varnishd crashed. Logs:")
print("\nStdout:")
print(proc.stdout.decode('utf-8'))
print("\nStderr:")
print(proc.stderr.decode('utf-8'))
exit(1)
finally:
shutil.rmtree(tmpdir)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment