bustapi 0.14.2__tar.gz → 0.14.3__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.14.2 → bustapi-0.14.3}/CHANGELOG.md +6 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/Cargo.lock +3 -3
- {bustapi-0.14.2 → bustapi-0.14.3}/Cargo.toml +1 -1
- {bustapi-0.14.2 → bustapi-0.14.3}/PKG-INFO +1 -1
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/changelog.md +6 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/pyproject.toml +1 -1
- {bustapi-0.14.2 → bustapi-0.14.3}/python/bustapi/__init__.py +1 -1
- {bustapi-0.14.2 → bustapi-0.14.3}/python/bustapi/websocket.py +23 -35
- {bustapi-0.14.2 → bustapi-0.14.3}/src/websocket/session.rs +3 -1
- {bustapi-0.14.2 → bustapi-0.14.3}/- +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/.github/FUNDING.yml +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/.github/workflows/ci-multiplatform.yml +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/.github/workflows/ci.yml +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/.github/workflows/docs.yml +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/.github/workflows/manual-publish.yml +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/.gitignore +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/.python-version +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/AGENT_KNOWLEDGE.md +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/Dockerfile +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/LICENSE +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/README.md +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/benchmarks/CACHE_BENCHMARK.md +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/benchmarks/README.md +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/benchmarks/app.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/benchmarks/benchmark_all.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/benchmarks/benchmark_avg.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/benchmarks/benchmark_cache.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/benchmarks/benchmark_combined.png +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/benchmarks/bustapi.md +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/benchmarks/bustapi_bench.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/benchmarks/bustapi_internal.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/benchmarks/comparison_bench.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/benchmarks/comprehensive_benchmark.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/benchmarks/gen_graph.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/benchmarks/quick_bench.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/benchmarks/resource_bench.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/benchmarks/rps_comparison.png +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/benchmarks/run_comparison_auto.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/benchmarks/ws_benchmark.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/advanced/async.md +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/advanced/blueprints.md +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/advanced/dependency_injection.md +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/advanced/deployment.md +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/advanced/middleware.md +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/advanced/security.md +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/advanced/validation.md +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/api-reference.md +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/assets/logo.png +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/complete-api-reference.md +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/deployment-performance-guide.md +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/deployment.md +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/examples-guide.md +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/index.md +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/installation.md +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/overrides/.gitkeep +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/quickstart.md +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/release_track.md +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/site/advanced/async_support.html +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/site/advanced/blueprints.html +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/site/advanced/dependency_injection.html +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/site/advanced/middleware.html +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/site/advanced/validation.html +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/site/api/all.html +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/site/api/app.html +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/site/api/context.html +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/site/api/utilities.html +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/site/assets/logo.png +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/site/changelog.html +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/site/core_concepts/request_data.html +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/site/core_concepts/responses.html +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/site/core_concepts/routing.html +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/site/core_concepts/templates.html +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/site/examples/index.html +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/site/getting_started/index.html +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/site/getting_started/quickstart.html +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/site/index.html +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/site/script.js +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/site/style.css +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/stylesheets/extra.css +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/user-guide/authentication.md +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/user-guide/caching.md +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/user-guide/cli.md +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/user-guide/database.md +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/user-guide/documentation.md +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/user-guide/error_handling.md +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/user-guide/jwt.md +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/user-guide/logging.md +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/user-guide/multiprocessing.md +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/user-guide/request_data.md +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/user-guide/responses.md +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/user-guide/routing.md +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/user-guide/sessions.md +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/user-guide/static_files.md +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/user-guide/templates.md +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/user-guide/turbo-routes.md +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/user-guide/video-streaming.md +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/docs/websockets.md +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/examples/advanced/08_auto_docs.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/examples/advanced/12_test_modes.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/examples/advanced/13_error_handling.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/examples/advanced/14_middleware.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/examples/advanced/16_middleware_session.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/examples/advanced/20_file_uploads.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/examples/advanced/24_body_and_depends.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/examples/advanced/27_video_stream.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/examples/advanced/28_websocket.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/examples/advanced/29_turbo_websocket.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/examples/basics/01_hello_world.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/examples/basics/02_parameters.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/examples/basics/03_async.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/examples/basics/04_request_data.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/examples/basics/19_all_types.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/examples/database/07_database_raw.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/examples/database/10_database_sqlmodel.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/examples/routing/06_blueprints.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/examples/routing/09_complex_routing.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/examples/routing/21_path_validation.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/examples/routing/22_path_docs.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/examples/routing/23_query_validation.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/examples/routing/blueprint_with_jwt.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/examples/security/10_rate_limit_demo.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/examples/security/11_security_demo.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/examples/security/17_jwt_auth.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/examples/security/17_safe_features.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/examples/security/18_jwt_cookies.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/examples/security/18_safe_advanced.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/examples/security/18_session_login.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/examples/templates/05_templates.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/examples/templates/26_complex_template.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/examples/templates/templates/index.html +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/examples/turbo/cache_test.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/examples/turbo/fair_benchmark.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/examples/turbo/typed_turbo_example.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/examples/ws/app.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/examples/ws/templates/index.html +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/examples/ws/websockets_demo.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/examples/ws/ws_limit.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/mkdocs.yml +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/python/bustapi/app.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/python/bustapi/auth/__init__.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/python/bustapi/auth/csrf.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/python/bustapi/auth/decorators.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/python/bustapi/auth/login.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/python/bustapi/auth/password.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/python/bustapi/auth/tokens.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/python/bustapi/auth/user.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/python/bustapi/cli/__init__.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/python/bustapi/cli/main.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/python/bustapi/context.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/python/bustapi/core/__init__.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/python/bustapi/core/asgi.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/python/bustapi/core/exceptions.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/python/bustapi/core/helpers.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/python/bustapi/core/logging.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/python/bustapi/dependencies.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/python/bustapi/dispatch.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/python/bustapi/documentation/__init__.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/python/bustapi/documentation/generator.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/python/bustapi/extraction.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/python/bustapi/fastapi_compat.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/python/bustapi/hooks.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/python/bustapi/http/__init__.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/python/bustapi/http/request.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/python/bustapi/http/response.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/python/bustapi/jwt.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/python/bustapi/logging.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/python/bustapi/middleware.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/python/bustapi/multiprocess.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/python/bustapi/params.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/python/bustapi/py.typed +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/python/bustapi/responses.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/python/bustapi/routing/__init__.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/python/bustapi/routing/blueprints.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/python/bustapi/routing/decorators.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/python/bustapi/safe/__init__.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/python/bustapi/safe/concurrency.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/python/bustapi/safe/types.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/python/bustapi/security/__init__.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/python/bustapi/security/extension.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/python/bustapi/security/rate_limit.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/python/bustapi/server/__init__.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/python/bustapi/server/runner.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/python/bustapi/server/wsgi.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/python/bustapi/sessions.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/python/bustapi/templating/__init__.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/python/bustapi/templating/engine.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/python/bustapi/templating/mixin.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/python/bustapi/testing/__init__.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/python/bustapi/testing/client.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/python/bustapi/utils.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/run_all_examples.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/scratch/test_abort.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/scratch/test_headers.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/src/bindings/app.rs +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/src/bindings/converters.rs +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/src/bindings/handlers.rs +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/src/bindings/mod.rs +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/src/bindings/request.rs +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/src/bindings/typed_turbo.rs +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/src/bindings/websocket.rs +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/src/crypto.rs +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/src/jwt.rs +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/src/lib.rs +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/src/logger.rs +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/src/rate_limiter.rs +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/src/request/methods.rs +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/src/request/mod.rs +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/src/request/tests.rs +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/src/response/builders.rs +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/src/response/methods.rs +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/src/response/mod.rs +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/src/router/handlers.rs +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/src/router/matching.rs +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/src/router/middleware.rs +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/src/router/mod.rs +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/src/router/tests.rs +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/src/server/handlers.rs +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/src/server/mod.rs +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/src/server/startup.rs +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/src/server/stream.rs +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/src/static_files.rs +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/src/templating.rs +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/src/watcher.rs +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/src/websocket/config.rs +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/src/websocket/mod.rs +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/src/websocket/turbo.rs +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/static/style.css +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/templates/base.html +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/templates/complex.html +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/tests/docs_test_all.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/tests/docs_test_api_reference.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/tests/docs_test_installation.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/tests/docs_test_quickstart.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/tests/docs_test_simple.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/tests/test_050_features.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/tests/test_async_hooks.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/tests/test_async_login.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/tests/test_auth.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/tests/test_discussion_21.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/tests/test_discussion_22.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/tests/test_discussion_28.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/tests/test_examples.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/tests/test_hot_reload.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/tests/test_issue_18.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/tests/test_issue_23.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/tests/test_issue_24.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/tests/test_issue_29.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/tests/test_jwt.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/tests/test_jwt_cookies.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/tests/test_login_manager.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/tests/test_middleware.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/tests/test_multiprocess_stability.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/tests/test_new_examples.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/tests/test_orm_conflict.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/tests/test_path_standalone.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/tests/test_path_validation.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/tests/test_rate_limit_rust.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/tests/test_safe.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/tests/test_security_unit.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/tests/test_sessions.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/tests/test_zero_copy.py +0 -0
- {bustapi-0.14.2 → bustapi-0.14.3}/tests/verify_router.py +0 -0
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented here.
|
|
4
4
|
|
|
5
|
+
## [0.14.3] - 2026-06-19
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
- **WebSocket Handshake**: Fixed a bug where client-initiated close frames (e.g. `socket.close()` in JS) were not properly echoed back by the Rust backend to complete the WebSocket close handshake. `on_disconnect` and `on_binary` handlers are now fully thread-safe and trigger cleanly.
|
|
9
|
+
- **WebSocket Config**: Clarified the usage of `WebSocketConfig` instance for the `config` parameter in WebSocket routes.
|
|
10
|
+
|
|
5
11
|
## [0.14.2] - 2026-06-18
|
|
6
12
|
|
|
7
13
|
### Fixed
|
|
@@ -432,7 +432,7 @@ checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649"
|
|
|
432
432
|
|
|
433
433
|
[[package]]
|
|
434
434
|
name = "bustapi_core"
|
|
435
|
-
version = "0.14.
|
|
435
|
+
version = "0.14.3"
|
|
436
436
|
dependencies = [
|
|
437
437
|
"actix-files",
|
|
438
438
|
"actix-http",
|
|
@@ -476,9 +476,9 @@ dependencies = [
|
|
|
476
476
|
|
|
477
477
|
[[package]]
|
|
478
478
|
name = "bytes"
|
|
479
|
-
version = "1.
|
|
479
|
+
version = "1.12.0"
|
|
480
480
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
481
|
-
checksum = "
|
|
481
|
+
checksum = "8ae3f5d315924270530207e2a68396c3cc547f6dca3fbdca317cfb1a51edb593"
|
|
482
482
|
|
|
483
483
|
[[package]]
|
|
484
484
|
name = "bytestring"
|
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented here.
|
|
4
4
|
|
|
5
|
+
## [0.14.3] - 2026-06-19
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
- **WebSocket Handshake**: Fixed a bug where client-initiated close frames (e.g. `socket.close()` in JS) were not properly echoed back by the Rust backend to complete the WebSocket close handshake. `on_disconnect` and `on_binary` handlers are now fully thread-safe and trigger cleanly.
|
|
9
|
+
- **WebSocket Config**: Clarified the usage of `WebSocketConfig` instance for the `config` parameter in WebSocket routes.
|
|
10
|
+
|
|
5
11
|
## [0.14.2] - 2026-06-18
|
|
6
12
|
|
|
7
13
|
### Fixed
|
|
@@ -197,61 +197,49 @@ class WebSocketHandler:
|
|
|
197
197
|
if hasattr(task, "add_done_callback"):
|
|
198
198
|
task.add_done_callback(_task_done_callback)
|
|
199
199
|
|
|
200
|
+
def _get_loop(self, session_id: int):
|
|
201
|
+
"""Find the asyncio loop associated with a session."""
|
|
202
|
+
if hasattr(self, "_background_loop") and self._background_loop:
|
|
203
|
+
return self._background_loop
|
|
204
|
+
task = self._tasks.get(session_id)
|
|
205
|
+
if task:
|
|
206
|
+
try:
|
|
207
|
+
return task.get_loop()
|
|
208
|
+
except Exception:
|
|
209
|
+
pass
|
|
210
|
+
return None
|
|
211
|
+
|
|
200
212
|
def on_message(self, session_id: int, message: str) -> None:
|
|
201
213
|
"""Called when a text message is received."""
|
|
202
214
|
if session_id in self._connections:
|
|
203
215
|
ws = self._connections[session_id]
|
|
204
|
-
|
|
205
|
-
# than the WebSocket's loop (Background thread), we must use thread-safe scheduling.
|
|
206
|
-
# We need to find the loop associated with this WebSocket's handler.
|
|
207
|
-
loop = None
|
|
208
|
-
if hasattr(self, "_background_loop") and self._background_loop:
|
|
209
|
-
loop = self._background_loop
|
|
210
|
-
else:
|
|
211
|
-
# Fallback: try to get loop from registered task?
|
|
212
|
-
pass
|
|
213
|
-
|
|
216
|
+
loop = self._get_loop(session_id)
|
|
214
217
|
if loop:
|
|
215
218
|
loop.call_soon_threadsafe(ws._receive_message, message)
|
|
216
219
|
else:
|
|
217
|
-
# If no specific background loop, imply we are reusing the main loop?
|
|
218
|
-
# But if we are in Actix thread, main loop might be running in main thread.
|
|
219
|
-
# call_soon_threadsafe is safe to call from any thread to target loop.
|
|
220
|
-
# However, if we don't have 'loop' var ...
|
|
221
|
-
# ws._messages is bound to a loop. We should get it.
|
|
222
|
-
# asyncio.Queue doesn't expose public ._loop, but we can try to guess.
|
|
223
|
-
# Actually, check self._tasks[session_id].get_loop() if available py3.7+
|
|
224
|
-
task = self._tasks.get(session_id)
|
|
225
|
-
if task:
|
|
226
|
-
try:
|
|
227
|
-
loop = task.get_loop()
|
|
228
|
-
loop.call_soon_threadsafe(ws._receive_message, message)
|
|
229
|
-
return
|
|
230
|
-
except:
|
|
231
|
-
pass
|
|
232
|
-
|
|
233
|
-
# Fallback to direct call if we can't find loop (risk of race)
|
|
234
220
|
ws._receive_message(message)
|
|
235
221
|
|
|
236
|
-
return None
|
|
237
|
-
|
|
238
222
|
def on_binary(self, session_id: int, data: bytes) -> None:
|
|
239
223
|
"""Called when binary data is received."""
|
|
240
224
|
if session_id in self._connections:
|
|
241
225
|
ws = self._connections[session_id]
|
|
242
|
-
# Convert if necessary, but data should come as bytes/list from bindings
|
|
243
|
-
# If bindings use Vec<u8> -> list[int] in Python usually?
|
|
244
|
-
# Or bytes?
|
|
245
|
-
# Let's assume bytes for now or cast.
|
|
246
226
|
if isinstance(data, list):
|
|
247
227
|
data = bytes(data)
|
|
248
|
-
|
|
228
|
+
loop = self._get_loop(session_id)
|
|
229
|
+
if loop:
|
|
230
|
+
loop.call_soon_threadsafe(ws._receive_message, data)
|
|
231
|
+
else:
|
|
232
|
+
ws._receive_message(data)
|
|
249
233
|
|
|
250
234
|
def on_disconnect(self, session_id: int, reason: Optional[str] = None) -> None:
|
|
251
235
|
"""Called when a client disconnects."""
|
|
252
236
|
if session_id in self._connections:
|
|
253
237
|
ws = self._connections[session_id]
|
|
254
|
-
|
|
238
|
+
loop = self._get_loop(session_id)
|
|
239
|
+
if loop:
|
|
240
|
+
loop.call_soon_threadsafe(ws._receive_close, reason)
|
|
241
|
+
else:
|
|
242
|
+
ws._receive_close(reason)
|
|
255
243
|
del self._connections[session_id]
|
|
256
244
|
|
|
257
245
|
self._cleanup_task(session_id)
|
|
@@ -214,12 +214,14 @@ pub async fn handle_websocket(
|
|
|
214
214
|
}
|
|
215
215
|
Message::Close(reason) => {
|
|
216
216
|
let sid = ws_session.id;
|
|
217
|
-
let reason_str = reason.
|
|
217
|
+
let reason_str = reason.as_ref().and_then(|r| r.description.clone());
|
|
218
218
|
let handler_ref = Python::attach(|py| handler_for_messages.clone_ref(py));
|
|
219
219
|
|
|
220
220
|
Python::attach(|py| {
|
|
221
221
|
let _ = handler_ref.call_method1(py, "on_disconnect", (sid, reason_str));
|
|
222
222
|
});
|
|
223
|
+
|
|
224
|
+
let _ = session.close(reason).await;
|
|
223
225
|
break;
|
|
224
226
|
}
|
|
225
227
|
_ => {
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|