Skip to content

Commit 7fb9e95

Browse files
committed
docs: add docs for Advanced Usage, e.g modifying request/response
1 parent c7cec23 commit 7fb9e95

File tree

4 files changed

+124
-19
lines changed

4 files changed

+124
-19
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ Source Code: <https://github.com/WSH032/fastapi-proxy-lib/>
3333
- [x] **Transparently** and **losslessly** handle all proxy requests,
3434
Including **HTTP headers**, **cookies**, **query parameters**, **body**, etc.
3535
- [x] Asynchronous streaming transfer, support **file proxy**.
36+
- [x] `fastapi-proxy-lib` value [privacy security](https://wsh032.github.io/fastapi-proxy-lib/Usage/Security/).
3637

3738
### other features
3839

@@ -50,6 +51,8 @@ Source Code: <https://github.com/WSH032/fastapi-proxy-lib/>
5051

5152
So, it perfectly supports all features of [httpx.AsyncClient](https://www.python-httpx.org/advanced/#client-instances), you can even use your custom `AsyncClient`, [`Transport`](https://www.python-httpx.org/advanced/#custom-transports).
5253

54+
See [Advanced Usage](https://wsh032.github.io/fastapi-proxy-lib/Usage/Advanced/) for more details.
55+
5356
> except `cookies` and `base_url` arguments, which are taken over by `fastapi-proxy-lib`
5457
5558
## Installation

docs/Usage/Advanced-and-Starlette.md

Lines changed: 0 additions & 18 deletions
This file was deleted.

docs/Usage/Advanced.md

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
# Advanced
2+
3+
For the following scenarios, you might prefer [fastapi_proxy_lib.core][]:
4+
5+
- When you need to use proxies with **only** `Starlette` dependencies (without `FastAPI`).
6+
- When you need more fine-grained control over parameters and lifespan event.
7+
- When you need to further process the input and output before and after the proxy (similar to middleware).
8+
9+
We will demonstrate with `FastAPI`,
10+
but you can completely switch to the `Starlette` approach,
11+
which is officially supported by this project.
12+
13+
## Starlette Support
14+
15+
**^^[Please visit the `ReverseHttpProxy#examples` to view the demo with annotations :material-file-document: ][fastapi_proxy_lib.core.http.ReverseHttpProxy--examples]^^**.
16+
17+
Also (without annotations):
18+
19+
- [`ForwardHttpProxy#examples`][fastapi_proxy_lib.core.http.ForwardHttpProxy--examples]
20+
- [`ReverseWebSocketProxy#examples`][fastapi_proxy_lib.core.websocket.ReverseWebSocketProxy--examples]
21+
22+
## Modify request
23+
24+
In some cases, you may want to make final modifications before sending a request, such as performing behind-the-scenes authentication by modifying the headers of request.
25+
26+
`httpx` provides comprehensive authentication support, and `fastapi-proxy-lib` offers first-class support for `httpx`.
27+
28+
See <https://www.python-httpx.org/advanced/#customizing-authentication>
29+
30+
You can refer following example to implement a simple authentication:
31+
32+
```python
33+
import httpx
34+
from fastapi_proxy_lib.fastapi.app import reverse_http_app
35+
36+
37+
class MyCustomAuth(httpx.Auth):
38+
# ref: https://www.python-httpx.org/advanced/#customizing-authentication
39+
40+
def __init__(self, token: str):
41+
self.token = token
42+
43+
def auth_flow(self, request: httpx.Request):
44+
# Send the request, with a custom `X-Authentication` header.
45+
request.headers["X-Authentication"] = self.token
46+
yield request
47+
48+
49+
app = reverse_http_app(
50+
client=httpx.AsyncClient(auth=MyCustomAuth("bearer_token")),
51+
base_url="http://www.httpbin.org/",
52+
)
53+
54+
```
55+
56+
visit `/headers` to see the result which contains `"X-Authentication": "bearer_token"` header.
57+
58+
## Modify response
59+
60+
In some cases, you may want to make final modifications before return the response to the client, such as transcoding video response streams.
61+
62+
See [issue#15](https://github.com/WSH032/fastapi-proxy-lib/issues/15)
63+
64+
You can refer following example to modify the response:
65+
66+
```python
67+
from contextlib import asynccontextmanager
68+
from typing import AsyncIterable, AsyncIterator, Union
69+
70+
from fastapi import FastAPI
71+
from fastapi_proxy_lib.core.http import ReverseHttpProxy
72+
from starlette.requests import Request
73+
from starlette.responses import StreamingResponse
74+
75+
AsyncContentStream = AsyncIterable[Union[str, bytes]]
76+
77+
78+
proxy = ReverseHttpProxy(base_url="http://www.example.com/")
79+
80+
81+
@asynccontextmanager
82+
async def close_proxy_event(_: FastAPI) -> AsyncIterator[None]:
83+
"""Close proxy."""
84+
yield
85+
await proxy.aclose()
86+
87+
88+
app = FastAPI(lifespan=close_proxy_event)
89+
90+
91+
async def new_content(origin_content: AsyncContentStream) -> AsyncContentStream:
92+
"""Fake content processing."""
93+
async for chunk in origin_content:
94+
# do some processing with chunk, e.g transcoding,
95+
# here we just print and return it as an example.
96+
print(chunk)
97+
yield chunk
98+
99+
100+
@app.get("/{path:path}")
101+
async def _(request: Request, path: str = ""):
102+
proxy_response = await proxy.proxy(request=request, path=path)
103+
104+
if isinstance(proxy_response, StreamingResponse):
105+
# get the origin content stream
106+
old_content = proxy_response.body_iterator
107+
108+
new_resp = StreamingResponse(
109+
content=new_content(old_content),
110+
status_code=proxy_response.status_code,
111+
headers=proxy_response.headers,
112+
media_type=proxy_response.media_type,
113+
)
114+
return new_resp
115+
116+
return proxy_response
117+
118+
```
119+
120+
visit `/`, you will notice that the response body is printed to the console.

mkdocs.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ nav:
143143
- Usage:
144144
- Usage/index.md
145145
- Usage/FastAPI-Helper.md
146-
- Usage/Advanced-and-Starlette.md
146+
- Usage/Advanced.md
147147
- Usage/Security.md
148148
- API Reference: reference/
149149
- CONTRIBUTING:

0 commit comments

Comments
 (0)