Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PUT requests for zero-byte files get 'Transfer-Encoding': 'chunked' header #6294

Open
radu-malliu opened this issue Nov 23, 2022 · 0 comments

Comments

@radu-malliu
Copy link

Context: uploading files to AWS S3 via requests. Files may be empty. When attempting to upload an empty file, a response of 501: Not implemented is received. This seems to be because, when content length is 0, a Transfer-Encoding: chunked header is automatically added. S3 does not support the encoding.

Expected Result

When an empty file PUT is attempted via requests.put, a Content-Length: 0 header should be set on the request. A Transfer-Encoding: chunked header should not be set automatically.

Actual Result

When an empty file PUT is attempted via requests.put, a Transfer-Encoding: chunked header is set. No Content-Length header is set. If a Content-Length: 0 header is set explicitly, the Transfer-Encoding: chunked header is still set.

Reproduction Steps

If AWS account, bucket, credentials for principal with PutObject permissions aren't available:

import requests

file = open(<path_to_empty_file>, "rb")
session = requests.session()

link = "http://httpbin.org/put"

# using requests.put yields the same results. Using session.put here to examine request
# with S3 instead of httpbin.org, the call below results in a 501. Note the request headers
res_no_CL = session.put(link, data=file, headers={"Content-Type": "text/plain"})
print(res_no_CL.request.headers)
# with S3 instead of httpbin.org, the call below results in a 501. With httpbin.org it returns
# ConnectionError: ('Connection aborted.', RemoteDisconnected('Remote end closed connection without response'))
# so can't examine headers, but I assume behaviour is consistent
res_explicit_CL = session.put(link, data=file, headers={"Content-Type": "text/plain", "Content-Length": "0"})
print(res_explicit_CL.request.headers)

If AWS prerequisites above are available:

import requests
import boto3

s3 = boto3.client('s3')
file = open(<path_to_empty_file>, "rb")
session = requests.session()

link = s3.generate_presigned_url(ClientMethod="put_object", Params={"Bucket": "<your_bucket>", "Key": "<path_in_bucket>", "ContentType": "text/plain"})

# using requests.put yields the same results. Using session.put here to examine request
# the call below results in a 501. Note the request headers
res_no_CL = session.put(link, data=file, headers={"Content-Type": "text/plain"})
print(res_no_CL.request.headers)
# the call below results in a 501. Note the request headers
res_explicit_CL = session.put(link, data=file, headers={"Content-Type": "text/plain", "Content-Length": "0"})
print(res_explicit_CL.request.headers)

System Information

$ python -m requests.help
{
  "chardet": {
    "version": null
  },
  "charset_normalizer": {
    "version": "2.1.1"
  },
  "cryptography": {
    "version": ""
  },
  "idna": {
    "version": "3.4"
  },
  "implementation": {
    "name": "CPython",
    "version": "3.9.5"
  },
  "platform": {
    "release": "5.10.102.1-microsoft-standard-WSL2",
    "system": "Linux"
  },
  "pyOpenSSL": {
    "openssl_version": "",
    "version": null
  },
  "requests": {
    "version": "2.28.1"
  },
  "system_ssl": {
    "version": "1010106f"
  },
  "urllib3": {
    "version": "1.26.12"
  },
  "using_charset_normalizer": true,
  "using_pyopenssl": false
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant