在用 Tornado 建站,打算将 UI 渲染和后端操作独立为两个进程,用 API 互相操作数据。
我的做法是前后端可以同时被外部访问,类似于这样的 nginx 配置:
location / { proxy_pass http://test_tornado; include proxy_params; } location ~ ^/api { proxy_pass http://test_tornado_backend; include proxy_params; }
在本地测试的时候是没有 nginx 的,是让 Tornado 直接跑。
于是在前端的代码中绑定 /api 到下面这个 Handler:
import tornado import tornado.gen import tornado.options import tornado.httpclient import tornado.web class APIProxyHandler(tornado.web.RequestHandler): @tornado.gen.coroutine def get(self): yield self.post() @tornado.gen.coroutine def post(self): http_client = tornado.httpclient.AsyncHTTPClient() request_headers = self.request.headers.copy() request_headers.add('X-Forwarded-For', self.request.remote_ip) request_options = { 'url': '?'.join([tornado.options.options.backend]+self.request.uri.split('?', 1)[1:]), 'method': self.request.method, 'headers': request_headers, 'body': self.request.body, 'user_agent': self.request.headers.get('User-Agent', 'Tornado/%s' % tornado.version), 'connect_timeout': 60, 'request_timeout': 60, 'follow_redirects': False, 'use_gzip': True, 'allow_nonstandard_methods': True, 'allow_ipv6': True, } try: response = yield http_client.fetch(tornado.httpclient.HTTPRequest(**request_options)) except tornado.httpclient.HTTPError as e: response = e.response self.set_status(response.code, response.reason) existed_headers = set() for header_name, header_value in response.headers.get_all(): if header_name.lower() in ('content-encoding', 'content-length'): continue elif header_name in existed_headers: self.add_header(header_name, header_value) else: self.set_header(header_name, header_value) existed_headers.add(header_name) self.finish(response.body or None)
没有评论:
发表评论