如何绕过 Boto3 put_object 方法中 S3 服务器 100 连续响应的预期

问题描述 投票:0回答:1

我正在尝试运行一个简单的 boto3 客户端程序,将一个对象放入工作 S3 服务器上的存储桶中。我确信服务器已启动且配置正确,因为我可以通过curl 和AWS Java SDK 等完美上传。事实上,我可以从失败的boto3 脚本中获取调试日志行并将其转换为curl 请求而且它们工作得很好。我正在尝试上传一个非常小的文件,长度只有 136 字节。

但是,我的 S3 服务器在发送正文之前不会发送 100 个继续响应。但 boto3 和 botocore 期望在 put_object 请求中传递正文之前收到 100 响应。此外,boto3 和 botocore 似乎在初始标头集中指定了主体的内容长度,这意味着服务器无休止地等待 136 字节的内容到达。结果是服务器空闲,等待主体传输,而客户端则超时等待永远不会到来的 100 响应。该文件从未上传。该服务器是商业产品,因此我无法更改其 S3 或 HTTP 配置的任何内容。我坚持原来的设置。

是否有一种简单的方法可以绕过客户端代码中的 100 响应代码预期,或者即使未返回 100 也强制传输请求正文?

这是我的 boto3 代码。是的,我知道 sigV4 更好,但我在 V2 或 V4 上也有同样的问题,并且在使用其他程序进行调试时,V2 更容易生成签名。这只是草稿。

import boto3
import botocore
import logging
import warnings
from boto3.compat import PythonDeprecationWarning
from botocore.config import Config
import http.client as http_client

# Suppress deprecation warnings
warnings.filterwarnings("ignore", category=PythonDeprecationWarning)

# Configure logging
logging.basicConfig(level=logging.DEBUG)

# Configure to use Signature Version 2
config = Config(
    signature_version='s3',
    retries = {'max_attempts': 0},
    s3 = {
        'use_accelerate_endpoint': False,
        'expect_100_continue': False
    }
)

# Initialize the S3 client with the custom endpoint and configuration
s3 = boto3.client('s3', endpoint_url='http://<my-domain>:80', config=config)

# Upload the file
try:
    with open('jeremy_test.txt', 'rb') as data:
        s3.put_object(
            Bucket='a-bucket', 
            Key='jeremy_upload.txt', 
            Body=data.read(), 
            ContentType='text/plain'
        )
    print("File uploaded successfully.")
except Exception as e:
    print(f"An error occurred: {e}")

以下是显示所发生情况的相关日志文件:

DEBUG:botocore.hooks:Event request-created.s3.PutObject: calling handler <function add_retry_headers at 0x7f4c43cbb4d0>
DEBUG:botocore.endpoint:Sending http request: <AWSPreparedRequest stream_output=False, method=PUT, url=http://<my-domain>:80/a-bucket/jeremy_upload.txt, headers={'Content-Type': b'text/plain', 'User-Agent': b'Boto3/1.33.13 md/Botocore#1.33.13 ua/2.0 os/linux#4.18.19-100.fc27.x86_64 md/arch#x86_64 lang/python#3.7.11 md/pyimpl#CPython cfg/retry-mode#legacy Botocore/1.33.13', 'Content-MD5': b'p5noto3k/PSRC+Krl8ivcQ==', 'Expect': b'100-continue', 'Date': b'Fri, 27 Sep 2024 03:13:32 GMT', 'Authorization': b'AWS rUNA7sEVArrRIaEp3zlA:/SY4HtAuh4x7edFBU5u8krHMGz4=', 'amz-sdk-invocation-id': b'616bbf1b-f8fb-448e-9c33-340c6d7b614c', 'amz-sdk-request': b'attempt=1', 'Content-Length': '136'}>
DEBUG:urllib3.connectionpool:Starting new HTTP connection (1): <my-domain>:80
send: b'PUT /a-bucket/jeremy_upload.txt HTTP/1.1\r\nHost: <my-domain>\r\nAccept-Encoding: identity\r\nContent-Type: text/plain\r\nUser-Agent: Boto3/1.33.13 md/Botocore#1.33.13 ua/2.0 os/linux#4.18.19-100.fc27.x86_64 md/arch#x86_64 lang/python#3.7.11 md/pyimpl#CPython cfg/retry-mode#legacy Botocore/1.33.13\r\nContent-MD5: p5noto3k/PSRC+Krl8ivcQ==\r\nExpect: 100-continue\r\nDate: Fri, 27 Sep 2024 03:13:32 GMT\r\nAuthorization: AWS rUNA7sEVArrRIaEp3zlA:/SY4HtAuh4x7edFBU5u8krHMGz4=\r\namz-sdk-invocation-id: 616bbf1b-f8fb-448e-9c33-340c6d7b614c\r\namz-sdk-request: attempt=1\r\nContent-Length: 136\r\n\r\n'
DEBUG:botocore.awsrequest:Waiting for 100 Continue response.
reply: '\r\n'
DEBUG:botocore.hooks:Event needs-retry.s3.PutObject: calling handler <botocore.retryhandler.RetryHandler object at 0x7f4c46343e90>
An error occurred: Connection was closed before we received a valid response from endpoint URL: "http://<my-domain>:80/a-bucket/jeremy_upload.txt".

我尝试过事件处理程序,并将配置设置为不期望_100_继续。我尝试过事件处理程序,但我对 boto3/botocore 很陌生,所以我没有运气。

python amazon-web-services amazon-s3 boto3
1个回答
0
投票

如果你想使用

boto3
,那你就不走运了,我猜其他 SDK 最终也会效仿它。

API 文档 没有提及接收 100 状态代码的可能性,尽管示例确实显示了 Expect: 100-continue

 请求标头。但是,
S3 用户指南 确实如此:100 状态旨在进行优化,以避免在重定向时多次发送请求正文。

不幸的是,

botocore

无条件地将
Expect
标头添加到请求中(在
handlers.py
add_expect_header()
中,这是基于
请求操作表调用的。然后,如果设置了标头,则等待 100 回复.

因此,要么您需要更新您的服务器以使其表现得像 S3(包括 API 文档之外记录的部分),要么您需要分叉

botocore

 以使该标头可选或完全删除它。

如果您选择后者,也许可以通过配置设置来控制它,然后将补丁提交回 AWS。

© www.soinside.com 2019 - 2024. All rights reserved.