-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- add `Usage` document - improve `README.md` - adjust the source code docs in `src/`.
- Loading branch information
Showing
10 changed files
with
466 additions
and
135 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,121 @@ | ||
Documentation is coming, please use [API Reference](https://WSH032.github.io/fastapi-proxy-lib/) first. :smile: | ||
# FastAPI Proxy Lib | ||
|
||
<p align="center"> | ||
<em>HTTP/WebSocket proxy for starlette/FastAPI</em> | ||
</p> | ||
|
||
| | | | ||
| ------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | | ||
| CI/CD | [![CI: lint-test]][CI: lint-test#link] [![CI: docs]][CI: docs#link] | | ||
| Code | [![codecov]][codecov#link] [![Code style: black]][Code style: black#link] [![Ruff]][Ruff#link] [![Checked with pyright]][Checked with pyright#link] | | ||
| Package | [![Python-Version]][Python-Version#link] | | ||
| Meta | [![Hatch project]][Hatch project#link] [![GitHub License]][GitHub License#link] | | ||
|
||
--- | ||
|
||
Documentation: <https://wsh032.github.io/fastapi-proxy-lib/> | ||
|
||
Source Code: <https://github.com/WSH032/fastapi-proxy-lib/> | ||
|
||
--- | ||
|
||
## Features | ||
|
||
- [X] **Out of the box !** [Helper functions](#quick-start) to get FastAPI `app`/`router` for proxy conveniently. | ||
- [x] **Only `Starlette` is required** for it to work ([`FastAPI` is optional](#installation)). | ||
- [x] Support both **HTTP** and **WebSocket** proxy. | ||
- [x] Supports all HTTP methods (`GET`, `POST`, etc.) | ||
- [x] Support both **reverse** proxy and **forward** proxy. | ||
- [x] **Transparently** and **losslessly** handle all proxy requests, | ||
- [x] Asynchronous streaming transfer, support **file proxy**. | ||
|
||
### other features | ||
|
||
- [x] Strict linting and strict-mode Pyright type checking. | ||
- [x] **100%** [Type Completeness](https://microsoft.github.io/pyright/#/typed-libraries?id=type-completeness), [Code coverage of **over 95%**][codecov#link]. | ||
- [x] Forced keep-alive connections, minimizing proxy latency. | ||
- [x] Handle errors as gracefully as possible. | ||
|
||
### `FastAPI Proxy Lib` stands on the shoulders of giants | ||
|
||
- [httpx](https://github.com/encode/httpx) for HTTP proxy | ||
- [httpx-ws](https://github.com/frankie567/httpx-ws) for WebSocket proxy | ||
|
||
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). | ||
|
||
## Installation | ||
|
||
> !!! note | ||
> | ||
> We follow semantic versioning.<br> | ||
> This is a young project, and before 1.0.0, there may be changes in the API (though we try to avoid that).<br> | ||
> We recommend pinning to any minor versions, such as 0.1.x. | ||
Pypi will come soon, please install from github temporarily: | ||
|
||
```shell | ||
pip install fastapi-proxy-lib[standard]@git+https://github.com/WSH032/fastapi-proxy-lib.git | ||
``` | ||
|
||
Perhaps you've noticed that we're installing `fastapi-proxy-lib[standard]` instead of `fastapi-proxy-lib`. The difference is: | ||
|
||
- The former will install `FastAPI` at the same time. | ||
- The latter installs only the basic dependencies for `fastapi-proxy-lib`. | ||
|
||
If you **only need to use this library with Starlette**, you only need to install the latter. | ||
|
||
## Quick start | ||
|
||
With the helper functions, get the FastAPI proxy server app is very convenient and out of the box: | ||
|
||
```python | ||
from fastapi_proxy_lib.fastapi.app import reverse_http_app | ||
|
||
app = reverse_http_app(base_url="http://www.example.com/foo/") | ||
``` | ||
|
||
That's all! Now, you can launch the proxy server with `uvicorn`: | ||
|
||
```shell | ||
uvicorn main:app --host 127.0.0.1 --port 8000 | ||
``` | ||
|
||
Then, visit `http://127.0.0.1:8000/bar?baz=1`, you will get the response from `http://www.example.com/foo/bar?baz=1`. | ||
|
||
For support with `FastAPI router` or only using `Starlette`, please **visit to our [documentation 📚](https://wsh032.github.io/fastapi-proxy-lib/) for more details**. | ||
|
||
## development | ||
|
||
- If you find any issues, please don't hesitate to [open an issue](https://github.com/WSH032/fastapi-proxy-lib/issues). | ||
- If you need assistance, feel free to [start a discussion](https://github.com/WSH032/fastapi-proxy-lib/discussions). | ||
- [Welcome PR](https://github.com/WSH032/fastapi-proxy-lib/pulls) | ||
|
||
English is not the native language of the author (me), so if you find any areas for improvement in the documentation, your feedback is welcome. | ||
|
||
If you think this project helpful, consider giving it a star ![GitHub Repo stars](https://img.shields.io/github/stars/wsh032/fastapi-proxy-lib?style=social) | ||
, which makes me happy. :smile: | ||
|
||
## License | ||
|
||
This project is licensed under the terms of the *Apache License 2.0*. | ||
|
||
<!-- link --> | ||
|
||
[CI: lint-test]: https://github.com/WSH032/fastapi-proxy-lib/actions/workflows/lint-test.yml/badge.svg?branch=main | ||
[CI: lint-test#link]: https://github.com/WSH032/fastapi-proxy-lib/actions/workflows/lint-test.yml | ||
[CI: docs]: https://github.com/WSH032/fastapi-proxy-lib/actions/workflows/docs.yml/badge.svg?branch=main | ||
[CI: docs#link]: https://github.com/WSH032/fastapi-proxy-lib/actions/workflows/docs.yml | ||
[Python-Version]: https://img.shields.io/python/required-version-toml?tomlFilePath=https%3A%2F%2Fraw.githubusercontent.com%2FWSH032%2Ffastapi-proxy%2Fmain%2Fpyproject.toml&logo=python&logoColor=gold&label=Python | ||
[Python-Version#link]: https://github.com/WSH032/fastapi-proxy-lib/blob/main/pyproject.toml | ||
[Code style: black]: https://img.shields.io/badge/code%20style-black-000000.svg | ||
[Code style: black#link]: https://github.com/psf/black | ||
[GitHub License]: https://img.shields.io/github/license/WSH032/fastapi-proxy-lib?color=9400d3 | ||
[GitHub License#link]: https://github.com/WSH032/fastapi-proxy-lib/blob/main/LICENSE | ||
[Ruff]: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json | ||
[Ruff#link]: https://github.com/astral-sh/ruff | ||
[Checked with pyright]: https://microsoft.github.io/pyright/img/pyright_badge.svg | ||
[Checked with pyright#link]: https://microsoft.github.io/pyright | ||
[Hatch project]: https://img.shields.io/badge/%F0%9F%A5%9A-Hatch-4051b5.svg | ||
[Hatch project#link]: https://github.com/pypa/hatch | ||
[codecov]: https://codecov.io/gh/WSH032/fastapi-proxy-lib/graph/badge.svg?token=62QQU06E8X | ||
[codecov#link]: https://codecov.io/gh/WSH032/fastapi-proxy-lib |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# Advanced and Starlette | ||
|
||
For the following scenarios, you might prefer [fastapi_proxy_lib.core][]: | ||
|
||
- When you need to use proxies with **only** `Starlette` dependencies (without `FastAPI`). | ||
- When you need more fine-grained control over parameters and lifespan event. | ||
- When you need to further process the input and output before and after the proxy (similar to middleware). | ||
|
||
We will demonstrate with `FastAPI`, | ||
but you can completely switch to the `Starlette` approach, | ||
which is officially supported by this project. | ||
|
||
**^^[Please visit the `ReverseHttpProxy#examples` to view the demo with annotations :material-file-document: ][fastapi_proxy_lib.core.http.ReverseHttpProxy--examples]^^**. | ||
|
||
Also (without annotations): | ||
|
||
- [`ForwardHttpProxy#examples`][fastapi_proxy_lib.core.http.ForwardHttpProxy--examples] | ||
- [`ReverseWebSocketProxy#examples`][fastapi_proxy_lib.core.websocket.ReverseWebSocketProxy--examples] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
# FastAPI Helper | ||
|
||
!!!note | ||
FastAPI Helper Module need `FastAPI` installed. | ||
|
||
There are two helper modules to get FastAPI `app`/`router` for proxy conveniently. | ||
|
||
- [fastapi_proxy_lib.fastapi.app][]: High-level | ||
- [fastapi_proxy_lib.fastapi.router][]: Low-level | ||
|
||
## app | ||
|
||
use `fastapi_proxy_lib.fastapi.app` is very convenient and out of the box, there are three helper functions: | ||
|
||
- [forward_http_app][fastapi_proxy_lib.fastapi.app.forward_http_app] | ||
- [reverse_http_app][fastapi_proxy_lib.fastapi.app.reverse_http_app] | ||
- [reverse_ws_app][fastapi_proxy_lib.fastapi.app.reverse_ws_app] | ||
|
||
Example: | ||
|
||
```python | ||
from fastapi_proxy_lib.fastapi.app import reverse_http_app | ||
from httpx import AsyncClient | ||
|
||
client = AsyncClient() # (1)! | ||
base_url = "http://www.example.com/" # (2)! | ||
|
||
app = reverse_http_app(client=client, base_url=base_url) | ||
``` | ||
|
||
1. You can pass `httpx.AsyncClient` instance: | ||
- if you want to customize the arguments, e.g. `httpx.AsyncClient(proxies={})` | ||
- if you want to reuse the connection pool of `httpx.AsyncClient` | ||
--- | ||
Or you can pass `None`(The default value), then `fastapi-proxy-lib` will create a new `httpx.AsyncClient` instance for you. | ||
2. !!! note | ||
The `base_url` must end with `/`! | ||
|
||
For other app helpers, please refer to their API references. | ||
|
||
## router | ||
|
||
For the following scenarios, you might prefer [fastapi_proxy_lib.fastapi.router][]: | ||
|
||
- When you need to adjust the `app`/`router` parameters. | ||
- When you need to [mount the proxy on a route of larger app](https://fastapi.tiangolo.com/tutorial/bigger-applications/). | ||
|
||
**^^[Please refer to the documentation of `RouterHelper` for more information :material-file-document: ][fastapi_proxy_lib.fastapi.router.RouterHelper--examples]^^**. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
# Security | ||
|
||
## proxy requests filter in forward proxy | ||
|
||
Forward proxy allows access to any URL on input, which can be **scary** 😫 if not restricted. | ||
|
||
For example, through `http://www.my-proxy-server.com/http://127.0.0.1:8000`, | ||
an attacker can access the server's local network. | ||
|
||
So, there is a `proxy_filter` argument in [`ForwardHttpProxy`][fastapi_proxy_lib.core.http.ForwardHttpProxy.__init__] to filter requests. | ||
|
||
If you do not explicitly specify it, `ForwardHttpProxy` will issue a warning and specify a [default_proxy_filter][fastapi_proxy_lib.core.tool.default_proxy_filter]. | ||
|
||
- If you want to accept all proxy requests (**never do this on a public server**), you can do it like this: | ||
|
||
```python | ||
proxy_filter = lambda _: None | ||
``` | ||
|
||
- If you want to implement your own proxy filter, please refer to the [fastapi_proxy_lib.core.tool.ProxyFilterProto][]. | ||
|
||
## `http` vs `https` | ||
|
||
!!! danger | ||
**Never use a server with the HTTPS protocol to proxy a target server (`base_url`) with the HTTP protocol !** | ||
|
||
e.g. `https://www.my-proxy-server.com/http://www.example.com/` | ||
|
||
There is a security issue: | ||
|
||
Browsers may send sensitive HTTPS information to your HTTPS proxy server, | ||
then because of transparency feature, `fastapi-proxy-lib` will forward | ||
these information to the target server using the HTTP protocol without modification, | ||
which may cause privacy leaks. | ||
|
||
!!! failure | ||
If you reverse it. Use an HTTP server to proxy an HTTPS target server. | ||
|
||
There is a high probability that the request will fail. | ||
|
||
## The same-origin policy of `ForwardHttpProxy` | ||
|
||
The `ForwardHttpProxy` server uses the same source to proxy different target servers. e.g: | ||
|
||
> http://www.my-proxy-server.com/http://www.example.com/<br> | ||
> http://www.my-proxy-server.com/http://www.google.com/ | ||
> | ||
> both source are `http://www.my-proxy-server.com/` | ||
|
||
For this situation, the browser's same-origin protection policy will fail, | ||
and cookies from `http://www.example.com/` will be sent to` http://www.google.com/`. | ||
|
||
You should inform the user of this situation and let them decide whether to continue. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# Introduction | ||
|
||
We provide two types of proxies: | ||
|
||
- reverse proxy: | ||
- [ReverseHttpProxy][fastapi_proxy_lib.core.http.ReverseHttpProxy] | ||
- [ReverseWebSocketProxy][fastapi_proxy_lib.core.websocket.ReverseWebSocketProxy] | ||
- forward proxy: | ||
- [ForwardHttpProxy][fastapi_proxy_lib.core.http.ForwardHttpProxy] | ||
|
||
## What is a reverse proxy? | ||
|
||
A reverse proxy is similar to a gateway. | ||
|
||
All reverse proxies have a `base_url` parameter, which transparently forwards all requests sent to the proxy server to the target server specified by `base_url`. | ||
|
||
For example, if you set `base_url` to `http://www.example.com/foo/`, and the proxy server launches at `http://127.0.0.1:8000`. | ||
|
||
Then all requests sent to the proxy server will be forwarded to `http://www.example.com/foo/`, including `path-params`, `query-params`, `headers`, `cookies`, etc. | ||
|
||
Visit `http//127.0.0.1:8000/bar?baz=1`, will get the response from `http://www.example.com/foo/bar?baz=1`. | ||
|
||
## What is a forward proxy? | ||
|
||
A forward proxy is very similar to a reverse proxy, except that the forward proxy server uses the full `path` of the requests it receives as the `base_url`. | ||
|
||
For example, visit `http//127.0.0.1:8000/http://www.example.com/foo/bar?baz=1`, will get the response from `http://www.example.com/foo/bar?baz=1`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.