龙卷风https代理输出405警告

时间:2014-02-26 01:48:51

标签: python https proxy tornado

我试图通过Python中的龙卷风制作代理服务器。简单的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

我猜,这是由龙卷风的requestHandler引起的,因为它不支持CONNECT方法。 我的问题是如何使用CONNECT方法?

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:0)

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

首先,应该在HTTPSHandler类中编写SUPPORTED_METHOD。 这可以解决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