【问题标题】:Tornado https proxy outputs 405 WARNINGTornado https 代理输出 405 警告
【发布时间】:2014-02-26 01:48:51
【问题描述】:

我尝试在 Python 中通过 tornado 制作代理服务器。简单的 http 代理服务器运行良好,但 https 代理存在一些问题。 我的部分程序可能有问题如下。

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

我猜,这是tornado的requestHandler造成的,因为它不支持CONNECT方法。 我的问题是如何使用 CONNECT 方法?

【问题讨论】:

    标签: python https proxy tornado


    【解决方案1】:

    我已经注意到了解决这个问题的方法。

    首先,SUPPORTED_METHOD 应该写在 HTTPSHandler 类中。 这样可以解决405 WARNING和浏览器错误。

    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
    

    【讨论】:

      【解决方案2】:

      理论上,您应该能够通过劫持底层连接的 IOStream 以与 WebSocketHandler 相同的方式实现 CONNECT 方法。但请注意,这是未知领域; HTTP 代理协议与普通 HTTP 有一些不同,我不知道在普通的应用程序级 HTTP 服务之上实现代理的效果如何。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-06-15
        • 1970-01-01
        • 2013-04-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多