代码之家  ›  专栏  ›  技术社区  ›  user2064000

asyncio HTTP服务器挂断keepalive

  •  0
  • user2064000  · 技术社区  · 7 年前

    我正在尝试使用asyncio编写一个HTTP/1服务器,并尝试让它处理HTTP keep alives。我有下面的代码。

    import re
    import socket
    import asyncio
    
    async def request_handler(reader, writer):
        try:
            keep_alive = True
    
            while keep_alive:
                keep_alive = False
    
                while True:
                    print('Awaiting data')
                    line = await reader.readline()
                    print('Finished await got %s' % line)
                    if not line.rstrip(b'\r\n'):
                        break
    
                    if re.match(rb'connection:\s*keep-alive', line, re.I):
                        keep_alive = True
    
                writer.write(b'HTTP/1.1 200 OK\r\n\r\n<h1>My web page</h1>\r\n')
                await writer.drain()
        finally:
            writer.close()
    
    if __name__ == '__main__':
        loop = asyncio.get_event_loop()
        coro = asyncio.start_server(request_handler, '', 8888, family=socket.AF_UNSPEC, loop=loop, limit=2048)
        server = loop.run_until_complete(coro) 
    
        try:
            loop.run_forever()
        finally:
            server.close()
            loop.run_until_complete(server.wait_closed())
            loop.close()
    

    对于来自curl等工具的请求,可以在不挂断服务器的情况下正确地处理请求。

    但是,尝试在浏览器中加载URL会导致服务器永远不会终止连接。浏览器试图请求两个资源,一个来自 / 一对一 /favicon.ico

    我试着打印服务器接收到的数据。但是,服务器似乎从未收到第二个请求的数据:

    Awaiting data
    Finished await got b'GET / HTTP/1.1\r\n'
    Awaiting data
    Finished await got b'Host: localhost:8888\r\n'
    Awaiting data
    Finished await got b'Connection: keep-alive\r\n'
    Awaiting data
    Finished await got b'Upgrade-Insecure-Requests: 1\r\n'
    Awaiting data
    Finished await got b'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36\r\n'
    Awaiting data
    Finished await got b'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\n'
    Awaiting data
    Finished await got b'Accept-Encoding: gzip, deflate, br\r\n'
    Awaiting data
    Finished await got b'Accept-Language: en-US,en;q=0.9\r\n'
    Awaiting data
    Finished await got b'\r\n'
    Awaiting data
    

    有人能告诉我问题出在哪里吗?

    1 回复  |  直到 7 年前
        1
  •  3
  •   user4815162342    7 年前

    Content-Length 标题(或使用更复杂的 chunked keep_alive 设置为true。例如,如果将编写代码更改为:

                body = b'<h1>My web page</h1>\r\n'
                writer.write(b'HTTP/1.1 200 OK\r\nContent-Length: %d\r\n\r\n' % len(body))
                writer.write(body)
    

    …连接不再挂起。

    curl Keep-Alive (因为在命令行上只指定了一个URL),所以您的代码将关闭连接,而不需要内容长度。