Skip to content

Instantly share code, notes, and snippets.

@alexey-sveshnikov
Last active June 12, 2017 10:39
Show Gist options
  • Save alexey-sveshnikov/501eaa784dbd088bdc36 to your computer and use it in GitHub Desktop.
Save alexey-sveshnikov/501eaa784dbd088bdc36 to your computer and use it in GitHub Desktop.
#!/usr/bin/python
# coding: utf8
# Simple HTTP proxy that appends ™ to all words in response that are six characters long
# To install run 'pip install lxml'
import re
import gzip
import copy
import urllib2
import BaseHTTPServer
from StringIO import StringIO
from lxml import etree
ALL_WORDS = re.compile(r'(\b\w{6}\b)', re.UNICODE)
def add_tm(text):
return ALL_WORDS.sub(ur"\1™", text)
def walk_and_modify_html(text):
tree = etree.fromstring(text, etree.HTMLParser())
for el in tree.xpath('//*'):
if el.tag in ('script', 'style'):
continue
if el.text:
el.text = add_tm(el.text)
if el.tail:
el.tail = add_tm(el.tail)
return etree.tostring(tree.getroottree(), pretty_print=True, method="html")
def make_request(url):
response = urllib2.urlopen(url)
return response.code, copy.deepcopy(response.headers.dict), response.read()
class ProxyHandler(BaseHTTPServer.BaseHTTPRequestHandler):
def do_GET(s):
if s.path.startswith('/'):
s.send_response(404)
s.send_header('Content-Type', 'text/plain')
s.end_headers()
s.wfile.write("Please use this server as HTTP PROXY. There is no any resources here.")
return
status_code, headers, body = make_request(s.path)
# Decode gzipped response if needed
if headers.get('content-encoding') == 'gzip':
headers.pop('content-encoding')
f = gzip.GzipFile(fileobj=StringIO(body))
body = f.read()
# For text/html documents do substitutions
if headers.get('content-type', '').startswith('text/html'):
body = body.decode('utf8')
body = walk_and_modify_html(body)
# durty hack to load page assets using HTTP (since our proxy doesn't support CONNECT method)
body = body.replace('https', 'http')
body = body.encode('utf8')
headers['content-length'] = len(body)
s.send_response(status_code)
for header, value in headers.items():
s.send_header(header, value)
s.end_headers()
s.wfile.write(body)
if __name__ == '__main__':
server_class = BaseHTTPServer.HTTPServer
httpd = server_class(('0.0.0.0', 3128), ProxyHandler)
try:
httpd.serve_forever()
except KeyboardInterrupt:
pass
httpd.server_close()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment