如何在 Python BaseHTTPRequestHandler 中处理分块编码?

2024-04-02

我有以下简单的 Web 服务器,利用 Pythonhttp module:

import http.server
import hashlib


class RequestHandler(http.server.BaseHTTPRequestHandler):
    protocol_version = "HTTP/1.1"

    def do_PUT(self):
        md5 = hashlib.md5()

        remaining = int(self.headers['Content-Length'])
        while True:
            data = self.rfile.read(min(remaining, 16384))
            remaining -= len(data)
            if not data or not remaining:
                break
            md5.update(data)
        print(md5.hexdigest())

        self.send_response(204)
        self.send_header('Connection', 'keep-alive')
        self.end_headers()


server = http.server.HTTPServer(('', 8000), RequestHandler)
server.serve_forever()

当我使用curl上传文件时,效果很好:

curl -vT /tmp/test http://localhost:8000/test

因为文件大小是预先知道的,curl 将发送一个Content-Length: 5header,这样我就可以知道应该从套接字读取多少内容。

但如果文件大小未知,或者客户端决定使用chunkedTransfer-Encoding,这种方法失败了。

可以使用以下命令进行模拟:

curl -vT /tmp/test -H "Transfer-Encoding: chunked" http://localhost:8000/test

如果我从self.rfile超过该块后,它将永远等待并挂起客户端,直到它断开 TCP 连接,其中self.rfile.read将返回一个空数据,然后跳出循环。

需要什么来扩展上述示例以支持chunked也是传输编码吗?


正如您在描述中看到的传输编码 https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Transfer-Encoding,分块传输将具有以下形状:

chunk1_length\r\n
chunk1 (binary data)
\r\n
chunk2_length\r\n
chunk2 (binary data)
\r\n
0\r\n
\r\n

您只需读取一行,获取下一个块的大小,然后消耗两个二进制块and后续换行符。

这个例子将能够处理请求Content-Length or Transfer-Encoding: chunked标头。

from http.server import HTTPServer, SimpleHTTPRequestHandler

PORT = 8080

class TestHTTPRequestHandler(SimpleHTTPRequestHandler):
    def do_PUT(self):
        self.send_response(200)
        self.end_headers()

        path = self.translate_path(self.path)

        if "Content-Length" in self.headers:
            content_length = int(self.headers["Content-Length"])
            body = self.rfile.read(content_length)
            with open(path, "wb") as out_file:
                out_file.write(body)
        elif "chunked" in self.headers.get("Transfer-Encoding", ""):
            with open(path, "wb") as out_file:
                while True:
                    line = self.rfile.readline().strip()
                    chunk_length = int(line, 16)

                    if chunk_length != 0:
                        chunk = self.rfile.read(chunk_length)
                        out_file.write(chunk)

                    # Each chunk is followed by an additional empty newline
                    # that we have to consume.
                    self.rfile.readline()

                    # Finally, a chunk size of 0 is an end indication
                    if chunk_length == 0:
                        break

httpd = HTTPServer(("", PORT), TestHTTPRequestHandler)

print("Serving at port:", httpd.server_port)
httpd.serve_forever()

注意我选择继承自简单HTTP请求处理程序代替基本HTTP请求处理程序,因为那么该方法SimpleHTTPRequestHandler.translate_path()可用于允许客户端选择目标路径(这可能有用也可能没用,具体取决于用例;我的示例已经编写为使用它)。

您可以使用以下命令测试两种操作模式curl命令,正如您提到的:

# PUT with "Content-Length":
curl --upload-file "file.txt" \
  "http://127.0.0.1:8080/uploaded.txt"

# PUT with "Transfer-Encoding: chunked":
curl --upload-file "file.txt" -H "Transfer-Encoding: chunked" \
  "http://127.0.0.1:8080/uploaded.txt"
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 Python BaseHTTPRequestHandler 中处理分块编码? 的相关文章

  • 如何让Python的socket服务器永远运行

    我有这段代码创建了一个简单的Python套接字服务器 但是每次客户端断开连接时它都会关闭 如何让它永远运行 import socket HOST PORT 8000 s socket socket socket AF INET socket
  • 管理 Tweepy API 搜索

    如果这是对之前在其他地方回答过的问题的粗略重复 请原谅我 但我不知道如何使用 tweepy API 搜索功能 是否有任何有关如何使用搜索推文的文档api search 功能 有什么方法可以控制返回的推文数量 结果类型等功能 由于某种原因 结
  • 使用 Pillow 和 Numpy 进行图像推导

    I have two images and 我想导出一个只有红色 Hello 的图像 例如 所以我正在运行一个简单的推导python脚本 from PIL import Image import numpy as np root root
  • 向 polls urls.py 添加额外的过滤器会导致测试失败

    按照 djangoproject 的教程 我尝试让 urls py 过滤掉没有选择下面 urlpattern 的民意调查 urlpatterns patterns url r ListView as view queryset Poll o
  • 顶级棉花糖模式验证

    From 棉花糖 validation http marshmallow readthedocs org en latest quickstart html validation 我知道我可以在架构中的特定字段上注册验证器 如果验证器失败
  • 如何在 kubernetes 上使多个 pod 相互通信

    我是 Kubernetes 新手 我正在尝试通过 microk8s 将应用程序部署到 Kubernetes 该应用程序包含Python Flask后端 Angular前端 Redis和MySQL数据库 我将映像部署在多个 Pod 中 状态显
  • HoughLinesP后如何合并线?

    My task is to find coordinates of lines startX startY endX endY and rectangles 4 lines Here is input file 我使用下一个代码 img c
  • Python Pandas 从宽到长的格式更改以及列标题拆分

    我有一个包含以下列标题和行示例的表 Subject Test1 Result1 Test1 Result2 Test2 Result1 Test2 Result2 0 John 10 0 5 20 0 3 我想将其改造成 Subject l
  • 如何将一串Python代码编译成一个可以调用函数的模块?

    在 Python 中 我有一串 Python 源代码 其中包含以下函数 mySrc def foo print foo def bar print bar 我想将这个字符串编译成某种形式类似模块的对象这样我就可以调用代码中包含的函数 这是我
  • 如何将 pip 指向 Mercurial 分支?

    我正在尝试通过 pip 将我的应用程序安装到 virtualenv 进行测试 安装时效果很好default or tip像这样 pip install e hg https email protected cdn cgi l email p
  • 将 for 循环替换为 pyspark 中的并行进程

    我在脚本中使用 for 循环来为 size DF 数据帧 的每个元素调用函数 但这需要很多时间 我尝试通过地图删除 for 循环 但没有得到任何输出 size DF 是我从表中获取的大约 300 个元素的列表 用于 import call
  • PyPI 上的轮子平台约束有什么限制吗?

    是否有任何地方 PEP 或其他地方 声明关于 Linux 轮子上传范围的限制 PyPI http pypi io 应该有 具体来说 上传是否被认为是可接受的做法linux x86 64轮子到 PyPI 而不是manylinux1 x86 6
  • 使用 .map() 在 pandas DataFrame 中高效创建附加列

    我正在分析形状与以下示例类似的数据集 我有两种不同类型的数据 abc数据和xyz data abc1 abc2 abc3 xyz1 xyz2 xyz3 0 1 2 2 2 1 2 1 2 1 1 2 1 1 2 2 2 1 2 2 2 3
  • 如何使用 Selenium Webdriver (Python) 在上下文菜单中选择“将图像另存为...”来保存图像

    我正在尝试使用 selenium webdriver 将特定图像保存到目录中 我希望通过模拟右键单击 img 元素并选择 将图像另存为 来实现此目的 使用以下代码我可以打开上下文菜单 但无法选择正确的选项 browser WebDriver
  • 让 TensorFlow 在 ARM Mac 上使用 GPU

    我已经安装了TensorFlow在 M1 上 ARM Mac 根据这些说明 https github com apple tensorflow macos issues 153 一切正常 然而 模型训练正在进行CPU 如何将培训切换到GPU
  • 如何从外语线程调用Python函数(C++)

    我正在开发一个程序 使用 DirectShow 来抓取音频数据 媒体文件 DirectShow 使用线程将音频数据传递给回调 我的程序中的函数 然后我让该回调函数调用另一个函数 Python 中的函数 我使用 Boost Python 来包
  • 在Python中将罗马数字转换为整数

    根据 user2486 所说 这是我当前的代码 def romanMap map M 1000 CM 900 D 500 CD 400 C 100 XC 90 L 50 XL 40 X 10 IX 9 V 5 V 4 I 1 return
  • 在Python中打开网站框架或图像

    所以我对 python 相当熟练 并且经常使用 urllib2 和 Cookies 来实现网站自动化 我刚刚偶然发现了 webbrowser 模块 它可以在默认浏览器中打开一个网址 我想知道是否可以从该 url 中仅选择一个对象并打开它 具
  • Matplotlib 渲染日期、图像的问题

    我在使用 conda forge 的 Matplotlib v 3 1 3 和 python 3 7 时遇到问题 我拥有 Matplotlib 所需的所有依赖项 当我输入这段代码时 它应该可以工作 我得到了泼溅艺术 它基于此 YouTube
  • Python模糊字符串匹配作为相关样式表/矩阵

    我有一个文件 其中包含 x 个字符串名称及其关联的 ID 本质上是两列数据 我想要的是一个格式为 x by x 的相关样式表 将相关数据作为 x 轴和 y 轴 但我想要 fuzzywuzzy 库的函数 fuzz ratio x y 作为输出

随机推荐