You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

本地部署Amazon S3用curl上传对象返回400错误请求排查

排查curl上传本地S3存储返回400 Bad Request的问题

由于Linux服务器限制无法使用AWS CLI,尝试通过curl命令向本地部署的Amazon S3存储上传文件,执行的curl命令如下:

curl -k -X PUT -T "/tmp/payload.txt" 
-H "Host: xyz-bl.s3.amazonaws.com" 
-H "Date: Thu, 21 Nov 2024 12:45:35 +345" 
-H "Content-Type: text/plain" 
-H "Authorization: AWS xyz-bl-usr:PAuh+xxxxxxxx" 
https://on-prem.s3.com:343/payload.txt

签名计算逻辑:

s3_resource="/${bucket_name}/${file}"
string_to_sign="PUT

${content_type}
${date_value}
${s3_resource}"
signature=`echo -en ${string_to_sign} | openssl sha1 -hmac ${aws_secret_access_key} -binary | base64`

在Windows(GitBash)和Ubuntu环境中均返回400 Bad Request,以下是可能的问题点:

  • Host头与请求URL不匹配
    curl请求的URL指向on-prem.s3.com:343,但Host头设置为xyz-bl.s3.amazonaws.com。本地部署的S3兼容存储需要Host头与实际服务地址匹配,或者按配置使用bucket作为子域名(如xyz-bl.on-prem.s3.com:343),不匹配的Host头会导致服务无法识别目标bucket,触发400错误。

  • Date头格式无效
    当前Date值为Thu, 21 Nov 2024 12:45:35 +345,HTTP标准的Date格式要求时区偏移为四位(如+0000或GMT),+345属于非法格式,S3服务无法解析该时间,会导致签名验证失败返回400。

  • 签名计算的s3_resource与请求模式不匹配
    如果请求URL是https://on-prem.s3.com:343/payload.txt(虚拟主机模式,bucket在Host头中),那么s3_resource应该是/payload.txt而非/${bucket_name}/${file};如果是路径模式(URL为https://on-prem.s3.com:343/xyz-bl/payload.txt),才需要用/xyz-bl/payload.txt。两种模式的签名resource部分不同,混淆会导致签名无效。

  • 换行符处理不一致导致签名错误
    echo -en在不同环境(GitBash/Ubuntu)下处理换行符的行为有差异,可能导致生成的string_to_sign不符合S3签名要求。建议用printf替代echo来保证换行符一致性:

    string_to_sign=$(printf "PUT\n\n%s\n%s\n%s" "${content_type}" "${date_value}" "${s3_resource}")
    
  • 请求URL路径未包含bucket信息
    若bucket名称为xyz-bl,正确的请求路径应为https://on-prem.s3.com:343/xyz-bl/payload.txt(路径模式)或https://xyz-bl.on-prem.s3.com:343/payload.txt(虚拟主机模式)。当前URL直接指向/payload.txt,服务无法识别目标bucket,会返回400。

内容的提问来源于stack exchange,提问作者Shades88

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 05:27:13