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

Add a new instance variable to subclass of http.server.BaseHTTPRequestHandler

我希望能够向 http.server.BaseHTTPRequestHandler 的子 class 添加一个实例变量。

这是我的代码:

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()

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

上面的代码不起作用——当调用 do_GETdo_POST 时它会抱怨 'Server' object has no attribute 'pathobj'.

上面docs for http.server.BaseHTTPRequestHandler说:

All of the relevant information is stored in instance variables of the handler. Subclasses should not need to override or extend the __init__() method.

但我看不到其他方法。可能吗?

文档说

The handler will parse the request and the headers, then call a method specific to the request type.

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

因此,为了使这项工作正常进行,您需要将 self.pathobj 行移动到 super() 行上方,然后重写它以执行 BaseHTTPRequestHandler 所做的解析构造 self.path.