向 http.server.BaseHTTPRequestHandler 的子类添加一个新的实例变量

cat*_*cat 6 http python-3.x basehttprequesthandler

我希望能够将实例变量添加到我的http.server.BaseHTTPRequestHandler子类中。

这是我的代码:

from http.server import BaseHTTPRequestHandler, HTTPServer
import urllib


class Server(BaseHTTPRequestHandler):

    def __init__(self, request, client_addr, server):
        super().__init__(request, client_addr, server)
        self.pathobj = urllib.parse.urlparse(self.path)

    def do_HEAD(self):
        self.send_response(200)

    def do_GET(self):
        print(self.pathobj)
        self.send_response(200)
        self.end_headers()

    def do_POST(self):
        print(self.pathobj)
        self.send_response(405)
        self.end_headers()   

def run(server_class=HTTPServer, handler_class=Server, port=8080):
    server_address = ("", port)
    httpd = server_class(server_address, handler_class)

    print("Starting httpd on port {}...".format(port))

    httpd.serve_forever()

if __name__ == "__main__":
    run()
Run Code Online (Sandbox Code Playgroud)

我希望能够访问每个类方法中ParseResult返回的对象,urllib.parse.urlparse而无需在每个类方法self.pathobj = urllib.parse.urlparse(self.path)的开头重写。

上面的代码不起作用 - 当do_GET或被do_POST调用时,它会抱怨'Server' object has no attribute 'pathobj'.

http.server.BaseHTTPRequestHandler的上述文档说:

所有相关信息都存储在处理程序的实例变量中。子类不需要覆盖或扩展该__init__()方法。

但我没有看到另一种方法来做到这一点。是否可以?

小智 1

文档说

处理程序将解析请求和标头,然后调用特定于请求类型的方法。

事实证明,http.server.BaseHTTPRequestHandler最终继承自socketserver.BaseRequestHandler,并且socketserver.BaseRequestHandler.__init__()此处定义)调用do_GET()。所以问题是实例变量实际上是在do_GET()调用之后设置的。

因此,为了使这项工作正常进行,您需要将该self.pathobj行移至该行上方super(),然后重写它以进行BaseHTTPRequestHandler构造self.path.