Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 29 additions & 1 deletion docs/async.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,35 @@ The async response streaming methods are:
* `Response.aiter_text()` - For streaming the response content as text.
* `Response.aiter_lines()` - For streaming the response content as lines of text.
* `Response.aiter_raw()` - For streaming the raw response bytes, without applying content decoding.
* `Response.aclose()` - For closing the response. You don't usually need this, since `.stream` block close the response automatically on exit.
* `Response.aclose()` - For closing the response. When using the context-managed syntax, `.stream()` will close the response automatically on exit.

If you need to return the body as an async iterator without block usage, you can manually enter the `.stream()` async context, and make sure it gets closed eventually. For example, if building a Starlette web view that returns a streaming response, this can be achieved using `AsyncExitStack` and a background task:

```python
from contextlib import AsyncExitStack
import httpx
from starlette.applications import Starlette
from starlette.routing import Route
from starlette.background import BackgroundTask
from starlette.responses import StreamingResponse

client = httpx.AsyncClient()

async def home(request):
data = await request.json()
url = data["url"]

exit_stack = AsyncExitStack()
r = await exit_stack.enter_async_context(client.stream("GET", url))

return StreamingResponse(
r.aiter_raw(),
media_type="application/octet-stream",
background=BackgroundTask(exit_stack.aclose),
)

app = Starlette(routes=[Route("/", home, methods=["POST"])])
```

### Streaming requests

Expand Down
4 changes: 3 additions & 1 deletion docs/compatibility.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ HTTPX provides a `.stream()` interface rather than using `stream=True`. This ens
For example:

```python
with request.stream("GET", "https://www.example.com") as response:
with httpx.stream("GET", "https://www.example.com") as response:
...
```

Expand All @@ -34,6 +34,8 @@ Within a `stream()` block request data is made available with:
* `.iter_raw()` - Use this instead of `response.raw`
* `.read()` - Read the entire response body, making `request.text` and `response.content` available.

For more information, see [Streaming Responses](/quickstart#streaming-responses).

## SSL configuration

When using a `Client` instance, the `trust_env`, `verify`, and `cert` arguments should always be passed on client instantiation, rather than passed to the request method.
Expand Down
21 changes: 21 additions & 0 deletions docs/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,27 @@ If you're using streaming responses in any of these ways then the `response.cont
... print(r.text)
```

If you need to return the body as an iterator without block usage, you can manually enter the `.stream()` context and make sure it gets closed eventually. For example, if building a Flask web view that returns a streaming response, this can be achieved using `ExitStack` and werkzeug's `ClosingIterator`:

```python
from contextlib import ExitStack
import httpx
from flask import Flask, Response, request
from werkzeug.wsgi import ClosingIterator

app = Flask(__name__)

@app.route("/", methods=["post"])
def home() -> Response:
url = request.json["url"]

exit_stack = ExitStack()
r = exit_stack.enter_context(httpx.stream("GET", url))
body = ClosingIterator(r.iter_raw(), callbacks=[exit_stack.close])

return Response(body, mimetype="application/octet-stream")
```

## Cookies

Any cookies that are set on the response can be easily accessed:
Expand Down