peerlink/peerlink/proxy.py

106 lines
2.9 KiB
Python

# -*- coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4
import tornado.web
import tornado.httpclient
import tornado.gen
from .utils import run_async
from . import link
import logging
logger = logging.getLogger('proxy')
class ProxyHandler(tornado.web.RequestHandler):
SUPPORTED_METHODS = ['GET', 'POST', 'PUT', 'DELETE']
@tornado.web.asynchronous
def _handle_response(self, response):
if response.error:
logger.debug('ERROR %s', str(response.error))
self.set_status(response.code)
if response.body:
self.write(response.body)
else:
self.write('Internal server error:\n' + str(response.error))
else:
if response.code:
self.set_status(response.code)
allowed_headers = (
'X-Ed25519-Key',
'X-Ed25519-Signature',
'Accept-Ranges',
'Cache-Control',
'Connection',
'Content-Encoding',
'Content-Length',
'Content-Range',
'Content-Type',
'Date',
'ETag',
'Last-Modified',
'Location',
'Range',
'Server',
'Vary'
)
for header in allowed_headers:
v = response.headers.get(header)
if v:
self.set_header(header, v)
ignored = set(response.headers.keys()) - set([h.lower() for h in allowed_headers])
if ignored:
print('IGNORED', ignored)
if response.data:
self.write(response.data)
elif response.body:
chunk = True
while chunk:
chunk = response.body.read(4096)
self.write(chunk)
self.finish()
@run_async
def _fetch_response(self, url, fingerprint, callback):
response = link.read(url, self.request.body, self.request.headers, fingerprint)
callback(response)
def remote_url(self):
self.set_status(500)
self.write('Internal server error:\n')
self.finish()
return None
@tornado.web.asynchronous
@tornado.gen.coroutine
def proxy(self):
url = self.remote_url()
if isinstance(url, tuple):
url, fingerprint = url
else:
fingerprint = None
if url:
logger.debug('request to %s', url)
response = yield tornado.gen.Task(self._fetch_response, url, fingerprint)
self._handle_response(response)
@tornado.web.asynchronous
def get(self):
return self.proxy()
@tornado.web.asynchronous
def post(self):
return self.proxy()
@tornado.web.asynchronous
def put(self):
return self.proxy()
@tornado.web.asynchronous
def delete(self):
return self.proxy()