国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Python > 正文

在Python的Tornado框架中實現簡單的在線代理的教程

2019-11-25 17:34:00
字體:
來源:轉載
供稿:網友

實現代理的方式很多種,流行的web服務器也大都有代理的功能,比如http://www.tornadoweb.cn用的就是nginx的代理功能做的tornadoweb官網的鏡像。

最近,我在開發一個移動運用(以下簡稱APP)的后臺程序(Server),該運用需要調用到另一平臺產品(Platform)的API。對于這個系統來說,可選的一種實現方式方式是APP同時跟Server&Platform兩者交互;另一種則在Server端封裝掉Platform的API,APP只和Server交互。顯然后一種方式的系統架構會清晰些,APP編程時也就相對簡單。那么如何在Server端封裝Platform的API呢,我首先考慮到的就是用代理的方式來實現。碰巧最近Tornado郵件群組里有人在討論using Tornado as a proxy,貼主提到的運用場景跟我這碰到的場景非常的相似,我把原帖的代碼做了些整理和簡化,源代碼如下:

# -*- coding: utf-8 -*-## Copyright(c) 2011 Felinx Lee & http://feilong.me/## Licensed under the Apache License, Version 2.0 (the "License"); you may# not use this file except in compliance with the License. You may obtain# a copy of the License at##   http://www.apache.org/licenses/LICENSE-2.0## Unless required by applicable law or agreed to in writing, software# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the# License for the specific language governing permissions and limitations# under the License. import logging import tornado.httpserverimport tornado.ioloopimport tornado.optionsimport tornado.webimport tornado.httpclientfrom tornado.web import HTTPError, asynchronousfrom tornado.httpclient import HTTPRequestfrom tornado.options import define, optionstry:  from tornado.curl_httpclient import CurlAsyncHTTPClient as AsyncHTTPClientexcept ImportError:  from tornado.simple_httpclient import SimpleAsyncHTTPClient as AsyncHTTPClient define("port", default=8888, help="run on the given port", type=int)define("api_protocol", default="http")define("api_host", default="feilong.me")define("api_port", default="80")define("debug", default=True, type=bool) class ProxyHandler(tornado.web.RequestHandler):  @asynchronous  def get(self):    # enable API GET request when debugging    if options.debug:      return self.post()    else:      raise HTTPError(405)   @asynchronous  def post(self):    protocol = options.api_protocol    host = options.api_host    port = options.api_port     # port suffix    port = "" if port == "80" else ":%s" % port     uri = self.request.uri    url = "%s://%s%s%s" % (protocol, host, port, uri)     # update host to destination host    headers = dict(self.request.headers)    headers["Host"] = host     try:      AsyncHTTPClient().fetch(        HTTPRequest(url=url,              method="POST",              body=self.request.body,              headers=headers,              follow_redirects=False),        self._on_proxy)    except tornado.httpclient.HTTPError, x:      if hasattr(x, "response") and x.response:        self._on_proxy(x.response)      else:        logging.error("Tornado signalled HTTPError %s", x)   def _on_proxy(self, response):    if response.error and not isinstance(response.error,                       tornado.httpclient.HTTPError):      raise HTTPError(500)    else:      self.set_status(response.code)      for header in ("Date", "Cache-Control", "Server", "Content-Type", "Location"):        v = response.headers.get(header)        if v:          self.set_header(header, v)      if response.body:        self.write(response.body)      self.finish() def main():  tornado.options.parse_command_line()  application = tornado.web.Application([    (r"/.*", ProxyHandler),  ])  http_server = tornado.httpserver.HTTPServer(application)  http_server.listen(options.port)  tornado.ioloop.IOLoop.instance().start() if __name__ == "__main__":  main()

運行上面的代碼后,訪問 http://localhost:8888/ 將會完整顯示飛龍博客的首頁,即代理訪問了http://feilong.me/的內容。

我考慮用程序的方式來做代理而不是直接用Nginx來做代理,其中一點是考慮到用程序可以很容易的控制Platform的哪些API是需要代理的,而哪些是要屏蔽掉的,還有哪些可能是要重寫的(比如Server的login可能不能直接代理Platform的login,但卻要調用到Platform的login API)。

以上這段代碼只是做了簡單的頁面內容代理,并沒有對頁面進行進一步的解析處理,比如鏈接替換等,這些就交個有興趣的朋友去開發了。基于以上這段代碼,將其擴展一下,是完全可以實現一個完整的在線代理程序的。

這段代碼我已放到了我的實驗項目里,見https://bitbucket.org/felinx/labs,我將會放更多類似于這樣的實驗性質的小項目到這個repository里來,有興趣的朋友可以關注一下。

轉載請注明出處:http://feilong.me/2011/09/tornado-as-a-proxy

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 周宁县| 双城市| 惠安县| 临高县| 龙胜| 乳山市| 德令哈市| 沙湾县| 太谷县| 汝州市| 大埔县| 军事| 鹤岗市| 江都市| 西昌市| 溧水县| 博客| 白朗县| 衡南县| 噶尔县| 盐山县| 陆丰市| 盘山县| 万安县| 平南县| 佛教| 合阳县| 芮城县| 建水县| 晋州市| 高密市| 彭泽县| 东光县| 大城县| 阿拉尔市| 镇雄县| 崇礼县| 穆棱市| 朝阳县| 柘城县| 永福县|