HTTPServer.run 需要 BaseHTTPRequestHandler 类而不是对象

tan*_*oal 5 python http http-headers python-3.x

我有一个自己的类,派生自 BaseHTTPRequestHandler,它实现了我的特定 GET 方法。这工作得很好:

from http.server import BaseHTTPRequestHandler, HTTPServer

class MyHTTPRequestHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        """ my implementation of the GET method """

myServer = HTTPServer(("127.0.0.1", 8099), MyHTTPRequestHandler)
myServer.handle_request()
Run Code Online (Sandbox Code Playgroud)

但为什么我需要通过我的MyHTTPRequestHandler课程HTTPServer我知道文档要求它:

类http.server.BaseHTTPRequestHandler(请求,客户端地址,服务器)

该类用于处理到达服务器的 HTTP 请求。它本身无法响应任何实际的 HTTP 请求;必须对其进行子类化以处理每个请求方法(例如 GET 或 POST)。BaseHTTPRequestHandler 提供了许多类和实例变量以及供子类使用的方法。

处理程序将解析请求和标头,然后调用特定于请求类型的方法。方法名称是根据请求构造的。例如,对于请求方法 SPAM,将不带参数调用 do_SPAM() 方法。所有相关信息都存储在处理程序的实例变量中。子类不应该需要重写或扩展init () 方法。

我确实想传递我的子类的实例化对象。我不明白为什么要这样设计,对我来说这看起来像是设计失败。具有多态性的面向对象编程的目的是我可以子类化以使用相同的接口实现特定的行为,所以在我看来这是一个不必要的限制。

这就是我想要的:

from http.server import BaseHTTPRequestHandler, HTTPServer

class MyHTTPRequestHandler(BaseHTTPRequestHandler):
    def __init__(self, myAdditionalArg):
        self.myArg = myAdditionalArg

    def do_GET(self):
        """ my implementation of the GET method """
        self.wfile(bytes(self.myArg, "utf-8"))
        # ...

myReqHandler = MyHTTPRequestHandler("mySpecificString")
myServer = HTTPServer(("127.0.0.1", 8099), myReqHandler)
myServer.handle_request()
Run Code Online (Sandbox Code Playgroud)

但如果我这样做,显然我会收到预期的错误消息:

类型错误:“MyHTTPRequestHandler”对象不可调用

如何解决这个问题,以便我仍然可以使用打印特定字符串?我需要这个的还有第二个原因:我希望MyHTTPRequestHandler它还提供有关客户端的更多信息,客户端使用 GET 方法从服务器检索数据(我想检索客户端浏览器的 HTTP 标头)。

我只有一个客户端向服务器发起一个请求。如果一个解决方案可以在更一般的环境中工作,我会很高兴,但我当前的项目不需要它。

有人有想法这样做吗?

tan*_*oal 1

可以派生出一个特定的HTTPServer类 ( MyHttpServer),它具有以下属性:

  • myArg:HTTP 请求处理程序应打印的特定“消息文本”
  • headers:存储 HTTP 请求处理程序设置的标头的字典

服务器类必须与 一起打包MyHTTPRequestHandler。此外,该实施仅在以下条件下才能正常工作:

  • 只有一个 HTTP 请求处理程序同时向服务器请求响应(否则属性保存的数据将被损坏)
  • MyHTTPRequestHandler只能与MyHttpServer一起使用,反之亦然(否则可能会发生未知的副作用,例如异常或数据损坏)

这就是为什么这两个类必须以如下方式打包和运输:

from http.server import BaseHTTPRequestHandler, HTTPServer

class MyHTTPRequestHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        self.wfile.write(bytes(self.server.myArg, 'utf-8'))
        #...
        self.server.headers = self.headers

class MyHttpServer(HTTPServer):
    def __init__(self, server_address, myArg, handler_class=MyHttpRequestHandler):
        super().__init__(server_address, handler_class)
        self.myArg = myArg
        self.headers = dict()
Run Code Online (Sandbox Code Playgroud)

这些类的用法可能如下所示,而服务器仅响应客户端(即 Web 浏览器)的一个请求:

def get_header():
    httpd = MyHttpServer(("127.0.0.1", 8099), "MyFancyText", MyHttpRequestHandler)
    httpd.handle_request()
    return httpd.headers
Run Code Online (Sandbox Code Playgroud)