Skip to content

Sending a file-like data payload prevents connection reuse #10325

@Tjstretchalot

Description

@Tjstretchalot

Describe the bug

If using aiohttp to send a 0-byte payload (as if via io.BytesIO(b'')) to get a very small response, the connection will be incorrectly closed when it could be reused

from adding prints directly to aiohttp to figure out why the connections were not being reused, I confirmed it still initializes write_bytes, but _cleanup_writer is called by payload.on_eof during ClientResponse#start, which leads to the writer being cancelled

when asyncio.CancelledError is raised in write_bytes, conn.close() is called with a comment noting that the body hasn't been fully sent so the connection can't be reused, but in this case that's incorrect - there was nothing to send in the first place!

This same sequence of events happens even if the payload is not empty, though it's not as self-evident that the comment is incorrect

To Reproduce

https://github.com/Tjstretchalot/aiohttp-reuse/blob/main/src/main.py

Expected behavior

I would expect aiohttp to reuse the connection whenever possible, regardless if passed a bytes object or a file-like object

Logs/tracebacks

======== Running on http://0.0.0.0:3003 ========
(Press CTRL+C to quit)
Traceback (most recent call last):
  File "src/main.py", line 43, in <module>
    asyncio.run(main())
  File "Python311\Lib\asyncio\runners.py", line 190, in run
    return runner.run(main)
           ^^^^^^^^^^^^^^^^
  File "Python311\Lib\asyncio\runners.py", line 118, in run
    return self._loop.run_until_complete(task)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "Python311\Lib\asyncio\base_events.py", line 653, in run_until_complete
    return future.result()
           ^^^^^^^^^^^^^^^
  File "src\main.py", line 35, in main
    len(session._connector._conns) == 1  # fails here
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError: defaultdict(<class 'collections.deque'>, {})

Python Version

$ python --version
Python 3.11.1

aiohttp Version

$ python -m pip show aiohttp
Version: 3.11.11

multidict Version

$ python -m pip show multidict
Version: 6.1.0

propcache Version

$ python -m pip show propcache
Version: 0.2.1

yarl Version

$ python -m pip show yarl
Version: 1.18.3

OS

Windows 10

Related component

Client

Additional context

No response

Code of Conduct

  • I agree to follow the aio-libs Code of Conduct

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugreproducer: presentThis PR or issue contains code, which reproduce the problem described or clearly understandable STR

    Type

    No type

    Projects

    Status

    Done

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions