为了学习目的,我创建了以下小型 HTTP 服务器:

import SimpleHTTPServer
import SocketServer

class ServerHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):

    def do_GET(self):
        print(self.headers)
        SimpleHTTPServer.SimpleHTTPRequestHandler.do_GET(self)

    def do_POST(self):
        print(self.headers)
        form = cgi.FieldStorage(
            fp=self.rfile,
            headers=self.headers,
            environ={'REQUEST_METHOD':'POST',
                 'CONTENT_TYPE':self.headers['Content-Type'],

def main():
    port = 50738
    Handler = ServerHandler(1000)
    httpd = SocketServer.TCPServer(("192.168.X.Y", port), Handler)

    print "serving at port", port
    httpd.serve_forever()


if __name__ == "__main__":
    main()

我的假设如下:
  • 我的类“ServerHandler”通过两个函数扩展 SimpleHTTPServer.SimpleHTTPRequestHandler 类,即 go_GET 和 do_POST
  • main() 函数创建一个服务器处理程序对象和服务器套接字绑定(bind)到我的 I.P.选择的地址和端口,并调用一个函数来无限期地服务/收听。

  • 旁白 :我通过查看 Python DOC https://docs.python.org/2/library/simplehttpserver.html 知道 SimpleHTTPServer.SimpleHTTPRequestHandler 有一个名为 do_GET 的方法,我认为它会被我的 ServerHandler 类中的 do_GET 覆盖?

    问题 :
    与 do_GET 和 do_POST 相关的引擎盖下发生了什么?一旦我们让这个服务器监听指向特定 IP:PORT 的 HTTP“事件”,它会自动知道传入的信号是 GET 还是 POST,一旦遇到,服务器就会调用我的 do_GET 或 do_POST职能?

    最佳答案

    当您调用 SocketServer.TCPServer 时,您将 Handler 类指定为接收传入请求的类。
    SimpleHTTPServer 模块为您提供的所有帮助是提供基本的 HTTP 功能,但您可以自己编写所有这些功能。

    因此,正如您所说,当您定义 Handler 时,您将继承 SimpleHTTPRequestHandler 类的所有方法,但随后会覆盖两个预定义的方法: do_GETdo_POST 。您还可以覆盖类中的任何其他方法。

    但是,如果不是 do_* 中定义的 handle 方法,这些 SimpleHTTPRequestHandler 方法将永远不会被调用,因为 socketserver 模块调用的是这个函数。

    所以如果你只是继承 socketserver.BaseRequestHandler ,你会失去所有功能,因为这个类的 handle() 方法什么都不做:



    ...

    因此,通过从 SimpleHTTPRequestHandler 模块导入 SimpleHTTPServer,您可以立即获得 HTTP 服务器的基本功能。

    所有这些功能都记录在案 here ,其 handle 方法有一个重要的部分:



    handle_one_request()


    ...

    所以最后,在分解 socketserver.TCPServer 如何为你传递的任何类调用 handle() 方法之后,我们看到 SimpleHTTPRequestHandler 如何实现这一点,将请求传递给适当的 do_GETdo_POST 或任何方法,具体取决于请求的 header 。

    如果您想了解如何自己实现,请查看 /usr/lib/pythonX.Y/http/server.pyGitHub 中的源代码。

    我们可以在那里看到 SimpleHTTPServer 继承了 BaseHTTPServer 的内容,其中 handle()handle_one_request() 方法被定义:

    因此,正如文档所描述的,handle 只是将请求传递给 handle_one_request,直到连接关闭:

    def handle(self):
        """Handle multiple requests if necessary."""
        self.close_connection = True
    
        self.handle_one_request()
        while not self.close_connection:
            self.handle_one_request()
    
    handle_one_request 是调用 do_* 方法的地方:
    def handle_one_request(self):
        """Handle a single HTTP request.
        You normally don't need to override this method; see the class
        __doc__ string for information on how to handle specific HTTP
        commands such as GET and POST.
        """
        try:
            self.raw_requestline = self.rfile.readline(65537)
            if len(self.raw_requestline) > 65536:
                self.requestline = ''
                self.request_version = ''
                self.command = ''
                self.send_error(HTTPStatus.REQUEST_URI_TOO_LONG)
                return
            if not self.raw_requestline:
                self.close_connection = True
                return
            if not self.parse_request():
                # An error code has been sent, just exit
                return
            mname = 'do_' + self.command   ## the name of the method is created
            if not hasattr(self, mname):   ## checking that we have that method defined
                self.send_error(
                    HTTPStatus.NOT_IMPLEMENTED,
                    "Unsupported method (%r)" % self.command)
                return
            method = getattr(self, mname)  ## getting that method
            method()                       ## finally calling it
            self.wfile.flush() #actually send the response if not already done.
        except socket.timeout as e:
            #a read or a write timed out.  Discard this connection
            self.log_error("Request timed out: %r", e)
            self.close_connection = True
            return
    

    (注意,我对( ## )我的评论进行了双重哈希处理,以将它们与原作者的评论分开)

    关于python - python 的 SimpleHTTPServer do_GET 和 do_POST 函数是如何工作的?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/50944323/

    10-10 19:22