您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

HTTP 的 response 中的响应体和头部是分开发送的吗?

HTTP 的 response 中的响应体和头部是分开发送的吗?

HTTP 报文的组成

image.png

Response 报文由:

  • 状态行 start-line
  • 响应头 HTTP headers
  • 空行 empty-line
  • 响应体 body

四部分组成

参考资料:
mozilla doc:Date
http里的时间格式


好了下面是问题的正文了

我发现一般的 HTTP 服务器在发送 Response 报文的时候,是把(状态行、响应头、空行)作为一个整体发送(即调用一次 socket.send()),然后在调用一次 socket.send() 把响应体 body 发出去。

看了 Gunicorn 服务器,和 aiohttp

为什么不一次发送呢?

下面是 Gunicorn 的两段源代码:

gunicorn/http/wsgi.py

def create(req, sock, client, server, cfg):
    resp = Response(req, sock, cfg)
    environ = default_environ(req, sock, cfg)
    # ...
    environ['PATH_INFO'] = util.unquote_to_wsgi_str(path_info)
    environ['SCRIPT_NAME'] = script_name
    # ....
    return resp, environ

class Response(object):

    def start_response(self, status, headers, exc_info=None):
        # ...

        self.status = status
        self.process_headers(headers)
        return self.write
    def write(self, arg):
        self.send_headers() # 可以看到一句 self.send_headers(), 单独发出了 headers
        # ...
        util.write(self.sock, arg, self.chunked)

�� 可以看到一句 self.send_headers(), 单独发出了 headers

gunicorn/util.py

def write(sock, data, chunked=False):
    if chunked:
        return write_chunk(sock, data)
    sock.sendall(data)

下面是一段 aiohttp 的 demo 代码。

import aiohttp
import asyncio


async def fetch(session, url):
    async with session.get(url) as resp:
        if resp.status != 200:
            resp.raise_for_status()
        data = await resp.text()
        return data

�� 比如 aiohttp 在获取 response.text 的时候会加一个 await,我不明白为什么要加 await ,因为客户端接收到 response 的时候,已经包含 text 了呀,为什么还要加一个 await 呢?除非是 text 是单独发送的,所以才会有 IO 等待的问题,是这样吗?


总结一下,问题的核心就是一般的 HTTP 服务器(nginxhttpdtomcatuwsgi等等),在调用 socket 的 send 给 client 发送 HTTP response 的时候,是不是都是先调用一次 socket.send 发送不包含 body 的部分,在调用 N 次发送 body 的呢?

php 2022/2/19 17:47:54 有1478人围观

撰写回答


你尚未登录,登录后可以

和开发者交流问题的细节

关注并接收问题和回答的更新提醒

参与内容的编辑和改进,让解决方法与时俱进

请先登录

推荐问题


联系我
置顶