The way to implement the proxy many kinds of popular web server also has a proxy function, such as http://www.tornadoweb.cn with Nginx proxy function to do the Tornadoweb official website image.
Recently, I was developing a background program (SERVER) for mobile applications that needed to invoke an API to another platform product (Platform). For this system, an optional way to do this is to interact with both the Server&platform and the platform, and the Api,app that encapsulates the server side only interacts with the server. Obviously, the latter way of the system architecture will be clear, app programming is relatively simple. So how to encapsulate the Platform API on the server side, the first thing I think about is to use the proxy way to achieve. It happened that recently someone in the Tornado Mail group was talking about using Tornado as a proxy, the application scenario mentioned by the owner was very similar to the one I met, and I did some sorting and simplification of the original post code, the source code is as follows:
#-*-Coding:utf-8-*-## Copyright (c) Felinx Lee & http://feilong.me/## Licensed under the Apache License, Versi On 2.0 (the "License"); You may# don't use this file except in compliance with the License. obtain# a copy of the License at## http://www.apache.org/licenses/LICENSE-2.0## unless required by applicable LA W or agreed to writing, software# distributed under the License are distributed on a "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) Defi NE ("api_protocol", default= "http") define ("Api_host", default= "Feilong.me") define ("Api_port", default= "a") define ( "Debug", Default=true, Type=bool) class Proxyhandler (Tornado.web.RequestHandler): @asynchronous def get (self): # Enab Le API GET request when debugging if Options.debug:return self.post () else:raise httperror (405) @async Hronous def post (self): protocol = Options.api_protocol host = options.api_host port = options.api_port # PO RT Suffix Port = "if Port = =" "Else":%s "% port uri = Self.request.uri url ="%s://%s%s%s "% (protocol, HO St, 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 Hasatt R (X, "response") and X.response:self._on_proxy (x.response) else:logging.error ("Tornado signalled HTTP Error%s ", x) def _on_proxy (self, Response): If Response.error and not isinstance (Response.error, Tornado.httpclient.HTTPError): Raise Httperror (+) Else:self.set_status (Response.code) for header I N ("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 ()
After running the above code, access to http://localhost:8888/will show the first page of the Dragon blog, that is, the agent visited the http://feilong.me/content.
I consider the way to use the program as an agent instead of using nginx directly to do the proxy, one of the considerations is that the program can easily control which APIs are required to platform, and which are to be masked, and what may be rewritten ( For example, the server login may not directly proxy platform login, but will be called to the platform login API).
The above code just do a simple page content agent, and no further parsing of the page, such as chain replacement, and so on, these are interested in a friend to develop. Based on the above code, it is completely possible to implement a complete online agent program.
This code I have put in my experiment project, see Https://bitbucket.org/felinx/labs, I will put more similar to such experimental small project into this repository, interested friends can pay attention to.
Reprint Please specify source: Http://feilong.me/2011/09/tornado-as-a-proxy