lightapi 0.1.6__tar.gz → 0.1.8__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {lightapi-0.1.6 → lightapi-0.1.8}/PKG-INFO +1 -1
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/advanced/authentication.md +4 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/api-reference/rest.md +16 -1
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/examples/.pages +2 -3
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/examples/auth.md +20 -31
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/index.md +27 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/tutorial/endpoints.md +15 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/examples/README.md +36 -50
- lightapi-0.1.6/examples/auth_example.py → lightapi-0.1.8/examples/authentication_jwt.py +5 -11
- lightapi-0.1.8/examples/blog_post.py +57 -0
- lightapi-0.1.6/examples/caching_example.py → lightapi-0.1.8/examples/caching_redis_custom.py +2 -3
- lightapi-0.1.6/examples/user_goal_example.py → lightapi-0.1.8/examples/comprehensive_ideal_usage.py +4 -3
- lightapi-0.1.6/examples/filtering_pagination_example.py → lightapi-0.1.8/examples/filtering_pagination.py +3 -11
- lightapi-0.1.6/examples/example.py → lightapi-0.1.8/examples/general_usage.py +7 -10
- lightapi-0.1.8/examples/mega_example.py +660 -0
- lightapi-0.1.6/examples/custom_snippet.py → lightapi-0.1.8/examples/middleware_cors_auth.py +14 -27
- lightapi-0.1.6/examples/middleware_example.py → lightapi-0.1.8/examples/middleware_custom.py +4 -14
- lightapi-0.1.6/examples/relationships_example.py → lightapi-0.1.8/examples/relationships_sqlalchemy.py +31 -73
- lightapi-0.1.6/examples/basic_rest_api.py → lightapi-0.1.8/examples/rest_crud_basic.py +1 -1
- lightapi-0.1.6/examples/swagger_example.py → lightapi-0.1.8/examples/swagger_openapi_docs.py +5 -10
- lightapi-0.1.6/examples/validation_example.py → lightapi-0.1.8/examples/validation_custom_fields.py +1 -1
- {lightapi-0.1.6 → lightapi-0.1.8}/lightapi/auth.py +1 -3
- {lightapi-0.1.6 → lightapi-0.1.8}/lightapi/base_endpoint.py +1 -3
- {lightapi-0.1.6 → lightapi-0.1.8}/lightapi/config.py +6 -18
- {lightapi-0.1.6 → lightapi-0.1.8}/lightapi/core.py +56 -109
- {lightapi-0.1.6 → lightapi-0.1.8}/lightapi/database.py +12 -2
- {lightapi-0.1.6 → lightapi-0.1.8}/lightapi/exceptions.py +1 -2
- {lightapi-0.1.6 → lightapi-0.1.8}/lightapi/handlers.py +125 -64
- lightapi-0.1.8/lightapi/lightapi.py +719 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/lightapi/models.py +57 -11
- {lightapi-0.1.6 → lightapi-0.1.8}/lightapi/rest.py +140 -27
- {lightapi-0.1.6 → lightapi-0.1.8}/lightapi/swagger.py +9 -35
- {lightapi-0.1.6 → lightapi-0.1.8}/pyproject.toml +1 -1
- lightapi-0.1.8/run_server.py +6 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/tests/test_additional_features.py +2 -62
- {lightapi-0.1.6 → lightapi-0.1.8}/tests/test_auth.py +5 -2
- {lightapi-0.1.6 → lightapi-0.1.8}/tests/test_cache.py +7 -32
- {lightapi-0.1.6 → lightapi-0.1.8}/tests/test_caching_example.py +19 -160
- lightapi-0.1.8/tests/test_core.py +41 -0
- lightapi-0.1.8/tests/test_custom_snippet.py +40 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/tests/test_filtering_pagination_example.py +7 -7
- {lightapi-0.1.6 → lightapi-0.1.8}/tests/test_filters.py +4 -24
- lightapi-0.1.8/tests/test_from_config.py +1149 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/tests/test_helpers.py +3 -19
- lightapi-0.1.8/tests/test_integration.py +54 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/tests/test_middleware.py +4 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/tests/test_rest.py +1 -17
- {lightapi-0.1.6 → lightapi-0.1.8}/tests/test_swagger.py +2 -6
- lightapi-0.1.8/tests/test_validators.py +45 -0
- lightapi-0.1.8/uv.lock +3107 -0
- lightapi-0.1.6/lightapi/lightapi.py +0 -341
- lightapi-0.1.6/run_server.py +0 -6
- lightapi-0.1.6/tests/test_auth_example.py +0 -301
- lightapi-0.1.6/tests/test_basic_rest_api.py +0 -209
- lightapi-0.1.6/tests/test_core.py +0 -81
- lightapi-0.1.6/tests/test_custom_snippet.py +0 -328
- lightapi-0.1.6/tests/test_example.py +0 -56
- lightapi-0.1.6/tests/test_from_config.py +0 -932
- lightapi-0.1.6/tests/test_integration.py +0 -112
- lightapi-0.1.6/tests/test_middleware_example.py +0 -337
- lightapi-0.1.6/tests/test_validation_example.py +0 -210
- lightapi-0.1.6/uv.lock +0 -734
- {lightapi-0.1.6 → lightapi-0.1.8}/.github/workflows/pages-publish.yml +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/.github/workflows/python-publish.yml +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/.github/workflows/test-dev.yml +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/.gitignore +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/LICENSE +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/README.md +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/.pages +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/advanced/.pages +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/advanced/caching.md +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/advanced/filtering.md +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/advanced/middleware.md +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/advanced/pagination.md +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/advanced/validation.md +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/api-reference/.pages +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/api-reference/auth.md +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/api-reference/cache.md +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/api-reference/core.md +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/api-reference/database.md +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/api-reference/exceptions.md +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/api-reference/filters.md +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/api-reference/index.md +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/api-reference/models.md +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/api-reference/pagination.md +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/api-reference/swagger.md +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/api-reference/validation.md +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/deployment/.pages +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/deployment/docker.md +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/deployment/production.md +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/deployment/security.md +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/examples/basic-crud.md +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/examples/basic-rest.md +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/examples/caching.md +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/examples/custom-application.md +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/examples/filtering-pagination.md +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/examples/middleware.md +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/examples/validation.md +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/getting-started/.pages +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/getting-started/configuration.md +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/getting-started/first-steps.md +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/getting-started/installation.md +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/getting-started/introduction.md +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/getting-started/quickstart.md +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/technical-reference/.pages +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/technical-reference/cache.md +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/technical-reference/core-api.md +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/technical-reference/endpoints.md +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/technical-reference/handlers.md +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/technical-reference/middleware.md +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/technical-reference/models.md +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/troubleshooting.md +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/tutorial/.pages +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/tutorial/basic-api.md +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/tutorial/database.md +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/tutorial/requests.md +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/docs/tutorial/responses.md +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/examples/__init__.py +0 -0
- lightapi-0.1.6/tests/__init__.py → lightapi-0.1.8/examples/example.py +0 -0
- lightapi-0.1.6/tests/test_clients.py → lightapi-0.1.8/examples/user_goal_example.py +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/lightapi/__init__.py +1 -1
- {lightapi-0.1.6 → lightapi-0.1.8}/lightapi/cache.py +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/lightapi/filters.py +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/lightapi/pagination.py +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/mkdocs.yml +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/pytest.ini +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/requirements.txt +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/tests/conftest.py +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/tests/test_pagination.py +0 -0
- {lightapi-0.1.6 → lightapi-0.1.8}/update_version.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: lightapi
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.8
|
|
4
4
|
Summary: A lightweight framework for building API endpoints using Python's native libraries.
|
|
5
5
|
Project-URL: Repository, https://github.com/henriqueblobato/LightApi
|
|
6
6
|
Project-URL: Issues, https://github.com/henriqueblobato/LightApi/issues
|
|
@@ -732,3 +732,7 @@ app.add_middleware([SecurityHeadersMiddleware])
|
|
|
732
732
|
```
|
|
733
733
|
|
|
734
734
|
This comprehensive authentication system provides enterprise-grade security while maintaining the simplicity and performance that LightAPI is known for. The modular design allows you to implement exactly the authentication strategy your application needs, from simple API keys to complex multi-factor authentication systems.
|
|
735
|
+
|
|
736
|
+
> **Note:** All JWT-protected endpoints require the `LIGHTAPI_JWT_SECRET` environment variable to be set before running the server.
|
|
737
|
+
|
|
738
|
+
> **Custom endpoints must specify their intended paths using `route_patterns`. See the mega example for a full-stack authentication and registration demo.**
|
|
@@ -753,4 +753,19 @@ class User(RestEndpoint):
|
|
|
753
753
|
- All required fields must be defined as NOT NULL in your database schema for correct enforcement.
|
|
754
754
|
- The API will return 409 Conflict if you attempt to create or update a record missing a NOT NULL field, or violating a UNIQUE or FOREIGN KEY constraint.
|
|
755
755
|
|
|
756
|
-
To start your API, always use `api.run(host, port)`. Do not use external libraries or 'app = api.app' to start the server directly.
|
|
756
|
+
To start your API, always use `api.run(host, port)`. Do not use external libraries or 'app = api.app' to start the server directly.
|
|
757
|
+
|
|
758
|
+
## Custom Endpoint Registration with route_patterns
|
|
759
|
+
|
|
760
|
+
When registering custom (non-model) endpoints, you must specify the intended REST path(s) using the `route_patterns` attribute. Fallback to class names is not supported for custom endpoints.
|
|
761
|
+
|
|
762
|
+
```python
|
|
763
|
+
class HelloWorldEndpoint(RestEndpoint):
|
|
764
|
+
route_patterns = ["/hello"]
|
|
765
|
+
def get(self, request):
|
|
766
|
+
return {"message": "Hello, World!"}
|
|
767
|
+
|
|
768
|
+
app.register(HelloWorldEndpoint)
|
|
769
|
+
```
|
|
770
|
+
|
|
771
|
+
> See the mega example for a comprehensive demonstration of registering multiple endpoints with custom paths.
|
|
@@ -6,7 +6,6 @@ nav:
|
|
|
6
6
|
- Caching: caching.md
|
|
7
7
|
- Filtering and Pagination: filtering-pagination.md
|
|
8
8
|
- Middleware: middleware.md
|
|
9
|
-
- Relationships: relationships.md
|
|
10
|
-
- Swagger Documentation: swagger.md
|
|
11
9
|
- Validation: validation.md
|
|
12
|
-
- Custom
|
|
10
|
+
- Custom Application: custom-application.md
|
|
11
|
+
- Basic CRUD: basic-crud.md
|
|
@@ -158,52 +158,41 @@ curl -X POST http://localhost:8000/auth/login \
|
|
|
158
158
|
}
|
|
159
159
|
```
|
|
160
160
|
|
|
161
|
-
### 2. Access
|
|
161
|
+
### 2. Access User Profile (JWT-protected)
|
|
162
162
|
|
|
163
|
-
|
|
164
|
-
curl http://localhost:8000/public
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
**Response:**
|
|
168
|
-
```json
|
|
169
|
-
{
|
|
170
|
-
"message": "This is public information"
|
|
171
|
-
}
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
### 3. Access Protected Endpoint
|
|
163
|
+
> **Note:** The `user_id` field in the profile must match the JWT `sub` claim (e.g., `user_1`).
|
|
175
164
|
|
|
176
165
|
```bash
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
}
|
|
186
|
-
```
|
|
166
|
+
curl -X POST http://localhost:8000/user_profiles \
|
|
167
|
+
-H "Content-Type: application/json" \
|
|
168
|
+
-H "Authorization: Bearer YOUR_TOKEN" \
|
|
169
|
+
-d '{
|
|
170
|
+
"user_id": "user_1",
|
|
171
|
+
"full_name": "Admin User",
|
|
172
|
+
"email": "admin@example.com"
|
|
173
|
+
}'
|
|
187
174
|
|
|
188
|
-
```bash
|
|
189
|
-
# With valid token
|
|
190
175
|
curl -H "Authorization: Bearer YOUR_TOKEN" \
|
|
191
|
-
http://localhost:8000/
|
|
176
|
+
http://localhost:8000/user_profiles
|
|
192
177
|
```
|
|
193
178
|
|
|
194
179
|
**Response:**
|
|
195
180
|
```json
|
|
196
181
|
{
|
|
197
|
-
"
|
|
198
|
-
"
|
|
182
|
+
"id": 2,
|
|
183
|
+
"user_id": "user_1",
|
|
184
|
+
"full_name": "Admin User",
|
|
185
|
+
"email": "admin@example.com"
|
|
199
186
|
}
|
|
200
187
|
```
|
|
201
188
|
|
|
202
|
-
###
|
|
189
|
+
### 3. Troubleshooting
|
|
190
|
+
|
|
191
|
+
- If you get `{ "error": "Profile not found" }`, ensure you created the profile with `user_id` matching the JWT `sub` claim.
|
|
192
|
+
- Always set the environment variable before running the server:
|
|
203
193
|
|
|
204
194
|
```bash
|
|
205
|
-
|
|
206
|
-
http://localhost:8000/profile
|
|
195
|
+
export LIGHTAPI_JWT_SECRET="your-super-secret-key"
|
|
207
196
|
```
|
|
208
197
|
|
|
209
198
|
## JWT Token Structure
|
|
@@ -160,3 +160,30 @@ LightAPI is released under the [MIT License](https://github.com/henriqueblobato/
|
|
|
160
160
|
|
|
161
161
|
> To start your API, always use `api.run(host, port)`. Do not use external libraries or 'app = api.app' to start the server directly.
|
|
162
162
|
|
|
163
|
+
## Mega Example: All Features in One App
|
|
164
|
+
|
|
165
|
+
The `examples/mega_example.py` script demonstrates the full capabilities of LightAPI:
|
|
166
|
+
- RESTful models (products, categories, orders, users, etc.)
|
|
167
|
+
- Custom endpoints (auth, weather, hello, secret, public, etc.)
|
|
168
|
+
- JWT authentication and protected resources
|
|
169
|
+
- Middleware (logging, CORS, rate limiting, authentication)
|
|
170
|
+
- Caching, filtering, pagination, and more
|
|
171
|
+
|
|
172
|
+
**Available Endpoints:**
|
|
173
|
+
|
|
174
|
+
| Path | Methods | Description |
|
|
175
|
+
|-----------------------|--------------------------------------------|------------------------------|
|
|
176
|
+
| /products | GET, POST, PUT, PATCH, DELETE, OPTIONS | Product CRUD |
|
|
177
|
+
| /categories | GET, POST, PUT, PATCH, DELETE, OPTIONS | Category CRUD |
|
|
178
|
+
| /orders | GET, POST, PUT, PATCH, DELETE, OPTIONS | Order CRUD |
|
|
179
|
+
| /order_items | GET, POST, PUT, PATCH, DELETE, OPTIONS | Order item CRUD |
|
|
180
|
+
| /users | GET, POST, PUT, PATCH, DELETE, OPTIONS | User CRUD |
|
|
181
|
+
| /user_profiles | GET, POST, PUT, PATCH, DELETE, OPTIONS | User profile (JWT protected) |
|
|
182
|
+
| /auth/login | POST, OPTIONS | JWT login |
|
|
183
|
+
| /secret | GET, OPTIONS (JWT required) | Protected resource |
|
|
184
|
+
| /public | GET, OPTIONS | Public resource |
|
|
185
|
+
| /weather/{city} | GET, OPTIONS | Weather info (custom path) |
|
|
186
|
+
| /hello | GET, OPTIONS | Hello world (custom path) |
|
|
187
|
+
|
|
188
|
+
> All endpoints are registered with explicit RESTful or custom paths using `route_patterns` or `__tablename__`.
|
|
189
|
+
|
|
@@ -33,6 +33,21 @@ app = LightApi()
|
|
|
33
33
|
app.register({'/custom-users': CustomUserEndpoint})
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
+
## Registering Custom Endpoints with route_patterns
|
|
37
|
+
|
|
38
|
+
When defining a custom endpoint (not a SQLAlchemy model), always specify the intended path(s) using the `route_patterns` attribute:
|
|
39
|
+
|
|
40
|
+
```python
|
|
41
|
+
class HelloWorldEndpoint(RestEndpoint):
|
|
42
|
+
route_patterns = ["/hello"]
|
|
43
|
+
def get(self, request):
|
|
44
|
+
return {"message": "Hello, World!"}
|
|
45
|
+
|
|
46
|
+
app.register(HelloWorldEndpoint)
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
> See the mega example for a comprehensive demonstration of this pattern.
|
|
50
|
+
|
|
36
51
|
## HTTP Method Configuration
|
|
37
52
|
|
|
38
53
|
- `http_method_names`: List of allowed HTTP methods.
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
This directory contains example applications demonstrating various features of the LightAPI framework.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Example Features
|
|
6
6
|
|
|
7
|
-
- **
|
|
7
|
+
- **comprehensive_ideal_usage.py**: Comprehensive demonstration of intended LightAPI usage patterns
|
|
8
8
|
- Shows the exact API design philosophy and usage as envisioned
|
|
9
9
|
- Demonstrates custom validators with field-specific validation methods
|
|
10
10
|
- Implements JWT authentication with proper configuration
|
|
@@ -13,17 +13,17 @@ This directory contains example applications demonstrating various features of t
|
|
|
13
13
|
- Includes CORS support and proper environment variable usage
|
|
14
14
|
- **Note**: Some advanced features (caching + pagination) are commented out due to current limitations
|
|
15
15
|
|
|
16
|
-
- **
|
|
16
|
+
- **rest_crud_basic.py**: A simple REST API with default CRUD operations
|
|
17
17
|
- Demonstrates minimal setup for a REST endpoint
|
|
18
18
|
- Shows automatic handling of GET, POST, PUT, DELETE operations
|
|
19
19
|
- Illustrates SQLAlchemy model integration with LightAPI
|
|
20
20
|
|
|
21
|
-
- **
|
|
21
|
+
- **validation_custom_fields.py**: Data validation with custom validators
|
|
22
22
|
- Shows field-specific validation rules using Validator class
|
|
23
23
|
- Demonstrates error handling for validation failures
|
|
24
24
|
- Illustrates data transformation (price conversion between dollars and cents)
|
|
25
25
|
|
|
26
|
-
- **
|
|
26
|
+
- **authentication_jwt.py**: JWT authentication with protected resources
|
|
27
27
|
- Implements JWT token generation and verification
|
|
28
28
|
- Shows protected endpoints requiring authentication
|
|
29
29
|
- Demonstrates user information extraction from token
|
|
@@ -31,45 +31,31 @@ This directory contains example applications demonstrating various features of t
|
|
|
31
31
|
|
|
32
32
|
## Advanced Features
|
|
33
33
|
|
|
34
|
-
- **
|
|
34
|
+
- **middleware_cors_auth.py**: Built-in middleware demonstration
|
|
35
35
|
- Shows new `CORSMiddleware` and `AuthenticationMiddleware` classes
|
|
36
36
|
- Demonstrates automatic CORS preflight handling with JWT authentication
|
|
37
37
|
- Illustrates seamless integration of authentication with CORS support
|
|
38
38
|
- Uses built-in middleware for cleaner, more maintainable code
|
|
39
39
|
|
|
40
|
-
- **
|
|
41
|
-
- Demonstrates
|
|
42
|
-
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
-
|
|
47
|
-
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
-
|
|
55
|
-
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
-
|
|
59
|
-
|
|
60
|
-
- **swagger_example.py**: Enhanced OpenAPI/Swagger documentation
|
|
61
|
-
- Demonstrates docstring-based API documentation
|
|
62
|
-
- Shows custom SwaggerGenerator implementation
|
|
63
|
-
- Illustrates request/response schema documentation
|
|
64
|
-
- Implements API grouping with tags
|
|
65
|
-
- Demonstrates security scheme definitions
|
|
66
|
-
|
|
67
|
-
- **relationships_example.py**: Complex SQLAlchemy relationships (one-to-many, many-to-many)
|
|
68
|
-
- Shows many-to-many relationships with association tables
|
|
69
|
-
- Demonstrates one-to-many relationships with back references
|
|
70
|
-
- Illustrates cascade behaviors on related objects
|
|
71
|
-
- Shows nested data serialization across relationships
|
|
72
|
-
- Implements relationship handling in POST/PUT operations
|
|
40
|
+
- **filtering_pagination.py**: Filtering and pagination
|
|
41
|
+
- Demonstrates filtering, pagination, and sorting of results
|
|
42
|
+
- Shows how to use query parameters for advanced queries
|
|
43
|
+
|
|
44
|
+
- **middleware_custom.py**: Custom middleware and order
|
|
45
|
+
- Demonstrates how to add custom middleware
|
|
46
|
+
- Shows the order of middleware execution
|
|
47
|
+
- Includes logging, CORS, and rate limiting examples
|
|
48
|
+
|
|
49
|
+
- **relationships_sqlalchemy.py**: SQLAlchemy relationships
|
|
50
|
+
- Demonstrates one-to-many and many-to-many relationships
|
|
51
|
+
- Shows how to query related resources
|
|
52
|
+
|
|
53
|
+
- **swagger_openapi_docs.py**: Swagger/OpenAPI documentation
|
|
54
|
+
- Shows how to generate and customize API documentation
|
|
55
|
+
- Demonstrates validator docstrings for better docs
|
|
56
|
+
|
|
57
|
+
- **general_usage.py**: General usage
|
|
58
|
+
- Shows custom validator, custom headers, and CRUD
|
|
73
59
|
|
|
74
60
|
## New Built-in Features (Latest Updates)
|
|
75
61
|
|
|
@@ -95,17 +81,17 @@ All examples now demonstrate improved CORS handling:
|
|
|
95
81
|
Each example is self-contained and can be run directly:
|
|
96
82
|
|
|
97
83
|
```bash
|
|
98
|
-
# Basic example
|
|
99
|
-
python examples/
|
|
84
|
+
# Basic REST/CRUD example
|
|
85
|
+
python examples/rest_crud_basic.py
|
|
100
86
|
|
|
101
|
-
# Built-in middleware
|
|
102
|
-
LIGHTAPI_JWT_SECRET="your-secret-key" python examples/
|
|
87
|
+
# Built-in middleware, CORS, Auth example
|
|
88
|
+
LIGHTAPI_JWT_SECRET="your-secret-key" python examples/middleware_cors_auth.py
|
|
103
89
|
|
|
104
|
-
# Authentication
|
|
105
|
-
LIGHTAPI_JWT_SECRET="your-secret-key" python examples/
|
|
90
|
+
# JWT Authentication example
|
|
91
|
+
LIGHTAPI_JWT_SECRET="your-secret-key" python examples/authentication_jwt.py
|
|
106
92
|
|
|
107
93
|
# Caching with Redis (requires Redis running)
|
|
108
|
-
python examples/
|
|
94
|
+
python examples/caching_redis_custom.py
|
|
109
95
|
```
|
|
110
96
|
|
|
111
97
|
Most examples will:
|
|
@@ -119,11 +105,11 @@ Most examples will:
|
|
|
119
105
|
The examples now include improved CORS and authentication. Test with:
|
|
120
106
|
|
|
121
107
|
```bash
|
|
122
|
-
# Start the
|
|
123
|
-
LIGHTAPI_JWT_SECRET="test-secret-key-123" python examples/
|
|
108
|
+
# Start the middleware_cors_auth example
|
|
109
|
+
LIGHTAPI_JWT_SECRET="test-secret-key-123" python examples/middleware_cors_auth.py
|
|
124
110
|
|
|
125
|
-
# Start the
|
|
126
|
-
LIGHTAPI_JWT_SECRET="test-secret-key-123" python examples/
|
|
111
|
+
# Start the comprehensive_ideal_usage example (comprehensive demonstration)
|
|
112
|
+
LIGHTAPI_JWT_SECRET="test-secret-key-123" python examples/comprehensive_ideal_usage.py
|
|
127
113
|
|
|
128
114
|
# Test CORS preflight (should work without authentication)
|
|
129
115
|
curl -X OPTIONS http://localhost:8000/custom -v
|
|
@@ -124,14 +124,10 @@ if __name__ == "__main__":
|
|
|
124
124
|
swagger_description="Example showing JWT authentication with LightAPI",
|
|
125
125
|
)
|
|
126
126
|
|
|
127
|
-
app.register(
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
"/secret": SecretResource,
|
|
132
|
-
"/profile": UserProfile,
|
|
133
|
-
}
|
|
134
|
-
)
|
|
127
|
+
app.register(AuthEndpoint)
|
|
128
|
+
app.register(PublicResource)
|
|
129
|
+
app.register(SecretResource)
|
|
130
|
+
app.register(UserProfile)
|
|
135
131
|
|
|
136
132
|
print("Server running at http://localhost:8000")
|
|
137
133
|
print("API documentation available at http://localhost:8000/docs")
|
|
@@ -140,8 +136,6 @@ if __name__ == "__main__":
|
|
|
140
136
|
'curl -X POST http://localhost:8000/auth/login -H \'Content-Type: application/json\' -d \'{"username": "admin", "password": "password"}\''
|
|
141
137
|
)
|
|
142
138
|
print("\nTo access protected resource:")
|
|
143
|
-
print(
|
|
144
|
-
"curl -X GET http://localhost:8000/secret -H 'Authorization: Bearer YOUR_TOKEN'"
|
|
145
|
-
)
|
|
139
|
+
print("curl -X GET http://localhost:8000/secret -H 'Authorization: Bearer YOUR_TOKEN'")
|
|
146
140
|
|
|
147
141
|
app.run(host="localhost", port=8000, debug=True)
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
|
|
3
|
+
from sqlalchemy import Column, DateTime, ForeignKey, Integer, String, Text
|
|
4
|
+
from sqlalchemy.orm import relationship
|
|
5
|
+
|
|
6
|
+
from lightapi import LightApi
|
|
7
|
+
from lightapi.database import Base
|
|
8
|
+
from lightapi.rest import RestEndpoint
|
|
9
|
+
|
|
10
|
+
print(f"DEBUG: LightApi loaded from {LightApi.__module__}")
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class BlogPost(Base):
|
|
14
|
+
__tablename__ = "posts"
|
|
15
|
+
|
|
16
|
+
id = Column(Integer, primary_key=True)
|
|
17
|
+
title = Column(String(200), nullable=False)
|
|
18
|
+
content = Column(Text, nullable=False)
|
|
19
|
+
created_at = Column(DateTime, default=datetime.utcnow, nullable=False)
|
|
20
|
+
|
|
21
|
+
comments = relationship("Comment", back_populates="post", cascade="all, delete-orphan")
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class Comment(Base):
|
|
25
|
+
__tablename__ = "comments"
|
|
26
|
+
|
|
27
|
+
id = Column(Integer, primary_key=True)
|
|
28
|
+
content = Column(String(1000), nullable=False)
|
|
29
|
+
author = Column(String(100), nullable=False)
|
|
30
|
+
created_at = Column(DateTime, default=datetime.utcnow, nullable=False)
|
|
31
|
+
post_id = Column(Integer, ForeignKey("posts.id"), nullable=False)
|
|
32
|
+
|
|
33
|
+
post = relationship("BlogPost", back_populates="comments")
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class Endpoint(RestEndpoint):
|
|
37
|
+
__tablename__ = "asdasd"
|
|
38
|
+
|
|
39
|
+
def get(self, post_id: int):
|
|
40
|
+
return {"status": "ok"}, 200
|
|
41
|
+
|
|
42
|
+
def post(self, data: dict):
|
|
43
|
+
return {"status": "ok"}, 200
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
if __name__ == "__main__":
|
|
47
|
+
app = LightApi(
|
|
48
|
+
enable_swagger=True,
|
|
49
|
+
swagger_title="Blog Post API",
|
|
50
|
+
swagger_version="1.0.0",
|
|
51
|
+
swagger_description="API documentation for the Blog Post application",
|
|
52
|
+
)
|
|
53
|
+
app.register(BlogPost)
|
|
54
|
+
app.register(Comment)
|
|
55
|
+
app.register(Endpoint)
|
|
56
|
+
|
|
57
|
+
app.run(host="0.0.0.0", port=8000)
|
lightapi-0.1.6/examples/caching_example.py → lightapi-0.1.8/examples/caching_redis_custom.py
RENAMED
|
@@ -168,9 +168,8 @@ if __name__ == "__main__":
|
|
|
168
168
|
swagger_description="Example showing caching capabilities with LightAPI",
|
|
169
169
|
)
|
|
170
170
|
|
|
171
|
-
app.register(
|
|
172
|
-
|
|
173
|
-
)
|
|
171
|
+
app.register(WeatherEndpoint)
|
|
172
|
+
app.register(ConfigurableCacheEndpoint)
|
|
174
173
|
|
|
175
174
|
print("Server running at http://localhost:8000")
|
|
176
175
|
print("API documentation available at http://localhost:8000/docs")
|
lightapi-0.1.6/examples/user_goal_example.py → lightapi-0.1.8/examples/comprehensive_ideal_usage.py
RENAMED
|
@@ -47,10 +47,10 @@ class Company(RestEndpoint):
|
|
|
47
47
|
validator_class = CustomEndpointValidator
|
|
48
48
|
filter_class = ParameterFilter
|
|
49
49
|
|
|
50
|
-
def post(self, request):
|
|
50
|
+
async def post(self, request):
|
|
51
51
|
"""Handle POST requests with custom Response object"""
|
|
52
52
|
return Response(
|
|
53
|
-
{"data": "ok", "request_data":
|
|
53
|
+
{"data": "ok", "request_data": await request.get_data()},
|
|
54
54
|
status_code=200,
|
|
55
55
|
content_type="application/json",
|
|
56
56
|
)
|
|
@@ -126,7 +126,8 @@ class CustomCORSMiddleware(Middleware):
|
|
|
126
126
|
app = LightApi()
|
|
127
127
|
|
|
128
128
|
# Register endpoints
|
|
129
|
-
app.register(
|
|
129
|
+
app.register(CustomEndpoint)
|
|
130
|
+
app.register(Company)
|
|
130
131
|
|
|
131
132
|
# Add middleware
|
|
132
133
|
# Note: Custom auth middleware is commented out to avoid blocking all requests
|
|
@@ -92,9 +92,7 @@ class ProductPaginator(Paginator):
|
|
|
92
92
|
|
|
93
93
|
# Validate the sort field
|
|
94
94
|
if sort_field in self.valid_sort_fields:
|
|
95
|
-
column = getattr(
|
|
96
|
-
queryset.column_descriptions[0]["type"], sort_field
|
|
97
|
-
)
|
|
95
|
+
column = getattr(queryset.column_descriptions[0]["type"], sort_field)
|
|
98
96
|
if descending:
|
|
99
97
|
queryset = queryset.order_by(column.desc())
|
|
100
98
|
else:
|
|
@@ -241,9 +239,7 @@ def init_database():
|
|
|
241
239
|
category="Clothing",
|
|
242
240
|
description="Cotton t-shirt",
|
|
243
241
|
),
|
|
244
|
-
Product(
|
|
245
|
-
name="Jeans", price=6000, category="Clothing", description="Denim jeans"
|
|
246
|
-
),
|
|
242
|
+
Product(name="Jeans", price=6000, category="Clothing", description="Denim jeans"),
|
|
247
243
|
Product(
|
|
248
244
|
name="Sneakers",
|
|
249
245
|
price=8000,
|
|
@@ -341,11 +337,7 @@ if __name__ == "__main__":
|
|
|
341
337
|
swagger_description="Example showing filtering and pagination with LightAPI",
|
|
342
338
|
)
|
|
343
339
|
|
|
344
|
-
app.register(
|
|
345
|
-
{
|
|
346
|
-
"/products": Product,
|
|
347
|
-
}
|
|
348
|
-
)
|
|
340
|
+
app.register(Product)
|
|
349
341
|
|
|
350
342
|
print("Server running at http://localhost:8000")
|
|
351
343
|
print("API documentation available at http://localhost:8000/docs")
|
|
@@ -36,13 +36,13 @@ class Company(RestEndpoint):
|
|
|
36
36
|
validator_class = CustomEndpointValidator
|
|
37
37
|
filter_class = ParameterFilter
|
|
38
38
|
|
|
39
|
-
def post(self, request):
|
|
39
|
+
async def post(self, request):
|
|
40
40
|
"""Create a new company.
|
|
41
41
|
|
|
42
42
|
Accepts company data and creates a new record.
|
|
43
43
|
"""
|
|
44
44
|
return Response(
|
|
45
|
-
{"data": "ok", "request_data": request.
|
|
45
|
+
{"data": "ok", "request_data": await request.get_data()},
|
|
46
46
|
status_code=200,
|
|
47
47
|
content_type="application/json",
|
|
48
48
|
)
|
|
@@ -76,7 +76,7 @@ class CustomEndpoint(RestEndpoint):
|
|
|
76
76
|
caching_method_names = ["GET"]
|
|
77
77
|
pagination_class = CustomPaginator
|
|
78
78
|
|
|
79
|
-
def post(self, request):
|
|
79
|
+
async def post(self, request):
|
|
80
80
|
return {"data": "ok"}, 200
|
|
81
81
|
|
|
82
82
|
def get(self, request):
|
|
@@ -97,12 +97,8 @@ class CORSMiddleware(Middleware):
|
|
|
97
97
|
|
|
98
98
|
if hasattr(response, "headers"):
|
|
99
99
|
response.headers["Access-Control-Allow-Origin"] = "*"
|
|
100
|
-
response.headers[
|
|
101
|
-
|
|
102
|
-
] = "GET, POST, PUT, DELETE, OPTIONS"
|
|
103
|
-
response.headers[
|
|
104
|
-
"Access-Control-Allow-Headers"
|
|
105
|
-
] = "Authorization, Content-Type"
|
|
100
|
+
response.headers["Access-Control-Allow-Methods"] = "GET, POST, PUT, DELETE, OPTIONS"
|
|
101
|
+
response.headers["Access-Control-Allow-Headers"] = "Authorization, Content-Type"
|
|
106
102
|
|
|
107
103
|
if request.method == "OPTIONS":
|
|
108
104
|
return Response(status_code=200)
|
|
@@ -116,7 +112,8 @@ if __name__ == "__main__":
|
|
|
116
112
|
swagger_version="1.0.0",
|
|
117
113
|
swagger_description="Example API for demonstrating LightAPI capabilities",
|
|
118
114
|
)
|
|
119
|
-
app.register(
|
|
115
|
+
app.register(Company)
|
|
116
|
+
app.register(CustomEndpoint)
|
|
120
117
|
# app.add_middleware([MyCustomMiddleware, CORSMiddleware])
|
|
121
118
|
|
|
122
119
|
print("Server running at http://0.0.0.0:8000")
|