Write the request body to the connection stream. This method handles writing different types of request bodies: 1. Payload objects (using their specialized write_with_length method) 2. Bytes/bytearray objects 3. Iterable body content Args:
(
self,
writer: AbstractStreamWriter,
conn: "Connection",
content_length: int | None = None,
)
| 1346 | self.proxy_headers = proxy_headers |
| 1347 | |
| 1348 | async def write_bytes( |
| 1349 | self, |
| 1350 | writer: AbstractStreamWriter, |
| 1351 | conn: "Connection", |
| 1352 | content_length: int | None = None, |
| 1353 | ) -> None: |
| 1354 | """ |
| 1355 | Write the request body to the connection stream. |
| 1356 | |
| 1357 | This method handles writing different types of request bodies: |
| 1358 | 1. Payload objects (using their specialized write_with_length method) |
| 1359 | 2. Bytes/bytearray objects |
| 1360 | 3. Iterable body content |
| 1361 | |
| 1362 | Args: |
| 1363 | writer: The stream writer to write the body to |
| 1364 | conn: The connection being used for this request |
| 1365 | content_length: Optional maximum number of bytes to write from the body |
| 1366 | (None means write the entire body) |
| 1367 | |
| 1368 | The method properly handles: |
| 1369 | - Waiting for 100-Continue responses if required |
| 1370 | - Content length constraints for chunked encoding |
| 1371 | - Error handling for network issues, cancellation, and other exceptions |
| 1372 | - Signaling EOF and timeout management |
| 1373 | |
| 1374 | Raises: |
| 1375 | ClientOSError: When there's an OS-level error writing the body |
| 1376 | ClientConnectionError: When there's a general connection error |
| 1377 | asyncio.CancelledError: When the operation is cancelled |
| 1378 | |
| 1379 | """ |
| 1380 | # 100 response |
| 1381 | if self._continue is not None: |
| 1382 | # Force headers to be sent before waiting for 100-continue |
| 1383 | writer.send_headers() |
| 1384 | await writer.drain() |
| 1385 | await self._continue |
| 1386 | |
| 1387 | protocol = conn.protocol |
| 1388 | assert protocol is not None |
| 1389 | try: |
| 1390 | # This should be a rare case but the |
| 1391 | # self._body can be set to None while |
| 1392 | # the task is being started or we wait above |
| 1393 | # for the 100-continue response. |
| 1394 | # The more likely case is we have an empty |
| 1395 | # payload, but 100-continue is still expected. |
| 1396 | if self._body is not None: |
| 1397 | await self._body.write_with_length(writer, content_length) |
| 1398 | except OSError as underlying_exc: |
| 1399 | reraised_exc = underlying_exc |
| 1400 | |
| 1401 | # Distinguish between timeout and other OS errors for better error reporting |
| 1402 | exc_is_not_timeout = underlying_exc.errno is not None or not isinstance( |
| 1403 | underlying_exc, asyncio.TimeoutError |
| 1404 | ) |
| 1405 | if exc_is_not_timeout: |