Skip to content

Instantly share code, notes, and snippets.

@amcgregor
Created January 21, 2011 03:21
Show Gist options
  • Save amcgregor/789193 to your computer and use it in GitHub Desktop.
Save amcgregor/789193 to your computer and use it in GitHub Desktop.
A transparent caching proxy server built using WSGI.
#!/usr/bin/env python
"""A transparent caching proxy.
To use, simply create a directory and run this script a la:
./caching-proxy.py cache
Then point your browser's HTTP proxy at localhost:8888.
Everything requested will be cached (regardless of no-cache headers).
To clear the cache, simply nuke the contents of the folder.
"""
import os
import sys
import hashlib
import httplib
from wsgiref.simple_server import make_server
def filename(method, path):
return os.path.join(sys.argv[1], hashlib.sha256(method + ' ' + path).hexdigest())
def proxy(environ, start_response):
fn = filename(environ['REQUEST_METHOD'], environ['PATH_INFO'])
status = '200 OK'
headers = []
body = None
if os.path.exists(fn):
print "Cache hit:", fn
data = open(fn, 'r').readlines()
status = data[0].strip()
j = 0
for i, header in enumerate(data[1:]):
if header.strip() == "":
j = i + 1
break
headers.append(tuple(header.strip().split(':', 1)))
body = data[j+1:]
else:
print "Cache miss:", fn
fh = open(fn, 'w')
rheaders = {}
for i, j in environ.iteritems():
if i.startswith("HTTP_"):
rheaders[i[5:].lower().replace('_', '-')] = j
conn = httplib.HTTPConnection(environ['PATH_INFO'][7:].split('/', 1)[0] + ':80')
conn.request(environ['REQUEST_METHOD'], '/' + environ['PATH_INFO'][7:].split('/', 1)[1], None, rheaders)
response = conn.getresponse()
status = "%s %s" % (response.status, response.reason)
headers = [(i, j) for i, j in response.getheaders() if i not in ('connection', 'keep-alive', 'transfer-encoding')]
body = [response.read()]
fh.write("%s\n" % (status, ))
fh.write("%s\n\n" % ("\n".join([":".join((i, j)) for i, j in headers])))
fh.write(body[0])
fh.close()
start_response(status, headers)
return body
httpd = make_server('', 8888, proxy)
print "Serving on port 127.0.0.1:8888..."
# Serve until process is killed
httpd.serve_forever()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment