bustapi 0.12.0__tar.gz → 0.13.0__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.
- bustapi-0.13.0/.github/FUNDING.yml +3 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/CHANGELOG.md +18 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/Cargo.lock +17 -15
- {bustapi-0.12.0 → bustapi-0.13.0}/Cargo.toml +1 -1
- {bustapi-0.12.0 → bustapi-0.13.0}/PKG-INFO +14 -13
- {bustapi-0.12.0 → bustapi-0.13.0}/README.md +9 -8
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/changelog.md +18 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/complete-api-reference.md +71 -10
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/examples-guide.md +9 -2
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/index.md +3 -1
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/quickstart.md +4 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/user-guide/authentication.md +3 -0
- bustapi-0.13.0/docs/user-guide/documentation.md +144 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/user-guide/error_handling.md +30 -0
- bustapi-0.13.0/docs/user-guide/jwt.md +203 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/user-guide/responses.md +63 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/examples/security/17_jwt_auth.py +1 -1
- bustapi-0.13.0/examples/security/18_jwt_cookies.py +99 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/pyproject.toml +6 -6
- {bustapi-0.12.0 → bustapi-0.13.0}/python/bustapi/__init__.py +4 -1
- {bustapi-0.12.0 → bustapi-0.13.0}/python/bustapi/app.py +32 -148
- {bustapi-0.12.0 → bustapi-0.13.0}/python/bustapi/auth/decorators.py +23 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/python/bustapi/auth/login.py +6 -1
- {bustapi-0.12.0 → bustapi-0.13.0}/python/bustapi/core/exceptions.py +3 -1
- {bustapi-0.12.0 → bustapi-0.13.0}/python/bustapi/dispatch.py +120 -119
- {bustapi-0.12.0 → bustapi-0.13.0}/python/bustapi/hooks.py +15 -3
- bustapi-0.13.0/python/bustapi/http/response.py +284 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/python/bustapi/jwt.py +122 -97
- {bustapi-0.12.0 → bustapi-0.13.0}/python/bustapi/server/wsgi.py +44 -13
- {bustapi-0.12.0 → bustapi-0.13.0}/python/bustapi/testing/client.py +62 -172
- {bustapi-0.12.0 → bustapi-0.13.0}/python/bustapi/utils.py +51 -1
- bustapi-0.13.0/scratch/test_abort.py +20 -0
- bustapi-0.13.0/scratch/test_headers.py +9 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/src/bindings/app.rs +4 -22
- {bustapi-0.12.0 → bustapi-0.13.0}/src/bindings/converters.rs +75 -158
- {bustapi-0.12.0 → bustapi-0.13.0}/src/response/builders.rs +6 -9
- bustapi-0.13.0/src/response/methods.rs +82 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/src/router/handlers.rs +1 -1
- {bustapi-0.12.0 → bustapi-0.13.0}/src/router/middleware.rs +6 -6
- {bustapi-0.12.0 → bustapi-0.13.0}/src/server/handlers.rs +3 -3
- bustapi-0.13.0/tests/test_async_hooks.py +56 -0
- bustapi-0.13.0/tests/test_async_login.py +82 -0
- bustapi-0.13.0/tests/test_jwt_cookies.py +70 -0
- bustapi-0.13.0/tests/test_orm_conflict.py +75 -0
- bustapi-0.12.0/.github/FUNDING.yml +0 -4
- bustapi-0.12.0/docs/user-guide/documentation.md +0 -32
- bustapi-0.12.0/docs/user-guide/jwt.md +0 -174
- bustapi-0.12.0/python/bustapi/core/wsgi.py +0 -136
- bustapi-0.12.0/python/bustapi/http/response.py +0 -513
- bustapi-0.12.0/src/response/methods.rs +0 -44
- {bustapi-0.12.0 → bustapi-0.13.0}/- +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/.github/workflows/ci-multiplatform.yml +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/.github/workflows/ci.yml +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/.github/workflows/docs.yml +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/.github/workflows/manual-publish.yml +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/.gitignore +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/.python-version +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/Dockerfile +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/LICENSE +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/benchmarks/CACHE_BENCHMARK.md +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/benchmarks/README.md +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/benchmarks/app.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/benchmarks/benchmark_all.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/benchmarks/benchmark_avg.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/benchmarks/benchmark_cache.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/benchmarks/benchmark_combined.png +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/benchmarks/bustapi.md +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/benchmarks/bustapi_bench.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/benchmarks/bustapi_internal.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/benchmarks/comparison_bench.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/benchmarks/comprehensive_benchmark.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/benchmarks/gen_graph.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/benchmarks/quick_bench.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/benchmarks/resource_bench.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/benchmarks/rps_comparison.png +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/benchmarks/run_comparison_auto.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/benchmarks/ws_benchmark.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/check_path.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/create_issues.sh +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/advanced/async.md +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/advanced/blueprints.md +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/advanced/dependency_injection.md +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/advanced/deployment.md +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/advanced/middleware.md +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/advanced/security.md +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/advanced/validation.md +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/api-reference.md +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/assets/logo.png +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/deployment-performance-guide.md +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/deployment.md +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/installation.md +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/overrides/.gitkeep +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/release_track.md +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/site/advanced/async_support.html +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/site/advanced/blueprints.html +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/site/advanced/dependency_injection.html +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/site/advanced/middleware.html +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/site/advanced/validation.html +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/site/api/all.html +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/site/api/app.html +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/site/api/context.html +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/site/api/utilities.html +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/site/assets/logo.png +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/site/changelog.html +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/site/core_concepts/request_data.html +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/site/core_concepts/responses.html +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/site/core_concepts/routing.html +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/site/core_concepts/templates.html +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/site/examples/index.html +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/site/getting_started/index.html +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/site/getting_started/quickstart.html +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/site/index.html +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/site/script.js +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/site/style.css +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/stylesheets/extra.css +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/user-guide/caching.md +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/user-guide/cli.md +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/user-guide/database.md +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/user-guide/logging.md +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/user-guide/multiprocessing.md +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/user-guide/request_data.md +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/user-guide/routing.md +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/user-guide/sessions.md +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/user-guide/static_files.md +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/user-guide/templates.md +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/user-guide/turbo-routes.md +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/user-guide/video-streaming.md +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/docs/websockets.md +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/examples/advanced/08_auto_docs.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/examples/advanced/12_test_modes.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/examples/advanced/13_error_handling.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/examples/advanced/14_middleware.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/examples/advanced/16_middleware_session.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/examples/advanced/20_file_uploads.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/examples/advanced/24_body_and_depends.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/examples/advanced/27_video_stream.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/examples/advanced/28_websocket.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/examples/advanced/29_turbo_websocket.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/examples/basics/01_hello_world.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/examples/basics/02_parameters.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/examples/basics/03_async.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/examples/basics/04_request_data.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/examples/basics/19_all_types.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/examples/database/07_database_raw.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/examples/database/10_database_sqlmodel.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/examples/routing/06_blueprints.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/examples/routing/09_complex_routing.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/examples/routing/21_path_validation.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/examples/routing/22_path_docs.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/examples/routing/23_query_validation.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/examples/routing/blueprint_with_jwt.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/examples/security/10_rate_limit_demo.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/examples/security/11_security_demo.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/examples/security/17_safe_features.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/examples/security/18_safe_advanced.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/examples/security/18_session_login.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/examples/templates/05_templates.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/examples/templates/26_complex_template.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/examples/templates/templates/index.html +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/examples/turbo/cache_test.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/examples/turbo/fair_benchmark.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/examples/turbo/typed_turbo_example.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/examples/ws/app.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/examples/ws/templates/index.html +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/examples/ws/websockets_demo.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/examples/ws/ws_limit.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/mkdocs.yml +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/python/bustapi/auth/__init__.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/python/bustapi/auth/csrf.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/python/bustapi/auth/password.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/python/bustapi/auth/tokens.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/python/bustapi/auth/user.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/python/bustapi/cli/__init__.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/python/bustapi/cli/main.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/python/bustapi/context.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/python/bustapi/core/__init__.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/python/bustapi/core/asgi.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/python/bustapi/core/helpers.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/python/bustapi/core/logging.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/python/bustapi/dependencies.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/python/bustapi/documentation/__init__.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/python/bustapi/documentation/generator.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/python/bustapi/extraction.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/python/bustapi/fastapi_compat.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/python/bustapi/http/__init__.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/python/bustapi/http/request.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/python/bustapi/logging.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/python/bustapi/middleware.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/python/bustapi/multiprocess.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/python/bustapi/params.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/python/bustapi/py.typed +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/python/bustapi/responses.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/python/bustapi/routing/__init__.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/python/bustapi/routing/blueprints.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/python/bustapi/routing/decorators.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/python/bustapi/safe/__init__.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/python/bustapi/safe/concurrency.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/python/bustapi/safe/types.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/python/bustapi/security/__init__.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/python/bustapi/security/extension.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/python/bustapi/security/rate_limit.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/python/bustapi/server/__init__.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/python/bustapi/server/runner.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/python/bustapi/sessions.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/python/bustapi/templating/__init__.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/python/bustapi/templating/engine.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/python/bustapi/templating/mixin.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/python/bustapi/testing/__init__.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/python/bustapi/websocket.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/run_all_examples.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/src/bindings/handlers.rs +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/src/bindings/mod.rs +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/src/bindings/request.rs +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/src/bindings/typed_turbo.rs +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/src/bindings/websocket.rs +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/src/crypto.rs +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/src/jwt.rs +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/src/lib.rs +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/src/logger.rs +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/src/rate_limiter.rs +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/src/request/methods.rs +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/src/request/mod.rs +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/src/request/tests.rs +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/src/response/mod.rs +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/src/router/matching.rs +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/src/router/mod.rs +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/src/router/tests.rs +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/src/server/mod.rs +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/src/server/startup.rs +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/src/server/stream.rs +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/src/static_files.rs +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/src/templating.rs +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/src/watcher.rs +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/src/websocket/config.rs +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/src/websocket/mod.rs +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/src/websocket/session.rs +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/src/websocket/turbo.rs +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/static/style.css +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/templates/base.html +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/templates/complex.html +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/test_trim.rs +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/tests/docs_test_all.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/tests/docs_test_api_reference.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/tests/docs_test_installation.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/tests/docs_test_quickstart.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/tests/docs_test_simple.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/tests/test_050_features.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/tests/test_auth.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/tests/test_examples.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/tests/test_hot_reload.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/tests/test_issue_18.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/tests/test_jwt.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/tests/test_login_manager.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/tests/test_middleware.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/tests/test_multiprocess_stability.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/tests/test_new_examples.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/tests/test_path_standalone.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/tests/test_path_validation.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/tests/test_rate_limit_rust.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/tests/test_safe.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/tests/test_security_unit.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/tests/test_sessions.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/tests/test_zero_copy.py +0 -0
- {bustapi-0.12.0 → bustapi-0.13.0}/tests/verify_router.py +0 -0
|
@@ -2,6 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented here.
|
|
4
4
|
|
|
5
|
+
## [0.13.0] - 2026-05-02
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
- **Robust Header Infrastructure**:
|
|
9
|
+
- Refactored `Headers` class to use `collections.UserDict` for better standard library compatibility.
|
|
10
|
+
- Implemented full case-insensitivity for all header operations (get, set, delete).
|
|
11
|
+
- Added native support for multi-value headers via `headers.add(key, value)` and `headers.getlist(key)`.
|
|
12
|
+
- **WSGI Adapter Enhancements**:
|
|
13
|
+
- Refactored `WSGIAdapter` to correctly handle multi-value headers.
|
|
14
|
+
- Integrated application-level error handling (including custom 404/500 handlers) into the WSGI layer.
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
- **JWT & Cookie Security**:
|
|
18
|
+
- Updated `Response.delete_cookie()` signature to accept `secure`, `httponly`, and `samesite` arguments, fixing crashes in JWT logout flows.
|
|
19
|
+
- Improved cookie attribute handling to ensure consistency between Python and Rust layers.
|
|
20
|
+
- **Response Unwrapping**: Fixed a bug where returning a `Response` object inside another `Response` (common in error handlers using `render_template`) resulted in the object's string representation being sent as the body.
|
|
21
|
+
- **FFI Stability**: Standardized the Python-to-Rust response conversion to ensure reliable header serialization.
|
|
22
|
+
|
|
5
23
|
## [0.12.0] - 2026-04-27
|
|
6
24
|
|
|
7
25
|
### Added
|
|
@@ -438,7 +438,7 @@ checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb"
|
|
|
438
438
|
|
|
439
439
|
[[package]]
|
|
440
440
|
name = "bustapi_core"
|
|
441
|
-
version = "0.
|
|
441
|
+
version = "0.13.0"
|
|
442
442
|
dependencies = [
|
|
443
443
|
"actix-files",
|
|
444
444
|
"actix-http",
|
|
@@ -488,9 +488,9 @@ checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33"
|
|
|
488
488
|
|
|
489
489
|
[[package]]
|
|
490
490
|
name = "bytestring"
|
|
491
|
-
version = "1.5.
|
|
491
|
+
version = "1.5.1"
|
|
492
492
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
493
|
-
checksum = "
|
|
493
|
+
checksum = "86566c496f2f47d9b8147a4c8b02ffdb69c919fe0c2b2e7195d22cbba0e635c9"
|
|
494
494
|
dependencies = [
|
|
495
495
|
"bytes",
|
|
496
496
|
]
|
|
@@ -1262,9 +1262,9 @@ dependencies = [
|
|
|
1262
1262
|
|
|
1263
1263
|
[[package]]
|
|
1264
1264
|
name = "idna_adapter"
|
|
1265
|
-
version = "1.2.
|
|
1265
|
+
version = "1.2.2"
|
|
1266
1266
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1267
|
-
checksum = "
|
|
1267
|
+
checksum = "cb68373c0d6620ef8105e855e7745e18b0d00d3bdb07fb532e434244cdb9a714"
|
|
1268
1268
|
dependencies = [
|
|
1269
1269
|
"icu_normalizer",
|
|
1270
1270
|
"icu_properties",
|
|
@@ -1344,10 +1344,12 @@ dependencies = [
|
|
|
1344
1344
|
|
|
1345
1345
|
[[package]]
|
|
1346
1346
|
name = "js-sys"
|
|
1347
|
-
version = "0.3.
|
|
1347
|
+
version = "0.3.97"
|
|
1348
1348
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1349
|
-
checksum = "
|
|
1349
|
+
checksum = "a1840c94c045fbcf8ba2812c95db44499f7c64910a912551aaaa541decebcacf"
|
|
1350
1350
|
dependencies = [
|
|
1351
|
+
"cfg-if",
|
|
1352
|
+
"futures-util",
|
|
1351
1353
|
"once_cell",
|
|
1352
1354
|
"wasm-bindgen",
|
|
1353
1355
|
]
|
|
@@ -2487,9 +2489,9 @@ dependencies = [
|
|
|
2487
2489
|
|
|
2488
2490
|
[[package]]
|
|
2489
2491
|
name = "wasm-bindgen"
|
|
2490
|
-
version = "0.2.
|
|
2492
|
+
version = "0.2.120"
|
|
2491
2493
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2492
|
-
checksum = "
|
|
2494
|
+
checksum = "df52b6d9b87e0c74c9edfa1eb2d9bf85e5d63515474513aa50fa181b3c4f5db1"
|
|
2493
2495
|
dependencies = [
|
|
2494
2496
|
"cfg-if",
|
|
2495
2497
|
"once_cell",
|
|
@@ -2500,9 +2502,9 @@ dependencies = [
|
|
|
2500
2502
|
|
|
2501
2503
|
[[package]]
|
|
2502
2504
|
name = "wasm-bindgen-macro"
|
|
2503
|
-
version = "0.2.
|
|
2505
|
+
version = "0.2.120"
|
|
2504
2506
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2505
|
-
checksum = "
|
|
2507
|
+
checksum = "78b1041f495fb322e64aca85f5756b2172e35cd459376e67f2a6c9dffcedb103"
|
|
2506
2508
|
dependencies = [
|
|
2507
2509
|
"quote",
|
|
2508
2510
|
"wasm-bindgen-macro-support",
|
|
@@ -2510,9 +2512,9 @@ dependencies = [
|
|
|
2510
2512
|
|
|
2511
2513
|
[[package]]
|
|
2512
2514
|
name = "wasm-bindgen-macro-support"
|
|
2513
|
-
version = "0.2.
|
|
2515
|
+
version = "0.2.120"
|
|
2514
2516
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2515
|
-
checksum = "
|
|
2517
|
+
checksum = "9dcd0ff20416988a18ac686d4d4d0f6aae9ebf08a389ff5d29012b05af2a1b41"
|
|
2516
2518
|
dependencies = [
|
|
2517
2519
|
"bumpalo",
|
|
2518
2520
|
"proc-macro2",
|
|
@@ -2523,9 +2525,9 @@ dependencies = [
|
|
|
2523
2525
|
|
|
2524
2526
|
[[package]]
|
|
2525
2527
|
name = "wasm-bindgen-shared"
|
|
2526
|
-
version = "0.2.
|
|
2528
|
+
version = "0.2.120"
|
|
2527
2529
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2528
|
-
checksum = "
|
|
2530
|
+
checksum = "49757b3c82ebf16c57d69365a142940b384176c24df52a087fb748e2085359ea"
|
|
2529
2531
|
dependencies = [
|
|
2530
2532
|
"unicode-ident",
|
|
2531
2533
|
]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: bustapi
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.13.0
|
|
4
4
|
Classifier: Development Status :: 3 - Alpha
|
|
5
5
|
Classifier: Intended Audience :: Developers
|
|
6
6
|
Classifier: License :: OSI Approved :: MIT License
|
|
@@ -61,10 +61,10 @@ Author-email: GrandpaEJ <>
|
|
|
61
61
|
License: MIT
|
|
62
62
|
Requires-Python: >=3.10
|
|
63
63
|
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
64
|
-
Project-URL: Documentation, https://
|
|
65
|
-
Project-URL: Homepage, https://github.com/
|
|
66
|
-
Project-URL: Issues, https://github.com/
|
|
67
|
-
Project-URL: Repository, https://github.com/
|
|
64
|
+
Project-URL: Documentation, https://RUSTxPY.github.io/BustAPI/
|
|
65
|
+
Project-URL: Homepage, https://github.com/RUSTxPY/BustAPI
|
|
66
|
+
Project-URL: Issues, https://github.com/RUSTxPY/BustAPI/issues
|
|
67
|
+
Project-URL: Repository, https://github.com/RUSTxPY/BustAPI.git
|
|
68
68
|
|
|
69
69
|
# BustAPI — High-Performance Python Web Framework
|
|
70
70
|
|
|
@@ -107,6 +107,7 @@ Under the hood, BustAPI runs on [Actix-Web](https://actix.rs/) — consistently
|
|
|
107
107
|
- 🦀 **Rust-powered** — Zero-copy JSON, mimalloc allocator, Actix-Web
|
|
108
108
|
- 🐍 **Pure Python API** — No Rust knowledge required
|
|
109
109
|
- 🔒 **Security built-in** — JWT, sessions, CSRF, rate limiting
|
|
110
|
+
- 🛡️ **Robust Header System** — Case-insensitive, multi-value support, high-performance cookie parsing
|
|
110
111
|
- 📦 **Zero config** — `pip install bustapi` and you're ready
|
|
111
112
|
- 🔥 **Hot reload** — Rust-native file watcher for instant restarts
|
|
112
113
|
|
|
@@ -510,13 +511,13 @@ CMD ["python", "app.py"]
|
|
|
510
511
|
|
|
511
512
|
## 📖 Documentation
|
|
512
513
|
|
|
513
|
-
📚 **[Full Documentation](https://
|
|
514
|
+
📚 **[Full Documentation](https://RUSTxPY.github.io/BustAPI/)**
|
|
514
515
|
|
|
515
|
-
- [Getting Started](https://
|
|
516
|
-
- [Routing Guide](https://
|
|
517
|
-
- [JWT Authentication](https://
|
|
518
|
-
- [WebSocket Guide](https://
|
|
519
|
-
- [API Reference](https://
|
|
516
|
+
- [Getting Started](https://RUSTxPY.github.io/BustAPI/quickstart/)
|
|
517
|
+
- [Routing Guide](https://RUSTxPY.github.io/BustAPI/user-guide/routing/)
|
|
518
|
+
- [JWT Authentication](https://RUSTxPY.github.io/BustAPI/user-guide/jwt/)
|
|
519
|
+
- [WebSocket Guide](https://RUSTxPY.github.io/BustAPI/user-guide/websocket/)
|
|
520
|
+
- [API Reference](https://RUSTxPY.github.io/BustAPI/api-reference/)
|
|
520
521
|
|
|
521
522
|
---
|
|
522
523
|
|
|
@@ -532,8 +533,8 @@ We welcome contributions! Here's how:
|
|
|
532
533
|
|
|
533
534
|
Found a bug? Have a feature request?
|
|
534
535
|
|
|
535
|
-
- [Open an Issue](https://github.com/
|
|
536
|
-
- [Start a Discussion](https://github.com/
|
|
536
|
+
- [Open an Issue](https://github.com/RUSTxPY/BustAPI/issues)
|
|
537
|
+
- [Start a Discussion](https://github.com/RUSTxPY/BustAPI/discussions)
|
|
537
538
|
|
|
538
539
|
---
|
|
539
540
|
|
|
@@ -39,6 +39,7 @@ Under the hood, BustAPI runs on [Actix-Web](https://actix.rs/) — consistently
|
|
|
39
39
|
- 🦀 **Rust-powered** — Zero-copy JSON, mimalloc allocator, Actix-Web
|
|
40
40
|
- 🐍 **Pure Python API** — No Rust knowledge required
|
|
41
41
|
- 🔒 **Security built-in** — JWT, sessions, CSRF, rate limiting
|
|
42
|
+
- 🛡️ **Robust Header System** — Case-insensitive, multi-value support, high-performance cookie parsing
|
|
42
43
|
- 📦 **Zero config** — `pip install bustapi` and you're ready
|
|
43
44
|
- 🔥 **Hot reload** — Rust-native file watcher for instant restarts
|
|
44
45
|
|
|
@@ -442,13 +443,13 @@ CMD ["python", "app.py"]
|
|
|
442
443
|
|
|
443
444
|
## 📖 Documentation
|
|
444
445
|
|
|
445
|
-
📚 **[Full Documentation](https://
|
|
446
|
+
📚 **[Full Documentation](https://RUSTxPY.github.io/BustAPI/)**
|
|
446
447
|
|
|
447
|
-
- [Getting Started](https://
|
|
448
|
-
- [Routing Guide](https://
|
|
449
|
-
- [JWT Authentication](https://
|
|
450
|
-
- [WebSocket Guide](https://
|
|
451
|
-
- [API Reference](https://
|
|
448
|
+
- [Getting Started](https://RUSTxPY.github.io/BustAPI/quickstart/)
|
|
449
|
+
- [Routing Guide](https://RUSTxPY.github.io/BustAPI/user-guide/routing/)
|
|
450
|
+
- [JWT Authentication](https://RUSTxPY.github.io/BustAPI/user-guide/jwt/)
|
|
451
|
+
- [WebSocket Guide](https://RUSTxPY.github.io/BustAPI/user-guide/websocket/)
|
|
452
|
+
- [API Reference](https://RUSTxPY.github.io/BustAPI/api-reference/)
|
|
452
453
|
|
|
453
454
|
---
|
|
454
455
|
|
|
@@ -464,8 +465,8 @@ We welcome contributions! Here's how:
|
|
|
464
465
|
|
|
465
466
|
Found a bug? Have a feature request?
|
|
466
467
|
|
|
467
|
-
- [Open an Issue](https://github.com/
|
|
468
|
-
- [Start a Discussion](https://github.com/
|
|
468
|
+
- [Open an Issue](https://github.com/RUSTxPY/BustAPI/issues)
|
|
469
|
+
- [Start a Discussion](https://github.com/RUSTxPY/BustAPI/discussions)
|
|
469
470
|
|
|
470
471
|
---
|
|
471
472
|
|
|
@@ -2,6 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented here.
|
|
4
4
|
|
|
5
|
+
## [0.13.0] - 2026-05-02
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
- **Robust Header Infrastructure**:
|
|
9
|
+
- Refactored `Headers` class to use `collections.UserDict` for better standard library compatibility.
|
|
10
|
+
- Implemented full case-insensitivity for all header operations (get, set, delete).
|
|
11
|
+
- Added native support for multi-value headers via `headers.add(key, value)` and `headers.getlist(key)`.
|
|
12
|
+
- **WSGI Adapter Enhancements**:
|
|
13
|
+
- Refactored `WSGIAdapter` to correctly handle multi-value headers.
|
|
14
|
+
- Integrated application-level error handling (including custom 404/500 handlers) into the WSGI layer.
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
- **JWT & Cookie Security**:
|
|
18
|
+
- Updated `Response.delete_cookie()` signature to accept `secure`, `httponly`, and `samesite` arguments, fixing crashes in JWT logout flows.
|
|
19
|
+
- Improved cookie attribute handling to ensure consistency between Python and Rust layers.
|
|
20
|
+
- **Response Unwrapping**: Fixed a bug where returning a `Response` object inside another `Response` (common in error handlers using `render_template`) resulted in the object's string representation being sent as the body.
|
|
21
|
+
- **FFI Stability**: Standardized the Python-to-Rust response conversion to ensure reliable header serialization.
|
|
22
|
+
|
|
5
23
|
## [0.12.0] - 2026-04-27
|
|
6
24
|
|
|
7
25
|
### Added
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# BustAPI Complete API Reference
|
|
2
2
|
|
|
3
|
-
> **Version:** 0.
|
|
4
|
-
> **Last Updated:**
|
|
3
|
+
> **Version:** 0.13.0
|
|
4
|
+
> **Last Updated:** 2026-05-02
|
|
5
5
|
|
|
6
6
|
## Table of Contents
|
|
7
7
|
|
|
@@ -356,8 +356,29 @@ response.data # Response body as bytes
|
|
|
356
356
|
```python
|
|
357
357
|
response.set_data(data) # Set response data
|
|
358
358
|
response.get_data(as_text=False) # Get response data
|
|
359
|
-
|
|
360
|
-
|
|
359
|
+
|
|
360
|
+
# Set a cookie
|
|
361
|
+
response.set_cookie(
|
|
362
|
+
key: str,
|
|
363
|
+
value: str = '',
|
|
364
|
+
max_age: Optional[int] = None,
|
|
365
|
+
expires: Optional[Union[datetime, float]] = None,
|
|
366
|
+
path: str = '/',
|
|
367
|
+
domain: Optional[str] = None,
|
|
368
|
+
secure: bool = False,
|
|
369
|
+
httponly: bool = False,
|
|
370
|
+
samesite: Optional[str] = 'Lax'
|
|
371
|
+
)
|
|
372
|
+
|
|
373
|
+
# Delete a cookie
|
|
374
|
+
response.delete_cookie(
|
|
375
|
+
key: str,
|
|
376
|
+
path: str = '/',
|
|
377
|
+
domain: Optional[str] = None,
|
|
378
|
+
secure: bool = False,
|
|
379
|
+
httponly: bool = False,
|
|
380
|
+
samesite: Optional[str] = 'Lax'
|
|
381
|
+
)
|
|
361
382
|
```
|
|
362
383
|
|
|
363
384
|
**Example:**
|
|
@@ -371,6 +392,30 @@ def custom_response():
|
|
|
371
392
|
return resp
|
|
372
393
|
```
|
|
373
394
|
|
|
395
|
+
### Headers Object
|
|
396
|
+
|
|
397
|
+
The `response.headers` object provides a case-insensitive dictionary-like interface for managing HTTP headers.
|
|
398
|
+
|
|
399
|
+
#### Methods
|
|
400
|
+
|
|
401
|
+
- `get(key, default=None)`: Get the first value for a header (case-insensitive).
|
|
402
|
+
- `add(key, value)`: Add a value to a header, preserving existing values (multi-value support).
|
|
403
|
+
- `getlist(key)`: Get all values for a header as a list.
|
|
404
|
+
- `setlist(key, values)`: Set multiple values for a header.
|
|
405
|
+
- `items()`: Get all header key-value pairs as a list of tuples.
|
|
406
|
+
|
|
407
|
+
**Example:**
|
|
408
|
+
|
|
409
|
+
```python
|
|
410
|
+
resp.headers['Content-Type'] = 'application/json'
|
|
411
|
+
resp.headers.add('Link', '<https://example.com>; rel="next"')
|
|
412
|
+
resp.headers.add('Link', '<https://example.com>; rel="prev"')
|
|
413
|
+
|
|
414
|
+
links = resp.headers.getlist('Link') # ['...', '...']
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
---
|
|
418
|
+
|
|
374
419
|
#### Response Helper Functions
|
|
375
420
|
|
|
376
421
|
##### `jsonify(*args, **kwargs)`
|
|
@@ -1076,14 +1121,30 @@ def internal_error(error):
|
|
|
1076
1121
|
|
|
1077
1122
|
#### Exception Handlers
|
|
1078
1123
|
|
|
1079
|
-
|
|
1124
|
+
````python
|
|
1080
1125
|
class ValidationError(Exception):
|
|
1081
1126
|
pass
|
|
1082
1127
|
|
|
1083
1128
|
@app.errorhandler(ValidationError)
|
|
1084
1129
|
def handle_validation_error(error):
|
|
1085
1130
|
return {'error': str(error), 'type': 'validation_error'}, 400
|
|
1086
|
-
|
|
1131
|
+
|
|
1132
|
+
#### Catch-All Handler
|
|
1133
|
+
|
|
1134
|
+
Handle all otherwise unhandled exceptions:
|
|
1135
|
+
|
|
1136
|
+
```python
|
|
1137
|
+
@app.errorhandler(Exception)
|
|
1138
|
+
def handle_exception(e):
|
|
1139
|
+
# Pass through HTTP errors
|
|
1140
|
+
if hasattr(e, "get_response"):
|
|
1141
|
+
return e.get_response()
|
|
1142
|
+
|
|
1143
|
+
# Generic error for everything else
|
|
1144
|
+
return {"error": "Something went wrong"}, 500
|
|
1145
|
+
````
|
|
1146
|
+
|
|
1147
|
+
````
|
|
1087
1148
|
|
|
1088
1149
|
### Using `abort()`
|
|
1089
1150
|
|
|
@@ -1102,7 +1163,7 @@ def admin():
|
|
|
1102
1163
|
if not is_admin():
|
|
1103
1164
|
abort(403, 'Admin access required')
|
|
1104
1165
|
return {'message': 'Admin panel'}
|
|
1105
|
-
|
|
1166
|
+
````
|
|
1106
1167
|
|
|
1107
1168
|
### Complete Error Handling Example
|
|
1108
1169
|
|
|
@@ -1546,11 +1607,11 @@ app.run(
|
|
|
1546
1607
|
```python
|
|
1547
1608
|
import bustapi
|
|
1548
1609
|
|
|
1549
|
-
print(bustapi.__version__) # '0.
|
|
1550
|
-
print(bustapi.get_version()) # '0.
|
|
1610
|
+
print(bustapi.__version__) # '0.13.0'
|
|
1611
|
+
print(bustapi.get_version()) # '0.13.0'
|
|
1551
1612
|
print(bustapi.get_debug_info()) # Detailed version info
|
|
1552
1613
|
```
|
|
1553
1614
|
|
|
1554
1615
|
---
|
|
1555
1616
|
|
|
1556
|
-
_This documentation covers BustAPI version 0.
|
|
1617
|
+
_This documentation covers BustAPI version 0.13.0. For the latest updates, visit the [official documentation](https://rustxpy.github.io/BustAPI/)._
|
|
@@ -12,6 +12,15 @@ The `examples/` directory in the repository contains many complete scripts demon
|
|
|
12
12
|
- **03_async.py**: Using `async def` for non-blocking routes.
|
|
13
13
|
- **04_request_data.py**: accessing query args and form data.
|
|
14
14
|
|
|
15
|
+
## Security & Authentication
|
|
16
|
+
|
|
17
|
+
Learn how to protect your application.
|
|
18
|
+
|
|
19
|
+
- **17_jwt_auth.py**: Standard JWT authentication using the Authorization header.
|
|
20
|
+
- **18_jwt_cookies.py**: Secure JWT implementation using HttpOnly cookies.
|
|
21
|
+
- **11_security_demo.py**: Implementing security headers.
|
|
22
|
+
- **10_rate_limit_demo.py**: Using the built-in rate limiter to prevent abuse.
|
|
23
|
+
|
|
15
24
|
## Data & Validation
|
|
16
25
|
|
|
17
26
|
Learn how to robustly handle input.
|
|
@@ -27,8 +36,6 @@ For production-grade applications.
|
|
|
27
36
|
|
|
28
37
|
- **06_blueprints.py**: Organizing your app into modules.
|
|
29
38
|
- **14_middleware.py**: Custom request/response hooks.
|
|
30
|
-
- **10_rate_limit_demo.py**: Using the built-in rate limiter to prevent abuse.
|
|
31
|
-
- **11_security_demo.py**: Implementing security headers.
|
|
32
39
|
|
|
33
40
|
## Database & Templates
|
|
34
41
|
|
|
@@ -44,7 +44,8 @@ if __name__ == "__main__":
|
|
|
44
44
|
- **Multiprocessing** - `workers=4` for parallel request handling on Linux
|
|
45
45
|
- **JWT Authentication** - Built-in token-based auth
|
|
46
46
|
- **Templates** - Jinja2 template rendering
|
|
47
|
-
-
|
|
47
|
+
- **Blueprints** - Modular app organization
|
|
48
|
+
- **Auto-Documentation** - Instant OpenAPI/Swagger & ReDoc UI
|
|
48
49
|
|
|
49
50
|
---
|
|
50
51
|
|
|
@@ -79,3 +80,4 @@ Supports Python **3.10 - 3.14** on Linux, macOS, and Windows.
|
|
|
79
80
|
- [Turbo Routes](user-guide/turbo-routes.md) - Maximum performance
|
|
80
81
|
- [Multiprocessing](user-guide/multiprocessing.md) - Scale to 100k+ RPS
|
|
81
82
|
- [JWT Auth](user-guide/jwt.md) - Secure your API
|
|
83
|
+
- [Auto-Documentation](user-guide/documentation.md) - Swagger & ReDoc
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# Auto-Documentation
|
|
2
|
+
|
|
3
|
+
BustAPI provides automatic OpenAPI (Swagger) and ReDoc documentation for your application via the `BustAPIDocs` extension. It extracts information from route signatures, docstrings, and parameter validators.
|
|
4
|
+
|
|
5
|
+
## Comparison with FastAPI
|
|
6
|
+
|
|
7
|
+
BustAPI's documentation system is designed to be familiar to FastAPI users while leveraging BustAPI's high-performance Rust backend.
|
|
8
|
+
|
|
9
|
+
| Feature | FastAPI | BustAPI |
|
|
10
|
+
|:---|:---|:---|
|
|
11
|
+
| **Engine** | Starlette / Pydantic | **Actix-web / Rust-core** |
|
|
12
|
+
| **Setup** | Automatic in `FastAPI()` | Manual via `BustAPIDocs(app)` |
|
|
13
|
+
| **Parameters** | `Query()`, `Path()`, `Body()` | `Query()`, `Path()`, `Body()` |
|
|
14
|
+
| **Validation** | Pydantic Models | `Struct` or `dict` schemas |
|
|
15
|
+
| **UI Endpoints** | `/docs`, `/redoc` | `/docs`, `/redoc` |
|
|
16
|
+
| **Metadata** | `tags`, `summary`, `description` | `tags`, `summary`, `description` |
|
|
17
|
+
| **Performance** | High (Python-based) | **Extreme (Rust-core parsing)** |
|
|
18
|
+
|
|
19
|
+
## Basic Setup
|
|
20
|
+
|
|
21
|
+
Initialize the `BustAPIDocs` extension with your application to enable the documentation endpoints.
|
|
22
|
+
|
|
23
|
+
```python
|
|
24
|
+
from bustapi import BustAPI, BustAPIDocs
|
|
25
|
+
|
|
26
|
+
app = BustAPI()
|
|
27
|
+
|
|
28
|
+
# Configure auto-documentation
|
|
29
|
+
docs = BustAPIDocs(
|
|
30
|
+
app,
|
|
31
|
+
title="My Store API",
|
|
32
|
+
version="1.0.0",
|
|
33
|
+
description="API for managing items and users",
|
|
34
|
+
docs_url="/docs", # Swagger UI path
|
|
35
|
+
redoc_url="/redoc", # ReDoc path
|
|
36
|
+
openapi_url="/openapi.json"
|
|
37
|
+
)
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Documenting Parameters
|
|
41
|
+
|
|
42
|
+
BustAPI automatically documents parameters defined in your route handlers using `Path`, `Query`, and `Body` validators.
|
|
43
|
+
|
|
44
|
+
### Query Parameters
|
|
45
|
+
|
|
46
|
+
Use `Query()` to add constraints and metadata to query strings.
|
|
47
|
+
|
|
48
|
+
```python
|
|
49
|
+
from bustapi import Query
|
|
50
|
+
|
|
51
|
+
@app.route("/search")
|
|
52
|
+
def search(
|
|
53
|
+
q: str = Query(..., min_length=3, description="Search query"),
|
|
54
|
+
page: int = Query(1, ge=1, description="Page number")
|
|
55
|
+
):
|
|
56
|
+
return {"q": q, "page": page}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Path Parameters
|
|
60
|
+
|
|
61
|
+
`Path()` works similarly for URL path segments.
|
|
62
|
+
|
|
63
|
+
```python
|
|
64
|
+
from bustapi import Path
|
|
65
|
+
|
|
66
|
+
@app.route("/items/<int:item_id>")
|
|
67
|
+
def get_item(item_id: int = Path(..., ge=1, title="Item ID")):
|
|
68
|
+
return {"id": item_id}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Request Bodies
|
|
72
|
+
|
|
73
|
+
The `Body()` validator documents JSON request bodies. You can provide a `schema` dictionary to define fields and their constraints.
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
from bustapi import Body
|
|
77
|
+
|
|
78
|
+
@app.route("/items", methods=["POST"])
|
|
79
|
+
def create_item(
|
|
80
|
+
item: dict = Body(..., schema={
|
|
81
|
+
"name": {"type": "str", "min_length": 1, "description": "Item name"},
|
|
82
|
+
"price": {"type": "float", "gt": 0, "description": "Price in USD"},
|
|
83
|
+
"tags": {"type": "list", "required": False}
|
|
84
|
+
})
|
|
85
|
+
):
|
|
86
|
+
return {"created": item}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Route Metadata
|
|
90
|
+
|
|
91
|
+
You can further customize documentation for specific routes using decorator arguments:
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
@app.route(
|
|
95
|
+
"/protected",
|
|
96
|
+
methods=["GET"],
|
|
97
|
+
tags=["Security"],
|
|
98
|
+
summary="Access protected resource",
|
|
99
|
+
description="This endpoint requires an active session.",
|
|
100
|
+
deprecated=True
|
|
101
|
+
)
|
|
102
|
+
def protected_route():
|
|
103
|
+
return {"status": "ok"}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Custom Responses
|
|
107
|
+
|
|
108
|
+
Define specific response codes and their descriptions:
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
@app.route(
|
|
112
|
+
"/items/<int:id>",
|
|
113
|
+
responses={
|
|
114
|
+
200: {"description": "Item found"},
|
|
115
|
+
404: {"description": "Item not in database"}
|
|
116
|
+
}
|
|
117
|
+
)
|
|
118
|
+
def get_item_with_docs(id):
|
|
119
|
+
return {"id": id}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Response Models
|
|
123
|
+
|
|
124
|
+
If you use `Struct` from `bustapi.safe.types`, you can specify it as a `response_model` to automatically generate a reusable schema in the documentation.
|
|
125
|
+
|
|
126
|
+
```python
|
|
127
|
+
from bustapi.safe.types import Struct
|
|
128
|
+
|
|
129
|
+
class Item(Struct):
|
|
130
|
+
id: int
|
|
131
|
+
name: str
|
|
132
|
+
|
|
133
|
+
@app.route("/item", response_model=Item)
|
|
134
|
+
def get_item_model():
|
|
135
|
+
return Item(id=1, name="Tool")
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## UI Endpoints
|
|
139
|
+
|
|
140
|
+
Once initialized, your documentation is accessible at:
|
|
141
|
+
|
|
142
|
+
- **Swagger UI**: `http://127.0.0.1:5000/docs` (interactive "Try it out" support)
|
|
143
|
+
- **ReDoc**: `http://127.0.0.1:5000/redoc` (clean, readable layout)
|
|
144
|
+
- **OpenAPI JSON**: `http://127.0.0.1:5000/openapi.json` (raw specification)
|
|
@@ -37,3 +37,33 @@ def admin():
|
|
|
37
37
|
abort(403, description="Admins only!")
|
|
38
38
|
return "Welcome Admin"
|
|
39
39
|
```
|
|
40
|
+
|
|
41
|
+
## Catch-All Error Handler
|
|
42
|
+
|
|
43
|
+
To handle any unhandled exception (the "else" block), you can register a handler for the base `Exception` class.
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
@app.errorhandler(Exception)
|
|
47
|
+
def handle_unexpected_error(e):
|
|
48
|
+
# Log the error
|
|
49
|
+
app.logger.error(f"Unexpected error: {e}")
|
|
50
|
+
|
|
51
|
+
# If it's already an HTTP error, let it handle itself
|
|
52
|
+
if hasattr(e, "get_response"):
|
|
53
|
+
return e.get_response()
|
|
54
|
+
|
|
55
|
+
return {"error": "An internal error occurred"}, 500
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Custom Exceptions
|
|
59
|
+
|
|
60
|
+
You can create your own exception classes and register handlers for them.
|
|
61
|
+
|
|
62
|
+
```python
|
|
63
|
+
class PaymentRequired(Exception):
|
|
64
|
+
pass
|
|
65
|
+
|
|
66
|
+
@app.errorhandler(PaymentRequired)
|
|
67
|
+
def handle_payment_required(e):
|
|
68
|
+
return "Please pay to continue", 402
|
|
69
|
+
```
|