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

TimeoutError instead of 403 "Forbidden" in case of not corresponding content length #8382

Open
1 task done
PrzemyslawSagalo opened this issue Apr 25, 2024 · 5 comments
Open
1 task done
Labels
bug needs-info Issue is lacking sufficient information and will be closed if not provided

Comments

@PrzemyslawSagalo
Copy link

Describe the bug

I use aiohttp to upload a file to an AWS S3 bucket using a pre-signed URL.

The header of the PUT request has a Content-Length parameter. If the length specified in the header differs from the actual length of the data being sent, it will cause a TimeoutError instead of returning a 403 "Forbidden" SignatureDoesNotMatch

In my case, these values can be different because the value in the headers is taken from metadata calculated in a different system. Sending it in the headers is necessary to perform validation.

To Reproduce

with open(file_path, "rb") as f:
    async with aiohttp.ClientSession(raise_for_status=False) as async_session:
        data = f.read()
        headers = {
            "Content-MD5": md5_value,
            "Content-Length": str(size_value),
            "Content-Type": "application/octet-stream",
        }
        resp = await async_session.request(method='PUT', url=url_s3_presigned, headers=headers, data=data)

Expected behavior

Return response with 403 "Forbidden" instead of raising TimeoutError

Logs/tracebacks

NA

Python Version

Python 3.11.6

aiohttp Version

Name: aiohttp
Version: 3.9.5
Summary: Async http client/server framework (asyncio)
Home-page: https://github.com/aio-libs/aiohttp
Author:
Author-email:
License: Apache 2
Location: /home/ubuntu/src/venv/lib/python3.11/site-packages
Requires: aiosignal, attrs, frozenlist, multidict, yarl
Required-by:

multidict Version

Name: multidict
Version: 6.0.5
Summary: multidict implementation
Home-page: https://github.com/aio-libs/multidict
Author: Andrew Svetlov
Author-email: [email protected]
License: Apache 2
Location: /home/ubuntu/src/venv/lib/python3.11/site-packages
Requires:
Required-by: aiohttp, yarl

yarl Version

Name: yarl
Version: 1.9.4
Summary: Yet another URL library
Home-page: https://github.com/aio-libs/yarl
Author: Andrew Svetlov
Author-email: [email protected]
License: Apache-2.0
Location: /home/ubuntu/src/venv/lib/python3.11/site-packages
Requires: idna, multidict
Required-by: aiohttp

OS

Distributor ID: Ubuntu
Description: Ubuntu 20.04.6 LTS
Release: 20.04
Codename: focal

Related component

Client

Additional context

No response

Code of Conduct

  • I agree to follow the aio-libs Code of Conduct
@Dreamsorcerer
Copy link
Member

This is on making a request. Why do you think it's an issue with aiohttp? As far as I can see from your example, the server is not responding. If that's really the expected format of a request (which seems weird to me), then surely the issue is with the server.

But, I'd expect any HTTP server to respond that way, i.e. if the Content-Length is longer than the data you sent, then it should continue waiting for the rest of the data. How would the server know when the data has finished being sent otherwise?

@PrzemyslawSagalo
Copy link
Author

This is on making a request. Why do you think it's an issue with aiohttp? As far as I can see from your example, the server is not responding. If that's really the expected format of a request (which seems weird to me), then surely the issue is with the server.

But, I'd expect any HTTP server to respond that way, i.e. if the Content-Length is longer than the data you sent, then it should continue waiting for the rest of the data. How would the server know when the data has finished being sent otherwise?

When I am making exactly the same request, using requests or httpx, it just returns 403, which I described earlier.

@Dreamsorcerer
Copy link
Member

What's the URL? The most common difference from those libraries is that URLs get encoded, so if you have query params they should be passed with the params parameter, or using an encoded URL: https://docs.aiohttp.org/en/stable/client_quickstart.html#passing-parameters-in-urls

That might explain the different response, if you are actually requesting a different path.

@PrzemyslawSagalo
Copy link
Author

@Dreamsorcerer Thank you for your response.
Yes, the URL contains a few query params like:

X-Amz-Security-Token
X-Amz-Algorithm
X-Amz-Date
X-Amz-SignedHeaders
X-Amz-Expires

and so on and I get an already composed url with all params.

I have wrapped the url by

from yarl import URL
url = URL(url, encoded=True)

but it still raises timeout.

@Dreamsorcerer
Copy link
Member

If this is still an issue with the latest release, then we need a reproducer that we can easily execute in order to investigate further. As mentioned before, the description of the problem just sounds like you're sending an invalid HTTP request where the expected behaviour is for the server to wait indefinitely for data your failing to send. So, without a reproducer there's no way we can guess what is going on here.

@Dreamsorcerer Dreamsorcerer added the needs-info Issue is lacking sufficient information and will be closed if not provided label Sep 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug needs-info Issue is lacking sufficient information and will be closed if not provided
Projects
None yet
Development

No branches or pull requests

2 participants