aio-libs / aiohttp

Asynchronous HTTP client/server framework for asyncio and Python
https://docs.aiohttp.org
Other
14.99k stars 2k forks source link

Request content is not returned on specific URL #2076

Closed mkapuza closed 1 week ago

mkapuza commented 7 years ago

Long story short

An aiohttp client request on 'http://east.vc/' returns an empty string. Sporadically, it will throw a ClientPayloadError, but this behavior is inconsistent. requests library and curl requests on ' http://east.vc/' work fine.

Expected behaviour

Expect the body of the response to be returned.

Actual behaviour

An empty string is returned

Steps to reproduce

Simply run:

import aiohttp
import asyncio

async def fetch(session, url):
    async with session.get(url) as response:
        return await response.text()

async def main():
    async with aiohttp.ClientSession() as session:
        html = await fetch(session, 'http://east.vc')
        print(html)

loop = asyncio.get_event_loop()
loop.run_until_complete(main())

Your environment

OS X 10.11.6 Python 3.6.1 aiohttp (2.2.3) asyncio (3.4.3)

asvetlov commented 7 years ago

What is exception message text?

asvetlov commented 7 years ago

BTW how did you get 3.4.3 asyncio on Python 3.6.1? The library is shipped as part of python batteries and the version should be 3.6.1 as well.

mkapuza commented 7 years ago

There is not typically an exception, but sometimes it will throw a TimeoutError and ClientConnectorError, which is normal enough. I have also gottenaiohttp.client_exceptions.ClientPayloadError: Response payload is not completed and when this error happens (which is rare), and you are reading in chunks it will read in about half the body content and then throw the ClientPayloadError

I am wary of pinging the server too many times. But the main issue is if you run curl east.vc you get a response body no problem. But if you run the above script with aiohttp, it returns an empty body.

alexmnazarenko commented 7 years ago

Just as +1 - I've run this test too (ubuntu 16.04, py 3.6, aiohttp 2.2.3).

No exceptions, just empty body. Site itself doesn't look too special. Trivial ideas like using 'real browser user agent' didn't help.

Same result with uvloop.

nesdis commented 7 years ago

This is a genuine problem. aiohttp throws ClientPayloadError: Response payload is not completed for no reason and this requires re-establishing the connection with the server.

This issue is more easily reproducible in for a streaming connection

fafhrd91 commented 7 years ago

@mkapuza seem server is completely broken

  1. it returns broken "content-encoding: gzip", aiohttp can not decode it. you can remove default "accept-encoding" header.
  2. server also sets size of first chunk to "60d" which is not valid hex value.

@asvetlov we should add api for raw responsestream.

@nesdis "no reason" is not very appropriate in this situation. there is no "no reason" exceptions in aiohttp framework. exception has specific text which indicates the problem.

fafhrd91 commented 7 years ago

I do not see actionable in this issue.

nesdis commented 7 years ago

@fafhrd91 The exception is very much a part of aiohttp Please try searching a bit b4 making such statements.

ClientPayloadError('Response payload is not completed'))

line 77 client_proto.py

fafhrd91 commented 7 years ago

I wrote this code. And I don't see any "no reason" here

asvetlov commented 7 years ago

aiohttp behavior is correct. The only think we could do is upgrading exception text. Maybe Response payload is not completed, server return malformed HTTP response sounds less confusing?

mkapuza commented 7 years ago

@asvetlov @fafhrd91 do you get a ClientPayloadError every time the response body is returned? My issue is that most times I just get a blank response body, which would indicate that the site has no body, rather than a corrupted response.

fafhrd91 commented 7 years ago

This is something related to http_parser, it does not raise exception. Python parser does raise exception.

Findus23 commented 6 years ago

Hi,

I am having an really similar error with https://www.soeren-hentzschel.at/feed/.

Even though I get a 200, the content is empty.

Curl is able to fetch the URL without an issue.

Reproduce: https://gist.github.com/Findus23/3aaedbac0dd2520a9b65d0c9a6431b22

asvetlov commented 6 years ago

@Findus23 acually your bug is #2277

dnp1 commented 6 years ago

Same problem here.

using curl or firefox the url return a body

However, using aiohttp, the request ends with 200 and the body is empty

asvetlov commented 6 years ago

@dnp1 please provide more info

luvvien commented 5 years ago

response payload is not completed solved

zumby commented 4 years ago

Im also having a strange issue while trying to use aiohttp/asyncio with Artifactory REST API.

The strange thing is that the below code works perfectly for 'url_2' but permanently fails with aiohttp.client_exceptions.ClientPayloadError: Response payload is not completed for 'url_1'. As you can see, there is absolutely no difference between these URLs.

import aiohttp
import asyncio

user_name = 'username'
user_password = 'password'

url_1 = 'https://someorg.jfrog.io/someorg/api/storage/repo/folder-xxx' # fails
url_2 = 'https://someorg.jfrog.io/someorg/api/storage/repo/folder-yyy' # works

async def fetch(url, user_name, user_password):
    async with aiohttp.ClientSession(auth=aiohttp.BasicAuth(user_name, user_password)) as session:
        remote_resp = await session.request("GET", url)
        return await remote_resp.json()

r = asyncio.run(fetch(url_1, user_name, user_password))
print(r)

I am thinking that this has something to do with chunks, as they state it here: https://docs.aiohttp.org/en/stable/client_reference.html#aiohttp.ClientPayloadError

class aiohttp.ClientPayloadError This exception can only be raised while reading the response payload if one of these errors occurs:

  • invalid compression
  • malformed chunked encoding
  • not enough data that satisfy Content-Length HTTP header.

Literally stuck and have no ideas :( @aio-libs-bot

QualityRobD commented 4 years ago

class aiohttp.ClientPayloadError This exception can only be raised while reading the response payload if one of these errors occurs:

  • invalid compression
  • malformed chunked encoding
  • not enough data that satisfy Content-Length HTTP header.

Literally stuck and have no ideas :( @aio-libs-bot

I am having a similar issue. My code is calling github API pull requests, I get about 97 calls in and then it hangs with

Response payload is not completed

The url is valid, I'm able to plug it directly into chrome or postman and view the content with no issue.

I've spent hours and hours on this and haven't come up with a solution. Python 3.8.4

edit: the solved link does not resolve.

iann838 commented 4 years ago

Here is my 2 cent, I am doing 80k request from an API that returns the same header every request, and 0.001% of them will fail with ClientPayloadError Response payload is not completed, sometimes the entire loop hangs for at least 2 to 5 minutes before raising this exception, which adds up a delay to the rest of the requests to about 2 hours to finish.

The header is exactly the same for each request:

{
    "Access-Control-Allow-Credentials": "true",
    "Access-Control-Allow-Headers": "Content-Type,Authorization,Region,Cookie",
    "Access-Control-Allow-Methods": "GET,POST,OPTIONS",
    "CF-Cache-Status": "DYNAMIC",
    "CF-RAY": "5d33a5d62d6eed3b-SJC",
    "cf-request-id": "053425f9dd0000ed3b01a25200000001",
    "Content-Encoding": "gzip",
    "Content-Type": "application/json;charset=utf-8",
    "Date": "Tue, 15 Sep 2020 16:15:40 GMT, Tue, 15 Sep 2020 16:15:40 GMT",
    "Expect-CT": "max-age=604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\"",
    "X-App-Rate-Limit": "20:1,100:120",
    "X-App-Rate-Limit-Count": "1:1,1:120",
    "X-Method-Rate-Limit": "500:10",
    "X-Method-Rate-Limit-Count": "1:10",
    "X-Riot-Edge-Trace-Id": "baf7396f-88a6-4dfc-994b-18542036bb24",
    "transfer-encoding": "chunked",
    "Connection": "keep-alive"
}

The exception is NOT raised randomly, it just raises on the same request every time. With request or curl it is parsed as expected.

webknjaz commented 7 months ago

Hey everyone, I just released v3.9.4rc0. It'll hopefully help us get more complete tracebacks and that in turn, will let us know the underlying causes for this exception being raised — there may be several distinct behaviors underneath and we need to discover what they are.

If you have ability to do so, please try out this pre-release in environments where you can reproduce your problems and come back with the logs with complete tracebacks. Let's figure this out together!