程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> 更多關於編程 >> 在Python的Tornado框架中實現簡單的在線代理的教程

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

編輯:更多關於編程

       這篇文章主要介紹了在Python的Tornado框架中實現簡單的在線代理的教程,代理功能是一個常見的網絡編程實現,需要的朋友可以參考下

      實現代理的方式很多種,流行的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,貼主提到的運用場景跟我這碰到的場景非常的相似,我把原帖的代碼做了些整理和簡化,源代碼如下:

      ?

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 # -*- coding: utf-8 -*- # # Copyright(c) 2011 Felinx Lee & http://3lian.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.httpserver import tornado.ioloop import tornado.options import tornado.web import tornado.httpclient from tornado.web import HTTPError, asynchronous from tornado.httpclient import HTTPRequest from tornado.options import define, options try: from tornado.curl_httpclient import CurlAsyncHTTPClient as AsyncHTTPClient except 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裡來,有興趣的朋友可以關注一下。

            注< >:更多精彩教程請關注三聯編程

    1. 上一頁:
    2. 下一頁:
    Copyright © 程式師世界 All Rights Reserved