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

來源:互聯網
上載者:User

在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://bkjia.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裡來,有興趣的朋友可以關注一下。

        注< >:更多精彩教程請關注幫客之家編程

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.