This article mainly introduced in the Python Tornado framework to implement a simple online proxy tutorial, the agent function is a common network programming realization, needs The friend may refer to under
Many ways to implement the agent, the popular Web server is also mostly agent functions, such as http://www.tornadoweb.cn with the Nginx agent function to do tornadoweb official website mirroring.
Recently, I was developing a background program (Server) for mobile apps (app) that needed to invoke APIs to another platform product (Platform). An optional way to implement this system is that the app interacts with both Server&platform, while the other encapsulates the platform Api,app only with the server on the server side. Obviously the system architecture in the latter way will be clearer, and app programming will be relatively simple. So how to encapsulate the Platform API on the server side, the first thing I think of is to use the proxy method to implement. It happened that recently someone in the Tornado Mail group was discussing using Tornado as a proxy, and the application scenario mentioned by the owner was very similar to the scene I met, and I did some sorting and simplification of the original post code, the source code is as follows:
|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 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 5 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100-101||#-*-Coding:utf-8-*-# Copyright (c) Felinx Lee & http://3lian.me/# Licensed under the Apache License, Ve Rsion 2.0 (the "License"); Use the ' may ' # not ' use ' this file except in compliance with the License. Your may obtain # a copy of the License in # # http://www.apache.org/licenses/LICENSE-2.0 # unless required by applicable Writing, software # Distributed under the License is distributed on ' as is ' basis, without # Warra Nties or CONDITIONS of any KIND, either express OR implied. The # License for the specific language governing permissions and limitations the under. Import logging Import tornado.httpserver import tornado.ioloop import tornado.options import tornado.web Imp ORT tornado.httpclient from Tornado.web import Httperror, asynchronous from tornado.httpclient import HttpRequest from Tor Nado.options import define, Options Try:from tornado.curl_httpclient import curlasynchttpclient as Asynchttpclient excep T 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=) define ("Debug", Default=true, Type=bool) class Proxyhandler ( Tornado.web.RequestHandler): @asynchronous def get (self): # Enable APIs GET request when debugging if Options.debug:return Self.post () else:raise httperror (405) @asynchronous def post (self): protocol = options.api_protocol host = option S.api_host port = options.api_port # port suffix port = "" If port = = "Else":%s "% port URI = self.requ Est.uri url = "%s://%s%s%s"% (protocol, host, Port, URI) # Update host to destination Host headers = Dict (self.req Uest.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.err Or and not isinstance (Response.error, Tornado.httpclient.HTTPError): Raise Httperror () Else:self.set_status ( Response.code) for header in ("Date", "Cache-control", "Server", "Content-type", "Location"): v = response.headers.get (He Ader) if V:self.set_header (header, v) if Response.body:self.write (response.body) self.finish () def main (): Tornad O.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 ()|
Run the above code, access to http://localhost:8888/will be complete display of the home of the Dragon blog, that is, the agent visited the content of the http://feilong.me/.
I consider using a program as a proxy instead of using Nginx directly as an agent, one of which is to consider that it is easy to use a program to control which APIs platform need to be represented, which are to be blocked, and what might be rewritten ( For example, the server login may not be able to directly proxy platform login, but to call to the platform login API.
The above code just do a simple page content agent, and no further analysis of the page to deal with, such as chain replacement and so on, these are interested in a friend to develop. Based on the above code, it can be extended to a complete online agent.
This code I have put into my experimental project, see Https://bitbucket.org/felinx/labs, I will put more similar to the experimental nature of the small project into this repository, interested friends can pay attention to.
Note < > : More Wonderful tutorials please focus on Triple programming