Skip to content

Instantly share code, notes, and snippets.

@chenzhuoyu
Created May 11, 2018 08:32
Show Gist options
  • Save chenzhuoyu/4739eff7f2816113dd30f91177b582b6 to your computer and use it in GitHub Desktop.
Save chenzhuoyu/4739eff7f2816113dd30f91177b582b6 to your computer and use it in GitHub Desktop.
Simple HTTP proxy
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import logging
from gevent import socket
from gevent import Greenlet
TIME_FORMAT = '%Y-%m-%d %H:%M:%S'
LOGGER_FORMAT = '[%(asctime)s][%(levelname)s] %(message)s'
handler = logging.StreamHandler(stream = sys.stderr)
handler.setFormatter(logging.Formatter(LOGGER_FORMAT, TIME_FORMAT))
logging.root.setLevel(logging.DEBUG)
logging.root.addHandler(handler)
def forward(a, b):
try:
while True:
c = a.recv(16384)
if not c:
break
b.sendall(c)
except Exception:
pass
finally:
a.close()
b.close()
def handle(sock):
try:
h = ''
while not h.endswith('\r\n'):
c = sock.recv(1)
if not c:
return None
h += c
m, p, v = h.strip().split(' ')
logging.info('%s %s %s', m, p, v)
if m != 'CONNECT':
schema, p = p.split('://', 1)
domain, p = p.split('/', 1)
s = socket.create_connection((domain, socket.getservbyname(schema)))
s.sendall('%s /%s %s\r\n' % (m, p, v))
else:
while not h.endswith('\r\n\r\n'):
c = sock.recv(1)
if not c:
return None
h += c
h, p = p.split(':')
s = socket.create_connection((h, int(p)))
sock.sendall('HTTP/1.1 200 Connection established\r\n\r\n')
Greenlet.spawn(forward, s, sock)
Greenlet.spawn(forward, sock, s)
except socket.error:
pass
except Exception:
sock.close()
raise
s = socket.socket()
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('0.0.0.0', 8080))
s.listen(128)
while True:
c, a = s.accept()
Greenlet.spawn(handle, c)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment