2014-02-26 41 views
0

我試圖通過Python中的tornado製作代理服務器。簡單的http代理服務器運行良好,但https代理有一些問題。 我的程序中可能有問題的部分內容如下。Tornado https代理輸出405警告

import tornado.ioloop 
from tornado.web import RequestHandler, Application 
from tornado.httpclient import AsyncHTTPClient, HTTPRequest 
from tornado.httpserver import HTTPServer 

class HTTPSHandler(RequestHandler): 
    @tornado.web.asynchronous 
    def get(self): 
     print self.request.host, self.request.method 
     def handle_request(response): 
      if response.error and not isinstance(response.error, tornado.httpclient.HTTPError): 
       print "Error:", response.error 
      else: 
       self.write(response.body) 
      self.finish(" ")#in case of response.body == None 

     request = self.request 
     req = HTTPRequest(url=request.uri, method=request.method, 
          headers=request.headers, body=request.body, 
          allow_nonstandard_methods = True, follow_redirects = False, 
          validate_cert=True) 

     http_client = AsyncHTTPClient() 
     try: 
      http_client.fetch(req, handle_request) 
     except Exception as e: 
      print e 

    @tornado.web.asynchronous  
    def post(self): 
     return self.get() 
    @tornado.web.asynchronous  
    def head(self): 
     return self.get() 
    @tornado.web.asynchronous  
    def delete(self): 
     return self.get() 
    @tornado.web.asynchronous  
    def patch(self): 
     return self.get() 
    @tornado.web.asynchronous  
    def put(self): 
     return self.get() 
    @tornado.web.asynchronous  
    def options(self): 
     return self.get() 

if __name__ == "__main__": 
    app2 = Application([(r"https:.*", HTTPSHandler),]) 
    httpsServer = HTTPServer(app2, ssl_options = { 
      "certfile": "./server.crt", 
      "keyfile": "./server.key", 
      }) 
    app2.listen(444) 
    tornado.ioloop.IOLoop.instance().start() 

它輸出像下方的警告(當我訪問https://www.google.comhttps://github.com

WARNING:tornado.access:405 CONNECT www.google.co.jp:443 (127.0.0.1) 0.69ms 
WARNING:tornado.access:405 CONNECT github.com:443 (127.0.0.1) 0.58ms 

最後,將使用https網頁協議不能被與瀏覽器的錯誤顯示。

ERR_TUNNEL_CONNECTION_FAILED 

我想這是龍捲風的requestHandler造成的,因爲它不支持CONNECT方法。 我的問題是如何使用CONNECT方法?

回答

0

我注意到解決這個問題的方法。

首先,SUPPORTED_METHOD應該寫在HTTPSHandler類中。 這可以解決405警告和瀏覽器錯誤。

class HTTPSHandler(RequestHandler): 
    SUPPORTED_METHODS = ("CONNECT", "GET", "HEAD", "POST", "DELETE", "PATCH", "PUT", "OPTIONS") 
    @tornado.web.asynchronous 
    def get(self): 

這是寫在官方文件如下。

If you want to support more methods than the standard GET/HEAD/POST, you 
should override the class variable ``SUPPORTED_METHODS`` in your 
`RequestHandler` subclass. 

此外,爲處理和加工CONNECT方法請求,需要在HTTPSHandler類的其他方法。

@tornado.web.asynchronous 
def connect(self): 
    print "some specific processings here" 

最後,我在正則表達式和ssl_option中犯了愚蠢的錯誤。

app2 = Application([(r"https:.*", HTTPSHandler),]) # not correct 
app2 = Application([(r".*", HTTPSHandler),])  # correct 
httpServer = HTTPServer(app2)      # ssl_options is not needed 
1

理論上你應該能夠像WebSocketHandler一樣工作,通過劫持底層連接的IOStream來實現CONNECT方法。但要警告這是未知的領域; HTTP代理協議與普通HTTP有一些不同,我不知道它將如何在正常的應用程序級HTTP服務之上實現代理。