Skip to content

Commit e9cc3aa

Browse files
authored
Merge pull request #5 from mr-fatalyst/0.4.0-dev
0.4.0 dev
2 parents c6d7be4 + 4e8e6df commit e9cc3aa

File tree

121 files changed

+6006
-1279
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

121 files changed

+6006
-1279
lines changed

CHANGELOG.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,21 @@ All notable changes to FastOpenAPI are documented in this file.
44

55
FastOpenAPI follows the [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) format.
66

7+
## [0.4.0] - 2025-03-20
8+
9+
### Added
10+
- `ReDoc UI` and default URL (`host:port/redoc`)
11+
- `TornadoRouter` for integration with the `Tornado` framework
12+
13+
### Changed
14+
- Revised and updated all tests.
15+
16+
### Fixed
17+
- Status code for error response fixed: 422 -> 500
18+
19+
### Removed
20+
- Removed the `add_docs_route` and `add_openapi_route` from `BaseRouter`.
21+
722
## [0.3.1] - 2025-03-15
823

924
### Fixed

README.md

Lines changed: 64 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66
<b>FastOpenAPI</b> is a library for generating and integrating OpenAPI schemas using Pydantic and various frameworks.
77
</p>
88

9+
<p align="center">
10+
This project was inspired by <a href="https://fastapi.tiangolo.com/">FastAPI</a> and aims to provide a similar developer-friendly experience.
11+
</p>
12+
913
<p align="center">
1014
<img src="https://img.shields.io/github/license/mr-fatalyst/fastopenapi">
1115
<img src="https://github.com/mr-fatalyst/fastopenapi/actions/workflows/master.yml/badge.svg">
@@ -37,6 +41,9 @@ pip install fastopenapi[sanic]
3741
```bash
3842
pip install fastopenapi[starlette]
3943
```
44+
```bash
45+
pip install fastopenapi[tornado]
46+
```
4047

4148
---
4249

@@ -62,7 +69,7 @@ pip install fastopenapi[starlette]
6269
from fastopenapi.routers import FalconRouter
6370

6471
app = falcon.asgi.App()
65-
router = FalconRouter(app=app, docs_url="/docs/", openapi_version="3.0.0")
72+
router = FalconRouter(app=app)
6673

6774

6875
class HelloResponse(BaseModel):
@@ -80,7 +87,7 @@ pip install fastopenapi[starlette]
8087
```
8188
</details>
8289

83-
- ![Flask](https://img.shields.io/badge/-Flask-000000?style=flat&logo=flask&logoColor=white)
90+
- ![Flask](https://img.shields.io/badge/-Flask-EEEEEE?style=flat&logo=flask&logoColor=black)
8491
<details>
8592
<summary>Click to expand the Flask Example</summary>
8693

@@ -91,7 +98,7 @@ pip install fastopenapi[starlette]
9198
from fastopenapi.routers import FlaskRouter
9299

93100
app = Flask(__name__)
94-
router = FlaskRouter(app=app, docs_url="/docs/", openapi_version="3.0.0")
101+
router = FlaskRouter(app=app)
95102

96103

97104
class HelloResponse(BaseModel):
@@ -120,7 +127,7 @@ pip install fastopenapi[starlette]
120127
from fastopenapi.routers import QuartRouter
121128

122129
app = Quart(__name__)
123-
router = QuartRouter(app=app, docs_url="/docs/", openapi_version="3.0.0")
130+
router = QuartRouter(app=app)
124131

125132

126133
class HelloResponse(BaseModel):
@@ -149,7 +156,7 @@ pip install fastopenapi[starlette]
149156
from fastopenapi.routers import SanicRouter
150157

151158
app = Sanic("MySanicApp")
152-
router = SanicRouter(app=app, docs_url="/docs/", openapi_version="3.0.0")
159+
router = SanicRouter(app=app)
153160

154161

155162
class HelloResponse(BaseModel):
@@ -167,7 +174,7 @@ pip install fastopenapi[starlette]
167174
```
168175
</details>
169176

170-
- ![Starlette](https://img.shields.io/badge/-Starlette-4B0082?style=flat&logo=fastapi&logoColor=white)
177+
- ![Starlette](https://img.shields.io/badge/-Starlette-4B0082?style=flat&logo=python&logoColor=white)
171178
<details>
172179
<summary>Click to expand the Starlette Example</summary>
173180

@@ -179,7 +186,7 @@ pip install fastopenapi[starlette]
179186
from fastopenapi.routers import StarletteRouter
180187

181188
app = Starlette()
182-
router = StarletteRouter(app=app, docs_url="/docs/", openapi_version="3.0.0")
189+
router = StarletteRouter(app=app)
183190

184191

185192
class HelloResponse(BaseModel):
@@ -196,6 +203,43 @@ pip install fastopenapi[starlette]
196203
```
197204
</details>
198205

206+
- ![Tornado](https://img.shields.io/badge/-Tornado-2980B9?style=flat&logo=python&logoColor=white)
207+
<details>
208+
<summary>Click to expand the Tornado Example</summary>
209+
210+
```python
211+
import asyncio
212+
213+
from pydantic import BaseModel
214+
from tornado.web import Application
215+
216+
from fastopenapi.routers.tornado import TornadoRouter
217+
218+
app = Application()
219+
220+
router = TornadoRouter(app=app)
221+
222+
223+
class HelloResponse(BaseModel):
224+
message: str
225+
226+
227+
@router.get("/hello", tags=["Hello"], status_code=200, response_model=HelloResponse)
228+
def hello(name: str):
229+
"""Say hello from Tornado"""
230+
return HelloResponse(message=f"Hello, {name}! It's Tornado!")
231+
232+
233+
async def main():
234+
app.listen(8000)
235+
await asyncio.Event().wait()
236+
237+
238+
if __name__ == "__main__":
239+
asyncio.run(main())
240+
```
241+
</details>
242+
199243
### Step 2. Run the server
200244

201245
Launch the application:
@@ -206,16 +250,21 @@ python main.py
206250

207251
Once launched, the documentation will be available at:
208252

253+
Swagger UI:
254+
```
255+
http://127.0.0.1:8000/docs
209256
```
210-
http://127.0.0.1:8000/docs/
257+
ReDoc UI:
258+
```
259+
http://127.0.0.1:8000/redoc
211260
```
212261

213262
---
214263

215264
## ⚙️ Features
216265
- **Generate OpenAPI schemas** with Pydantic v2.
217266
- **Data validation** using Pydantic models.
218-
- **Supports multiple frameworks:** Falcon, Flask, Quart, Sanic, Starlette.
267+
- **Supports multiple frameworks:** Falcon, Flask, Quart, Sanic, Starlette, Tornado.
219268
- **Proxy routing provides FastAPI-style routing**
220269

221270
---
@@ -232,6 +281,12 @@ Examples of integration and detailed usage for each framework are available in t
232281

233282
---
234283

284+
## 📊 Quick & Dirty Benchmarks
285+
286+
Fast but not perfect benchmarks. Check the [`benchmarks`](https://github.com/mr-fatalyst/fastopenapi/tree/master/benchmarks) directory for details.
287+
288+
---
289+
235290
## ✅ Development Recommendations
236291

237292
- Use Pydantic models for strict typing and data validation.

benchmarks/README.md

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
## 📊 Quick & Dirty Benchmarks
2+
3+
This benchmark compares the performance of two API implementations:
4+
- **Original**: Uses standard routing with Pydantic validation.
5+
- **FastOpenAPI**: Uses proxy routing with Pydantic validation.
6+
7+
Each implementation runs in a separate instance, and the benchmark measures response times across multiple endpoints.
8+
9+
### 📈 Rough results
10+
- You can check rough results here:
11+
- [Falcon](falcon/FALCON.md)
12+
- [Flask](flask/FLASK.md)
13+
- [Quart](quart/QUART.md)
14+
- [Sanic](sanic/SANIC.md)
15+
- [Starlette](starlette/STARLETTE.md)
16+
- [Tornado](tornado/TORNADO.md)
17+
18+
### 📖 How It Works
19+
- The script runs **10,000 requests per endpoint**. You can set your own value.
20+
- It tests **GET, POST, PUT, PATCH, and DELETE** operations.
21+
- For DELETE, it first creates a temporary record to ensure valid deletion.
22+
- Results are printed and compared in a summary table.
23+
24+
### 📂 Benchmark Structure
25+
- The main benchmark script is in `benchmarks/benchmark.py`.
26+
- Test applications are organized in separate folders (`without_fastopenapi/` and `with_fastopenapi/`).
27+
- Each implementation runs on different ports (`8000` and `8001` by default).
28+
29+
### ▶️ Running the Benchmark
30+
1. Start both API implementations:
31+
```sh
32+
python benchmarks/<framework>/without_fastopenapi/run.py
33+
python benchmarks/<framework>/with_fastopenapi/run.py
34+
```
35+
2. Run the benchmark:
36+
```sh
37+
python benchmarks/benchmark.py
38+
```
39+
3. Waiting for the results (example):
40+
```sh
41+
Testing Original Implementation
42+
43+
Original - Running 10000 iterations per endpoint
44+
--------------------------------------------------
45+
GET all records: 16.3760 sec total, 1.64 ms per request
46+
GET one record: 17.7782 sec total, 1.78 ms per request
47+
POST new record: 19.8376 sec total, 1.98 ms per request
48+
PUT record: 20.4346 sec total, 2.04 ms per request
49+
PATCH record: 19.7331 sec total, 1.97 ms per request
50+
DELETE record: 37.4556 sec total, 3.75 ms per request
51+
52+
Testing FastOpenAPI Implementation
53+
54+
FastOpenAPI - Running 10000 iterations per endpoint
55+
--------------------------------------------------
56+
GET all records: 17.4752 sec total, 1.75 ms per request
57+
GET one record: 18.3059 sec total, 1.83 ms per request
58+
POST new record: 19.9647 sec total, 2.00 ms per request
59+
PUT record: 19.3761 sec total, 1.94 ms per request
60+
PATCH record: 19.5880 sec total, 1.96 ms per request
61+
DELETE record: 40.6837 sec total, 4.07 ms per request
62+
63+
Performance Comparison (10000 iterations)
64+
======================================================================
65+
Endpoint Original FastOpenAPI Difference
66+
----------------------------------------------------------------------
67+
GET all records 1.64 ms 1.75 ms 0.11 ms (+6.7%)
68+
GET one record 1.78 ms 1.83 ms 0.05 ms (+3.0%)
69+
POST new record 1.98 ms 2.00 ms 0.01 ms (+0.6%)
70+
PUT record 2.04 ms 1.94 ms -0.11 ms (-5.2%)
71+
PATCH record 1.97 ms 1.96 ms -0.01 ms (-0.7%)
72+
DELETE record 3.75 ms 4.07 ms 0.32 ms (+8.6%)
73+
```

0 commit comments

Comments
 (0)