Streaming¶
OxideHTTP supports streaming HTTP response bodies through OxideHTTP.stream().
Unlike regular requests, streaming does not load the entire response body into memory. Instead, it yields raw byte chunks as they are received.
Basic usage¶
Use stream() as an asynchronous context manager:
import asyncio
from oxidehttp import OxideHTTP
async def main() -> None:
async with OxideHTTP() as client:
async with client.stream(
'GET', 'https://example.com/large-file'
) as chunks:
async for chunk in chunks:
print(f'Received {len(chunk)} bytes')
asyncio.run(main())
The stream is kept open for the duration of the context manager. Exiting the context closes the underlying streamed response.
Saving a streamed response¶
You can write chunks directly to a file without buffering the entire response:
import asyncio
from oxidehttp import OxideHTTP
async def download() -> None:
async with OxideHTTP() as client:
async with client.stream(
'GET', 'https://example.com/large-file'
) as chunks:
with open('download.bin', 'wb') as file:
async for chunk in chunks:
file.write(chunk)
asyncio.run(download())
Each yielded chunk is a bytes object.
Request options¶
stream() accepts the following arguments:
| Argument | Description |
|---|---|
method |
HTTP method to use. |
url |
Request URL or path. |
params |
Optional query parameters. |
headers |
Optional request headers. |
json |
Optional JSON request body. |
body_text |
Optional text request body. |
body_bytes |
Optional binary request body. |
form |
Optional form-encoded request body. |
buffer_limit |
Maximum size of the underlying streamed-read buffer. Defaults to 100. |
middlewares |
Optional request-specific middleware. |
extensions |
Optional request extensions. |
The HTTP method is positional, while the remaining request options are keyword-only.
Buffer limit¶
The buffer_limit argument controls the underlying streamed-read buffer:
async with client.stream(
'GET', 'https://example.com/large-file', buffer_limit=256
) as chunks:
async for chunk in chunks:
process_chunk(chunk)
The default value is 100.
Streaming with query parameters¶
Query parameters work the same way as regular requests:
async with client.stream(
'GET',
'https://example.com/events',
params={'limit': 100, 'include_metadata': True},
) as chunks:
async for chunk in chunks:
process_chunk(chunk)
See Requests for query parameter serialization.
Streaming request bodies¶
Streaming supports the same request body representations as the request builder:
async with client.stream(
'POST', 'https://example.com/upload', json={'name': 'example'}
) as chunks:
async for chunk in chunks:
process_chunk(chunk)
When multiple body arguments are supplied, the first non-None representation takes precedence in this order:
jsonbody_textbody_bytesform
Middleware and extensions¶
You can pass middleware and request extensions directly:
async with client.stream(
'GET',
'https://example.com/large-file',
middlewares=[my_middleware],
extensions={'my_extension': 'value'},
) as chunks:
async for chunk in chunks:
process_chunk(chunk)
Client-level middleware configured through OxideHTTPConfig.request.middlewares also applies.
Error handling¶
Errors raised by the underlying HTTP client are translated into OxideHTTP exceptions.
Cancellation is propagated as asyncio.CancelledError, allowing normal asyncio cancellation handling:
import asyncio
from oxidehttp import OxideHTTP
from oxidehttp.exceptions import OxideHTTPError
async def download() -> None:
async with OxideHTTP() as client:
try:
async with client.stream(
'GET', 'https://example.com/large-file'
) as chunks:
async for chunk in chunks:
process_chunk(chunk)
except asyncio.CancelledError:
raise
except OxideHTTPError as exc:
print(f'Streaming failed: {exc}')
raise
The streamed response is closed when the context manager exits, including when an exception occurs.
API reference¶
See OxideHTTP.stream() for the complete method signature.