foghttp 0.3.6__tar.gz → 0.3.7__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.
- {foghttp-0.3.6 → foghttp-0.3.7}/.flake8 +4 -3
- {foghttp-0.3.6 → foghttp-0.3.7}/.github/workflows/ci.yml +2 -2
- {foghttp-0.3.6 → foghttp-0.3.7}/Cargo.lock +1 -1
- {foghttp-0.3.6 → foghttp-0.3.7}/Cargo.toml +1 -1
- {foghttp-0.3.6 → foghttp-0.3.7}/PKG-INFO +11 -6
- {foghttp-0.3.6 → foghttp-0.3.7}/README.md +10 -5
- {foghttp-0.3.6 → foghttp-0.3.7}/docs/index.md +8 -1
- {foghttp-0.3.6 → foghttp-0.3.7}/docs/limitations.md +4 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/docs/packaging.md +5 -3
- foghttp-0.3.7/docs/policy-hooks.md +109 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/docs/pyo3-boundary.md +40 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/docs/quickstart.md +23 -1
- {foghttp-0.3.6 → foghttp-0.3.7}/docs/redirects.md +39 -36
- {foghttp-0.3.6 → foghttp-0.3.7}/docs/request-builder.md +49 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/__init__.py +12 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_client/config.py +5 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_client/core.py +3 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_client/options.py +2 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_client/raw/lifecycle.py +1 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_client/raw/requests.py +6 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_client/request_builder/builder.py +1 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_client/request_builder/models.py +2 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_client/response.py +12 -7
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_client/transport.py +4 -4
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_client/transport_requests.py +1 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_foghttp.pyi +5 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/async_client.py +29 -4
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/client.py +22 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/models.py +2 -0
- foghttp-0.3.7/foghttp/policy.py +111 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/request.py +18 -2
- foghttp-0.3.7/foghttp/request_extensions.py +76 -0
- foghttp-0.3.7/foghttp/request_info.py +28 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/pyproject.toml +1 -1
- {foghttp-0.3.6 → foghttp-0.3.7}/src/core/mod.rs +1 -0
- foghttp-0.3.7/src/core/policy/error.rs +41 -0
- foghttp-0.3.7/src/core/policy/mod.rs +14 -0
- foghttp-0.3.7/src/core/policy/pipeline.rs +109 -0
- foghttp-0.3.7/src/core/policy/proxy.rs +58 -0
- foghttp-0.3.7/src/core/policy/redirect/action.rs +42 -0
- foghttp-0.3.7/src/core/policy/redirect/headers.rs +89 -0
- foghttp-0.3.7/src/core/policy/redirect/method.rs +28 -0
- foghttp-0.3.7/src/core/policy/redirect/mod.rs +12 -0
- foghttp-0.3.7/src/core/policy/redirect/policy.rs +47 -0
- {foghttp-0.3.6/src/py/client/redirects → foghttp-0.3.7/src/core/policy/redirect}/status.rs +1 -1
- foghttp-0.3.7/src/core/policy/redirect/tests.rs +306 -0
- {foghttp-0.3.6/src/py/client/redirects → foghttp-0.3.7/src/core/policy/redirect}/utils.rs +1 -1
- foghttp-0.3.7/src/core/policy/request.rs +77 -0
- foghttp-0.3.7/src/core/policy/tests.rs +189 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/messages.rs +2 -2
- {foghttp-0.3.6 → foghttp-0.3.7}/src/py/client/mod.rs +34 -4
- foghttp-0.3.7/src/py/client/policy_hooks.rs +170 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/py/client/transport/buffered.rs +21 -34
- {foghttp-0.3.6 → foghttp-0.3.7}/src/py/client/transport/client.rs +11 -11
- {foghttp-0.3.6 → foghttp-0.3.7}/src/py/client/transport/context.rs +1 -4
- {foghttp-0.3.6 → foghttp-0.3.7}/src/py/client/transport/errors.rs +5 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/py/client/transport/mod.rs +0 -1
- {foghttp-0.3.6 → foghttp-0.3.7}/src/py/client/transport/request.rs +135 -65
- {foghttp-0.3.6 → foghttp-0.3.7}/src/py/client/transport/response.rs +50 -28
- {foghttp-0.3.6 → foghttp-0.3.7}/src/py/client/transport/streaming.rs +20 -50
- foghttp-0.3.7/src/py/client/transport/tests.rs +182 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_lifecycle/helpers.py +1 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_options/test_raw_numeric_boundary.py +17 -0
- foghttp-0.3.7/tests/client_policy_hooks/requests.py +20 -0
- foghttp-0.3.7/tests/client_policy_hooks/test_async_hooks.py +150 -0
- foghttp-0.3.7/tests/client_policy_hooks/test_contract.py +122 -0
- foghttp-0.3.7/tests/client_policy_hooks/test_sync_hooks.py +241 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_proxy/client_options.py +1 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_transport/models.py +1 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_transport/test_transport_adapter.py +6 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/pyo3_boundary/test_raw_client_signatures.py +3 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/redirect_helpers.py +22 -0
- foghttp-0.3.7/tests/request_builder/test_extensions.py +88 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/request_builder/test_shortcuts.py +10 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/request_factories.py +3 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/support/raw_responses.py +31 -16
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/support/sync_http_server.py +7 -17
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/test_async_redirects.py +55 -13
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/test_public_api.py +2 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/test_raw_client.py +39 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/test_raw_client_errors.py +1 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/test_redaction.py +11 -0
- foghttp-0.3.7/tests/test_request_extensions.py +95 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/test_sync_redirects.py +75 -13
- foghttp-0.3.7/tests/types/__init__.py +0 -0
- foghttp-0.3.7/tests/types/test_policy_contracts.py +40 -0
- foghttp-0.3.7/tests/types/test_request_extensions_contracts.py +30 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/uv.lock +1 -1
- foghttp-0.3.6/foghttp/request_info.py +0 -18
- foghttp-0.3.6/src/py/client/body.rs +0 -19
- foghttp-0.3.6/src/py/client/redirects/action.rs +0 -42
- foghttp-0.3.6/src/py/client/redirects/headers.rs +0 -43
- foghttp-0.3.6/src/py/client/redirects/method.rs +0 -24
- foghttp-0.3.6/src/py/client/redirects/mod.rs +0 -12
- foghttp-0.3.6/src/py/client/redirects/policy.rs +0 -42
- foghttp-0.3.6/src/py/client/redirects/tests.rs +0 -212
- foghttp-0.3.6/src/py/client/transport/proxy.rs +0 -66
- foghttp-0.3.6/src/py/client/transport/tests.rs +0 -215
- {foghttp-0.3.6 → foghttp-0.3.7}/.github/workflows/release.yml +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/.gitignore +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/.pre-commit-config.yaml +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/CODE_OF_CONDUCT.md +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/CONTRIBUTING.md +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/LICENSE +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/SECURITY.md +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/docs/benchmarks.md +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/docs/lifecycle.md +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/docs/proxies.md +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/docs/streaming.md +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/docs/telemetry.md +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/docs/timeouts.md +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/docs/tls.md +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/docs/upload-types.md +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/docs/use-cases.md +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/examples/README.md +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/examples/async_json_fanout.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/examples/async_lifecycle_debug.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/examples/async_resource_limits.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/examples/async_streaming.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/examples/compressed_response.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/examples/http_proxy.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/examples/multipart_uploads.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/examples/prepared_requests.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/examples/redirects.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/examples/request_builder_compatibility.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/examples/sync_json_api.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/examples/sync_streaming.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/examples/telemetry_hooks.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_client/__init__.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_client/asyncio_futures.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_client/constants.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_client/lifecycle_debug.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_client/process.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_client/proxy/__init__.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_client/proxy/auth.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_client/proxy/constants.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_client/proxy/environment.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_client/proxy/models.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_client/proxy/no_proxy.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_client/proxy/no_proxy_rule.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_client/proxy/no_proxy_tokens.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_client/proxy/resolver.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_client/proxy/transport_policy.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_client/proxy/url_parsing.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_client/raw/__init__.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_client/raw/errors.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_client/raw/timeout_errors.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_client/request_builder/__init__.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_client/request_builder/defaults.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_client/request_builder/header_policy.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_client/request_builder/merge.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_client/runtime/__init__.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_client/runtime/constants.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_client/runtime/mode.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_client/runtime/validation.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_client/runtime/workers.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_client/stats.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_client/stream_context.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_client/telemetry/__init__.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_client/telemetry/clock.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_client/telemetry/dispatcher.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_client/telemetry/emission.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_client/telemetry/request_context.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_client/telemetry/request_events.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_client/telemetry/responses.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_client/telemetry/url.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_client/tls.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_client/transport_snapshot_mapping.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_multipart/__init__.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_multipart/constants.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_multipart/content_type.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_multipart/encoding.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_multipart/fields.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_multipart/file_parts.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_multipart/iterators.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_multipart/length.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_multipart/models.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_multipart/normalize.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_multipart/parts.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_multipart/stream.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_multipart/values.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_redaction.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_request_body.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_response/__init__.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_response/encoding.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_response/status.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_streaming/__init__.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_streaming/text/__init__.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_streaming/text/async_chunks.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_streaming/text/iterators.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_streaming/text/lines.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_streaming/text/sync_chunks.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_telemetry.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_upload_body/__init__.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_upload_body/async_sending.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_upload_body/chunks.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_upload_body/feeders.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_upload_body/file_source.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_upload_body/models.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_upload_body/normalize.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_upload_body/predicates.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_upload_body/runtime.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_upload_body/thread_bridge.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_validation/__init__.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/_validation/numeric.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/body.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/errors/__init__.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/errors/base.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/errors/lifecycle.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/errors/response.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/errors/timeout.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/headers.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/lifecycle_debug.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/limits.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/messages.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/methods.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/pool_diagnostics.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/py.typed +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/response.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/stats.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/status_codes/__init__.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/status_codes/client_error.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/status_codes/redirect.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/status_codes/server_error.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/status_codes/success.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/stream_response/__init__.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/stream_response/async_response.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/stream_response/base.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/stream_response/bindings.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/stream_response/constants.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/stream_response/lifecycle_debug.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/stream_response/status.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/stream_response/sync_response.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/stream_response/telemetry.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/telemetry/__init__.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/telemetry/config.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/telemetry/errors.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/telemetry/events.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/telemetry/sinks.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/timeout_diagnostics.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/timeouts.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/tls.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/transport_state.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/transport_stats.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/types/__init__.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/types/http.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/types/multipart.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/types/request.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/types/streams.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/foghttp/url.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/logo.png +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/ruff.toml +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/scripts/check_all_position.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/scripts/install_wheel_smoke.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/core/client/body.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/core/client/connection_limit.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/core/client/mod.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/core/client/proxy/authorization.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/core/client/proxy/endpoint.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/core/client/proxy/http.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/core/client/proxy/mod.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/core/client/proxy/tests.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/core/client/proxy/tunnel.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/core/client/telemetry/mod.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/core/client/telemetry/tests.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/core/client/write_timeout.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/core/headers/mod.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/core/headers/request.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/core/headers/response.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/core/headers/tests.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/core/method.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/core/metrics/atomic.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/core/metrics/buffered.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/core/metrics/counters.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/core/metrics/lifecycle.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/core/metrics/mod.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/core/metrics/origin/blocking.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/core/metrics/origin/metrics.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/core/metrics/origin/mod.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/core/metrics/origin/registry.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/core/metrics/origin/snapshots.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/core/metrics/origin/tests.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/core/metrics/origin/waiters.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/core/metrics/snapshots.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/core/metrics/telemetry.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/core/metrics/tests.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/core/numeric/mod.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/core/numeric/tests.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/core/request.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/core/response/body.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/core/response/budget.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/core/response/decompression.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/core/response/mod.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/core/tls/mod.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/core/tls/tests.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/core/url/constants.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/core/url/mod.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/core/url/origin.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/core/url/scheme.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/core/url/tests.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/errors.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/lib.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/py/client/acquire/diagnostics.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/py/client/acquire/gate.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/py/client/acquire/mod.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/py/client/acquire/origin.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/py/client/acquire/pending.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/py/client/acquire/permit.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/py/client/acquire/telemetry.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/py/client/acquire/tests.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/py/client/async_requests/active.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/py/client/async_requests/callback.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/py/client/async_requests/mod.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/py/client/async_requests/registry.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/py/client/async_requests/spawn.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/py/client/async_requests/stream_spawn.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/py/client/future.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/py/client/lifecycle/mod.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/py/client/lifecycle/tests.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/py/client/options.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/py/client/process.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/py/client/runtime/constants.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/py/client/runtime/mod.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/py/client/runtime/shared.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/py/client/runtime/tests.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/py/client/runtime/workers.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/py/client/streams/callback.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/py/client/streams/constants.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/py/client/streams/mod.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/py/client/streams/parts.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/py/client/streams/read.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/py/client/streams/registry.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/py/client/streams/response.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/py/client/streams/state.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/py/client/streams/state_tests.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/py/client/timeout_diagnostics.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/py/client/transport/body.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/py/client/upload_body.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/py/mod.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/py/pool_diagnostics.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/py/response.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/py/stats.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/py/transport_state.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/src/py/url.rs +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/__init__.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_cancellation/__init__.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_cancellation/conftest.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_cancellation/constants.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_cancellation/helpers.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_cancellation/lifecycle_debug_actions.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_cancellation/lifecycle_debug_assertions.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_cancellation/lifecycle_debug_data.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_cancellation/lifecycle_debug_predicates.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_cancellation/test_async_cancellation.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_cancellation/test_async_lifecycle_debug_buffered.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_cancellation/test_async_lifecycle_debug_messages.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_cancellation/test_async_lifecycle_debug_streaming.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_cancellation/test_async_lifecycle_debug_strict.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_cancellation/test_async_telemetry.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_cancellation/test_asyncio_helpers.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_keepalive/__init__.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_keepalive/assertions.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_keepalive/conftest.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_keepalive/constants.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_keepalive/models.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_keepalive/server.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_keepalive/test_async_keepalive.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_keepalive/test_sync_keepalive.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_lifecycle/__init__.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_lifecycle/conftest.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_lifecycle/constants.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_lifecycle/fork_actions.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_lifecycle/test_async_client_lifecycle.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_lifecycle/test_fork_close_safety.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_lifecycle/test_fork_safety.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_lifecycle/test_fork_stream_safety.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_lifecycle/test_raw_client_lifecycle.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_lifecycle/test_sync_client_lifecycle.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_lifecycle/test_sync_close_race.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_lifecycle/test_sync_close_waits.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_multipart/__init__.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_multipart/assertions.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_multipart/models.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_multipart/sources.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_multipart/test_async_multipart.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_multipart/test_multipart_internals.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_multipart/test_request_builder.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_multipart/test_sync_multipart.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_options/__init__.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_options/test_numeric_validation.py +0 -0
- {foghttp-0.3.6/tests/client_proxy → foghttp-0.3.7/tests/client_policy_hooks}/__init__.py +0 -0
- {foghttp-0.3.6/tests/client_query → foghttp-0.3.7/tests/client_proxy}/__init__.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_proxy/conftest.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_proxy/connect_proxy_server.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_proxy/environment.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_proxy/http_proxy_server.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_proxy/test_client_config.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_proxy/test_environment.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_proxy/test_http_proxy_transport.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_proxy/test_https_proxy_connect.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_proxy/test_no_proxy.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_proxy/test_proxy_models.py +0 -0
- {foghttp-0.3.6/tests/client_resources → foghttp-0.3.7/tests/client_query}/__init__.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_query/assertions.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_query/constants.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_query/test_async_query.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_query/test_async_query_redirects.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_query/test_request_builder.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_query/test_sync_query.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_query/test_sync_query_redirects.py +0 -0
- {foghttp-0.3.6/tests/client_telemetry → foghttp-0.3.7/tests/client_resources}/__init__.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_resources/conftest.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_resources/constants.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_resources/helpers.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_resources/test_async_connection_limits.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_resources/test_async_global_limits.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_resources/test_async_origin_limits.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_resources/test_async_pool_diagnostics.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_resources/test_async_response_body_limits.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_resources/test_async_transport_state.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_resources/test_diagnostic_snapshot_contract.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_resources/test_sync_connection_limits.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_resources/test_sync_global_limits.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_resources/test_sync_origin_limits.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_resources/test_sync_pool_diagnostics.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_resources/test_sync_response_body_limits.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_resources/test_sync_transport_state.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_streaming/__init__.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_streaming/conftest.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_streaming/constants.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_streaming/server.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_streaming/stream_readers.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_streaming/test_async_streaming.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_streaming/test_async_streaming_text_lines.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_streaming/test_streaming_text_decoding.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_streaming/test_sync_streaming.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_streaming/test_sync_streaming_text_lines.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_streaming/text_decoding_sources.py +0 -0
- {foghttp-0.3.6/tests/client_timeouts → foghttp-0.3.7/tests/client_telemetry}/__init__.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_telemetry/assertions.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_telemetry/conftest.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_telemetry/constants.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_telemetry/models.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_telemetry/test_async_stream_hooks.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_telemetry/test_async_stream_telemetry.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_telemetry/test_async_telemetry.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_telemetry/test_concurrent_delivery.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_telemetry/test_event_contract.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_telemetry/test_sync_stream_telemetry.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_telemetry/test_sync_telemetry.py +0 -0
- {foghttp-0.3.6/tests/client_tls → foghttp-0.3.7/tests/client_timeouts}/__init__.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_timeouts/conftest.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_timeouts/constants.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_timeouts/helpers.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_timeouts/test_async_timeouts.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_timeouts/test_sync_timeouts.py +0 -0
- {foghttp-0.3.6/tests/client_upload → foghttp-0.3.7/tests/client_tls}/__init__.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_tls/assertions.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_tls/certificates.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_tls/conftest.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_tls/constants.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_tls/handshake_server.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_tls/models.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_tls/server.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_tls/test_async_tls.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_tls/test_async_tls_redirects.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_tls/test_sync_tls.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_tls/test_sync_tls_redirects.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_tls/test_tls_config.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_transport/__init__.py +0 -0
- {foghttp-0.3.6/tests/fault_injection → foghttp-0.3.7/tests/client_upload}/__init__.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_upload/helpers.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_upload/test_streaming_upload.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_upload/test_upload_helpers.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/client_warning_actions.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/conftest.py +0 -0
- {foghttp-0.3.6/tests/network_errors → foghttp-0.3.7/tests/fault_injection}/__init__.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/fault_injection/conftest.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/fault_injection/constants.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/fault_injection/models.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/fault_injection/protocol.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/fault_injection/responses.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/fault_injection/server.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/fault_injection/state.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/fault_injection/state_assertions.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/fault_injection/test_async_fault_injection.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/fault_injection/test_async_socket_shutdown.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/fault_injection/test_sync_fault_injection.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/fault_injection/test_sync_socket_shutdown.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/fault_injection/timeout_assertions.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/fault_injection/transport_waiters.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/http_body_scenarios.py +0 -0
- {foghttp-0.3.6/tests/request_builder → foghttp-0.3.7/tests/network_errors}/__init__.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/network_errors/conftest.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/network_errors/constants.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/network_errors/helpers.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/network_errors/test_async_network_errors.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/network_errors/test_sync_network_errors.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/pyo3_boundary/__init__.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/pyo3_boundary/async_future_server.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/pyo3_boundary/conftest.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/pyo3_boundary/constants.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/pyo3_boundary/gil_progress.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/pyo3_boundary/test_async_future_boundary.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/pyo3_boundary/test_sync_gil_boundary.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/pyo3_boundary/thread_worker.py +0 -0
- {foghttp-0.3.6/tests/response_decompression → foghttp-0.3.7/tests/request_builder}/__init__.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/request_builder/encoding_property_helpers.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/request_builder/test_base_url.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/request_builder/test_body.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/request_builder/test_default_headers.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/request_builder/test_default_params.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/request_builder/test_encoding_properties.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/request_builder/test_header_policy.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/request_builder/test_headers.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/request_builder/test_merge_contract.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/request_builder/test_no_mutation.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/request_builder/test_parity.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/request_builder/test_query_params.py +0 -0
- {foghttp-0.3.6/tests/types → foghttp-0.3.7/tests/response_decompression}/__init__.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/response_decompression/conftest.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/response_decompression/constants.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/response_decompression/helpers.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/response_decompression/payloads.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/response_decompression/server.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/response_decompression/test_async_response_decompression.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/response_decompression/test_sync_response_decompression.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/support/__init__.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/support/async_http_server.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/support/http_routes.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/support/timeout_diagnostics.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/support/transport_state.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/support/transport_stats.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/test_async_client.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/test_async_response.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/test_client_options.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/test_headers.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/test_query_params.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/test_request_model.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/test_response_encoding.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/test_response_flags.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/test_runtime_workers.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/test_sync_client.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/test_sync_response.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/test_transport_stats.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/test_url.py +0 -0
- {foghttp-0.3.6 → foghttp-0.3.7}/tests/types/test_upload_contracts.py +0 -0
|
@@ -29,10 +29,11 @@ exclude =
|
|
|
29
29
|
per-file-ignores =
|
|
30
30
|
# FogHTTP uses public __init__.py modules as explicit import/__all__ API vitrines.
|
|
31
31
|
**/__init__.py: WPS412
|
|
32
|
-
#
|
|
33
|
-
foghttp/__init__.py: WPS201, WPS412
|
|
32
|
+
# Root package is an explicit API vitrine; import count follows the stable public surface.
|
|
33
|
+
foghttp/__init__.py: WPS201, WPS203, WPS412
|
|
34
|
+
# Public client orchestration modules naturally collect ergonomic kwargs.
|
|
34
35
|
foghttp/client.py: WPS201, WPS211, WPS214, WPS501
|
|
35
|
-
foghttp/async_client.py: WPS201, WPS211, WPS214
|
|
36
|
+
foghttp/async_client.py: WPS201, WPS203, WPS211, WPS214
|
|
36
37
|
# ClientCore maps Rust snapshots to TypedDict literal keys and owns the unclosed-client warning.
|
|
37
38
|
foghttp/_client/core.py: WPS201, WPS211, WPS214, WPS226, WPS603
|
|
38
39
|
# Public domain objects intentionally expose mapping/response/url-style APIs.
|
|
@@ -152,8 +152,8 @@ jobs:
|
|
|
152
152
|
enable-cache: true
|
|
153
153
|
cache-dependency-glob: uv.lock
|
|
154
154
|
|
|
155
|
-
- name:
|
|
156
|
-
run: uv run --extra dev --with "maturin>=1.7,<2" maturin develop --locked
|
|
155
|
+
- name: Build extension in place
|
|
156
|
+
run: uv run --extra dev --with "maturin>=1.7,<2" maturin develop --locked --skip-install
|
|
157
157
|
|
|
158
158
|
- name: Run tests
|
|
159
159
|
if: matrix.python-version != '3.14'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: foghttp
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.7
|
|
4
4
|
Classifier: Development Status :: 3 - Alpha
|
|
5
5
|
Classifier: Framework :: AsyncIO
|
|
6
6
|
Classifier: License :: OSI Approved :: MIT License
|
|
@@ -92,9 +92,9 @@ Runtime requirements:
|
|
|
92
92
|
- `orjson>=3.11,<4`
|
|
93
93
|
|
|
94
94
|
Published CPython wheels use the stable `cp311-abi3` ABI: each supported
|
|
95
|
-
OS/architecture pair has one wheel for
|
|
96
|
-
|
|
97
|
-
|
|
95
|
+
OS/architecture pair has one wheel for the currently validated GIL-enabled
|
|
96
|
+
CPython 3.11 through 3.14 range. Newer Python versions are not part of the
|
|
97
|
+
compatibility claim until they pass the same release checks. See [Packaging and Python compatibility](https://github.com/AmberFog/foghttp/blob/main/docs/packaging.md)
|
|
98
98
|
for the complete wheel matrix and validation policy.
|
|
99
99
|
|
|
100
100
|
## Quick Start
|
|
@@ -149,12 +149,14 @@ async with foghttp.AsyncClient() as client:
|
|
|
149
149
|
- sync and async bytes/text/line response streaming with explicit
|
|
150
150
|
context-managed lifecycle
|
|
151
151
|
- prepared `Request` objects with `build_request()` and `send()`
|
|
152
|
+
- immutable request `extensions` for policy/application metadata outside the HTTP message
|
|
152
153
|
- case-insensitive `Headers` with repeated values
|
|
153
154
|
- safe policy for transport-managed request headers
|
|
154
155
|
- redacted repr/error surfaces for sensitive headers, URL credentials,
|
|
155
156
|
token-like URL params, and buffered body bytes
|
|
156
157
|
- normalized `URL` model with origin comparison and relative joins
|
|
157
|
-
- GET/HEAD/POST/QUERY redirects with final URL, history,
|
|
158
|
+
- GET/HEAD/POST/QUERY redirects with final URL, history, typed same-origin and
|
|
159
|
+
cross-origin header policy, and no cross-origin body replay
|
|
158
160
|
- HTTP proxy routing and HTTPS proxy `CONNECT` tunnelling through explicit
|
|
159
161
|
`proxy=` or `trust_env=True` when the proxy endpoint uses `http://`
|
|
160
162
|
- HTTPS with default WebPKI roots, explicit custom CA certificates, and
|
|
@@ -166,6 +168,8 @@ async with foghttp.AsyncClient() as client:
|
|
|
166
168
|
acquire pressure and idle lifecycle diagnostics
|
|
167
169
|
- opt-in typed telemetry event hooks for request, redirect, response headers,
|
|
168
170
|
response body, and request completion lifecycle
|
|
171
|
+
- opt-in typed transport policy hooks for lightweight request admission and
|
|
172
|
+
response-head checks without default-path Python callbacks
|
|
169
173
|
- versioned telemetry snapshot metadata for `stats()`, `dump_transport_state()`,
|
|
170
174
|
and `dump_pool_diagnostics()`
|
|
171
175
|
- opt-in async lifecycle debug mode for active request snapshots, strict leak
|
|
@@ -184,6 +188,7 @@ async with foghttp.AsyncClient() as client:
|
|
|
184
188
|
- [Packaging and Python compatibility](https://github.com/AmberFog/foghttp/blob/main/docs/packaging.md)
|
|
185
189
|
- [Timeout model](https://github.com/AmberFog/foghttp/blob/main/docs/timeouts.md)
|
|
186
190
|
- [Upload typing contracts](https://github.com/AmberFog/foghttp/blob/main/docs/upload-types.md)
|
|
191
|
+
- [Transport policy hooks](https://github.com/AmberFog/foghttp/blob/main/docs/policy-hooks.md)
|
|
187
192
|
- [Telemetry contract](https://github.com/AmberFog/foghttp/blob/main/docs/telemetry.md)
|
|
188
193
|
- [Response streaming](https://github.com/AmberFog/foghttp/blob/main/docs/streaming.md)
|
|
189
194
|
- [Proxy and trust_env](https://github.com/AmberFog/foghttp/blob/main/docs/proxies.md)
|
|
@@ -217,7 +222,7 @@ path. Disabling TLS verification is intentionally not supported.
|
|
|
217
222
|
Development requires a Rust toolchain with `cargo` available in `PATH`.
|
|
218
223
|
|
|
219
224
|
```bash
|
|
220
|
-
uv run --extra dev --with "maturin>=1.7,<2" maturin develop
|
|
225
|
+
uv run --extra dev --with "maturin>=1.7,<2" maturin develop --locked --skip-install
|
|
221
226
|
uv run --extra dev coverage run -m pytest
|
|
222
227
|
uv run --extra dev coverage report -m
|
|
223
228
|
uv run --extra dev pre-commit run --all-files --show-diff-on-failure
|
|
@@ -49,9 +49,9 @@ Runtime requirements:
|
|
|
49
49
|
- `orjson>=3.11,<4`
|
|
50
50
|
|
|
51
51
|
Published CPython wheels use the stable `cp311-abi3` ABI: each supported
|
|
52
|
-
OS/architecture pair has one wheel for
|
|
53
|
-
|
|
54
|
-
|
|
52
|
+
OS/architecture pair has one wheel for the currently validated GIL-enabled
|
|
53
|
+
CPython 3.11 through 3.14 range. Newer Python versions are not part of the
|
|
54
|
+
compatibility claim until they pass the same release checks. See [Packaging and Python compatibility](https://github.com/AmberFog/foghttp/blob/main/docs/packaging.md)
|
|
55
55
|
for the complete wheel matrix and validation policy.
|
|
56
56
|
|
|
57
57
|
## Quick Start
|
|
@@ -106,12 +106,14 @@ async with foghttp.AsyncClient() as client:
|
|
|
106
106
|
- sync and async bytes/text/line response streaming with explicit
|
|
107
107
|
context-managed lifecycle
|
|
108
108
|
- prepared `Request` objects with `build_request()` and `send()`
|
|
109
|
+
- immutable request `extensions` for policy/application metadata outside the HTTP message
|
|
109
110
|
- case-insensitive `Headers` with repeated values
|
|
110
111
|
- safe policy for transport-managed request headers
|
|
111
112
|
- redacted repr/error surfaces for sensitive headers, URL credentials,
|
|
112
113
|
token-like URL params, and buffered body bytes
|
|
113
114
|
- normalized `URL` model with origin comparison and relative joins
|
|
114
|
-
- GET/HEAD/POST/QUERY redirects with final URL, history,
|
|
115
|
+
- GET/HEAD/POST/QUERY redirects with final URL, history, typed same-origin and
|
|
116
|
+
cross-origin header policy, and no cross-origin body replay
|
|
115
117
|
- HTTP proxy routing and HTTPS proxy `CONNECT` tunnelling through explicit
|
|
116
118
|
`proxy=` or `trust_env=True` when the proxy endpoint uses `http://`
|
|
117
119
|
- HTTPS with default WebPKI roots, explicit custom CA certificates, and
|
|
@@ -123,6 +125,8 @@ async with foghttp.AsyncClient() as client:
|
|
|
123
125
|
acquire pressure and idle lifecycle diagnostics
|
|
124
126
|
- opt-in typed telemetry event hooks for request, redirect, response headers,
|
|
125
127
|
response body, and request completion lifecycle
|
|
128
|
+
- opt-in typed transport policy hooks for lightweight request admission and
|
|
129
|
+
response-head checks without default-path Python callbacks
|
|
126
130
|
- versioned telemetry snapshot metadata for `stats()`, `dump_transport_state()`,
|
|
127
131
|
and `dump_pool_diagnostics()`
|
|
128
132
|
- opt-in async lifecycle debug mode for active request snapshots, strict leak
|
|
@@ -141,6 +145,7 @@ async with foghttp.AsyncClient() as client:
|
|
|
141
145
|
- [Packaging and Python compatibility](https://github.com/AmberFog/foghttp/blob/main/docs/packaging.md)
|
|
142
146
|
- [Timeout model](https://github.com/AmberFog/foghttp/blob/main/docs/timeouts.md)
|
|
143
147
|
- [Upload typing contracts](https://github.com/AmberFog/foghttp/blob/main/docs/upload-types.md)
|
|
148
|
+
- [Transport policy hooks](https://github.com/AmberFog/foghttp/blob/main/docs/policy-hooks.md)
|
|
144
149
|
- [Telemetry contract](https://github.com/AmberFog/foghttp/blob/main/docs/telemetry.md)
|
|
145
150
|
- [Response streaming](https://github.com/AmberFog/foghttp/blob/main/docs/streaming.md)
|
|
146
151
|
- [Proxy and trust_env](https://github.com/AmberFog/foghttp/blob/main/docs/proxies.md)
|
|
@@ -174,7 +179,7 @@ path. Disabling TLS verification is intentionally not supported.
|
|
|
174
179
|
Development requires a Rust toolchain with `cargo` available in `PATH`.
|
|
175
180
|
|
|
176
181
|
```bash
|
|
177
|
-
uv run --extra dev --with "maturin>=1.7,<2" maturin develop
|
|
182
|
+
uv run --extra dev --with "maturin>=1.7,<2" maturin develop --locked --skip-install
|
|
178
183
|
uv run --extra dev coverage run -m pytest
|
|
179
184
|
uv run --extra dev coverage report -m
|
|
180
185
|
uv run --extra dev pre-commit run --all-files --show-diff-on-failure
|
|
@@ -60,6 +60,8 @@ FogHTTP is designed around a few engineering priorities:
|
|
|
60
60
|
pressure, idle lifecycle snapshots, and stuck request diagnostics
|
|
61
61
|
- opt-in typed telemetry event hooks with redacted request/response lifecycle
|
|
62
62
|
events
|
|
63
|
+
- opt-in typed transport policy hooks for lightweight request admission and
|
|
64
|
+
response-head checks, with Rust-owned redirect safety
|
|
63
65
|
- versioned telemetry snapshots that separate alert-oriented stats from
|
|
64
66
|
diagnostic dump APIs
|
|
65
67
|
- opt-in async lifecycle debug snapshots for tests, staging, and incident
|
|
@@ -76,6 +78,7 @@ try to keep public interfaces stable and avoid unnecessary breaking changes.
|
|
|
76
78
|
- [Packaging and Python compatibility](./packaging.md)
|
|
77
79
|
- [Timeout model](./timeouts.md)
|
|
78
80
|
- [Upload typing contracts](./upload-types.md)
|
|
81
|
+
- [Transport policy hooks](./policy-hooks.md)
|
|
79
82
|
- [Telemetry contract](./telemetry.md)
|
|
80
83
|
- [Response streaming](./streaming.md)
|
|
81
84
|
- [TLS trust](./tls.md)
|
|
@@ -110,6 +113,7 @@ try to keep public interfaces stable and avoid unnecessary breaking changes.
|
|
|
110
113
|
- sync and async bytes/text/line response streaming with context-managed cleanup
|
|
111
114
|
- response status flags for success, redirects, and client/server errors
|
|
112
115
|
- prepared `Request` objects with `build_request()` and `send()`
|
|
116
|
+
- immutable request `extensions` for policy/application metadata outside the HTTP message
|
|
113
117
|
- public upload typing contracts for streaming request bodies and multipart
|
|
114
118
|
`files=` providers
|
|
115
119
|
- case-insensitive `Headers` with repeated value support
|
|
@@ -117,7 +121,8 @@ try to keep public interfaces stable and avoid unnecessary breaking changes.
|
|
|
117
121
|
- redacted repr/error surfaces for sensitive headers, URL credentials,
|
|
118
122
|
token-like URL params, and buffered body bytes
|
|
119
123
|
- normalized `URL` model with origin comparison and relative joins
|
|
120
|
-
- GET/HEAD/POST/QUERY redirects with final URL, history,
|
|
124
|
+
- GET/HEAD/POST/QUERY redirects with final URL, history, typed same-origin and
|
|
125
|
+
cross-origin header policy, and no cross-origin body replay
|
|
121
126
|
- HTTPS with default WebPKI roots, explicit custom CA certificates, and
|
|
122
127
|
custom-only CA trust
|
|
123
128
|
- documented lazy transport creation, graceful sync close, async request
|
|
@@ -129,6 +134,8 @@ try to keep public interfaces stable and avoid unnecessary breaking changes.
|
|
|
129
134
|
acquire and idle lifecycle telemetry
|
|
130
135
|
- opt-in typed telemetry event hooks for request, redirect, response headers,
|
|
131
136
|
response body, and request completion lifecycle
|
|
137
|
+
- opt-in typed transport policy hooks with immutable request/response views and
|
|
138
|
+
no default-path Python callback
|
|
132
139
|
- versioned telemetry snapshot metadata for `stats()`, `dump_transport_state()`,
|
|
133
140
|
and `dump_pool_diagnostics()`
|
|
134
141
|
- opt-in async lifecycle debug mode for active request snapshots and strict
|
|
@@ -34,6 +34,7 @@ try to keep public interfaces stable and avoid unnecessary breaking changes.
|
|
|
34
34
|
`response.raise_for_status()`
|
|
35
35
|
- lightweight `response.request`
|
|
36
36
|
- prepared `Request` objects with `build_request()` and `send()`
|
|
37
|
+
- immutable request `extensions` propagated to policy hooks and `response.request`
|
|
37
38
|
- case-insensitive `Headers` with repeated values
|
|
38
39
|
- response header bytes exposed as Latin-1 strings, including obs-text values
|
|
39
40
|
- normalized `URL` with origin comparison and relative joins
|
|
@@ -52,6 +53,8 @@ try to keep public interfaces stable and avoid unnecessary breaking changes.
|
|
|
52
53
|
connection-acquire pressure and idle lifecycle diagnostics
|
|
53
54
|
- opt-in typed telemetry event hooks for request, redirect, response headers,
|
|
54
55
|
response body, and request completion lifecycle
|
|
56
|
+
- opt-in synchronous transport policy hooks with immutable request/response
|
|
57
|
+
snapshots and Rust-owned redirect safety
|
|
55
58
|
- opt-in async lifecycle debug snapshots for active async request handles,
|
|
56
59
|
pending transport pressure, strict test checks, and unclosed-client context
|
|
57
60
|
- default per-response and aggregate buffered response memory limits
|
|
@@ -95,6 +98,7 @@ try to keep public interfaces stable and avoid unnecessary breaking changes.
|
|
|
95
98
|
| separate read/write timeout semantics | `Timeouts.read` is implemented as a buffered and streamed response body progress timeout; `Timeouts.write` is implemented for buffered request body write progress and streaming upload chunk/write progress |
|
|
96
99
|
| socket lifecycle telemetry granularity | `TransportStats` and `dump_transport_state()["origins"]` expose opened, open-failed, closed, reused, aborted, idle-timeout eviction, active, and idle tracked connection counters for the current HTTP/1 path; dedicated failed-reuse and close-reason taxonomy are not exposed yet because current connector hooks do not provide a stable reason signal |
|
|
97
100
|
| telemetry hook granularity | `TelemetryConfig` currently dispatches Python-level request/response lifecycle events; lower-level Rust pool acquire and connection lifecycle event delivery is planned before Prometheus/OpenTelemetry exporters |
|
|
101
|
+
| transport policy hook execution | `TransportPolicyHooks` callbacks are synchronous, inline, non-reentrant, and may run on Rust transport worker threads; `after_response_body` observes only redirect bodies consumed internally, not the final response body returned to the caller |
|
|
98
102
|
| diagnostic snapshot transactionality | `stats()`, `dump_transport_state()`, and `dump_pool_diagnostics()` include `schema_version` and a monotonic `snapshot_sequence`, but the `dump_*` APIs remain diagnostic snapshots rather than lock-protected SLA transactions; use `stats()` for alert-oriented low-cardinality metrics |
|
|
99
103
|
|
|
100
104
|
## Practical Guidance
|
|
@@ -2,9 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
FogHTTP ships a Rust extension built with PyO3. Published CPython wheels target
|
|
4
4
|
the stable `cp311-abi3` ABI, matching the package minimum of Python 3.11. One
|
|
5
|
-
wheel per supported operating-system and architecture pair
|
|
6
|
-
|
|
7
|
-
wheel for every CPython minor version.
|
|
5
|
+
wheel per supported operating-system and architecture pair covers the
|
|
6
|
+
currently validated GIL-enabled CPython 3.11-3.14 range instead of requiring a
|
|
7
|
+
separate wheel for every supported CPython minor version. The ABI may remain
|
|
8
|
+
compatible with newer Python versions, but FogHTTP does not claim that support
|
|
9
|
+
until the full suite and exact wheel pass the release validation matrix.
|
|
8
10
|
|
|
9
11
|
## Release Matrix
|
|
10
12
|
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# Transport Policy Hooks
|
|
2
|
+
|
|
3
|
+
FogHTTP exposes a small opt-in Python edge around its Rust-owned transport
|
|
4
|
+
policy stages. It is intended for trusted, lightweight request admission and
|
|
5
|
+
response-head policy checks. It is not a middleware framework and does not
|
|
6
|
+
expose the internal transport adapter.
|
|
7
|
+
|
|
8
|
+
The default is `policy_hooks=None`. In that mode the Rust bridge does not
|
|
9
|
+
resolve callback or view objects, allocate hook snapshots, call Python, or
|
|
10
|
+
build a runtime list of policies. Built-in proxy and redirect policies remain
|
|
11
|
+
statically dispatched in Rust.
|
|
12
|
+
|
|
13
|
+
## Configuration
|
|
14
|
+
|
|
15
|
+
Hooks are configured per client and have the same contract for `Client` and
|
|
16
|
+
`AsyncClient`, including buffered and streaming requests:
|
|
17
|
+
|
|
18
|
+
```python
|
|
19
|
+
import foghttp
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def allow_service_origins(request: foghttp.TransportPolicyRequest) -> None:
|
|
23
|
+
if foghttp.URL(request.url).origin != "https://api.example.com":
|
|
24
|
+
raise PermissionError("transport target is outside the service boundary")
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def reject_server_errors(response: foghttp.TransportPolicyResponse) -> None:
|
|
28
|
+
if response.status_code >= 500:
|
|
29
|
+
raise RuntimeError("upstream response rejected by transport policy")
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
hooks = foghttp.TransportPolicyHooks(
|
|
33
|
+
before_send=allow_service_origins,
|
|
34
|
+
on_response_headers=reject_server_errors,
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
with foghttp.Client(policy_hooks=hooks) as client:
|
|
38
|
+
response = client.get("https://api.example.com/resource")
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
All callbacks are synchronous and must return `None`. Raising an exception
|
|
42
|
+
rejects the current request and preserves that exception for the caller.
|
|
43
|
+
Returning any other value raises `TypeError`; hook return values cannot mutate
|
|
44
|
+
or replace transport state.
|
|
45
|
+
|
|
46
|
+
## Stage Order
|
|
47
|
+
|
|
48
|
+
| Hook | Ordering and scope |
|
|
49
|
+
|---|---|
|
|
50
|
+
| `before_send` | Runs for the initial request and every redirect hop after Rust has selected and validated the transport route, but before request-slot acquire. |
|
|
51
|
+
| `on_response_headers` | Runs for every response after Rust has classified any redirect action and before FogHTTP consumes or returns the response body. |
|
|
52
|
+
| `after_response_body` | Runs only for redirect response bodies consumed internally by FogHTTP. Rust first validates the redirect limit, replayability, scheme downgrade, header policy, and proxy boundary; the hook runs before the already validated mutation is applied. It does not run for the final body returned to the caller. |
|
|
53
|
+
|
|
54
|
+
There is deliberately no error, timeout, or cancellation hook. Those stages
|
|
55
|
+
remain unavailable until FogHTTP has a Rust-owned failure taxonomy and a real
|
|
56
|
+
retry-policy consumer.
|
|
57
|
+
|
|
58
|
+
## Snapshot Contract
|
|
59
|
+
|
|
60
|
+
`TransportPolicyRequest` is an immutable snapshot with:
|
|
61
|
+
|
|
62
|
+
- normalized uppercase `method`;
|
|
63
|
+
- full normalized `url`;
|
|
64
|
+
- `body` as `"empty"`, `"replayable"`, or `"non_replayable"`;
|
|
65
|
+
- zero-based `redirect_hop`;
|
|
66
|
+
- immutable request-scoped `extensions` supplied by the caller.
|
|
67
|
+
|
|
68
|
+
`TransportPolicyResponse` contains the request snapshot, `status_code`, and an
|
|
69
|
+
immutable tuple of response header pairs. Repeated values for the same header
|
|
70
|
+
retain their order.
|
|
71
|
+
|
|
72
|
+
The full URL and header values are available because trusted policy code may
|
|
73
|
+
need them to make a decision. They can contain credentials or tokens and are
|
|
74
|
+
not telemetry-safe data. Their `repr()` surfaces redact URL secrets and omit
|
|
75
|
+
header values plus extension keys and values, but hook code must still avoid
|
|
76
|
+
logging the raw attributes. Extensions are metadata only and are never
|
|
77
|
+
serialized into HTTP headers, the URL, or the request body. Use
|
|
78
|
+
[`TelemetryConfig`](./telemetry.md) when the goal is observability through
|
|
79
|
+
redacted events rather than request admission.
|
|
80
|
+
|
|
81
|
+
Snapshots contain no socket, permit, response body, cancellation handle, pool,
|
|
82
|
+
or runtime reference. Their transport fields are copies: replacing those fields
|
|
83
|
+
through Python escape hatches cannot alter the request or bypass Rust redirect
|
|
84
|
+
and replayability checks. The extensions mapping is immutable, but its values
|
|
85
|
+
are the caller-owned shallow references described in the request builder
|
|
86
|
+
contract.
|
|
87
|
+
|
|
88
|
+
## Execution And Lifecycle
|
|
89
|
+
|
|
90
|
+
Hooks run inline with transport policy evaluation. They may execute on FogHTTP
|
|
91
|
+
transport worker threads and may be invoked concurrently by concurrent
|
|
92
|
+
requests. A hook must therefore be fast, thread-safe, and independent of an
|
|
93
|
+
asyncio event loop, thread-local state, or `contextvars` propagation.
|
|
94
|
+
Extension values are shared shallow references, so hooks must treat them as
|
|
95
|
+
read-only and safe for concurrent observation.
|
|
96
|
+
|
|
97
|
+
Do not perform blocking I/O, call back into FogHTTP, or re-enter the same client
|
|
98
|
+
from a hook. Hook execution advances the wall clock used by later total-time
|
|
99
|
+
checks, but a running Python callback is not preempted or independently bounded
|
|
100
|
+
by FogHTTP timeouts. Callback failure unwinds through the normal request path
|
|
101
|
+
so permits, response bodies, connections, upload providers, and request metrics
|
|
102
|
+
retain their existing owners and cleanup behavior.
|
|
103
|
+
|
|
104
|
+
## Stability Boundary
|
|
105
|
+
|
|
106
|
+
`TransportPolicyHooks` and its immutable views are the deliberate public
|
|
107
|
+
surface. `src/core/policy/`, PyO3 bridge classes, raw clients, connector types,
|
|
108
|
+
and internal transport adapter Protocols remain implementation details and are
|
|
109
|
+
not extension points.
|
|
@@ -44,6 +44,46 @@ buffered requests:
|
|
|
44
44
|
- If a Rust stream state lock owns an active Python future handle, the lock must
|
|
45
45
|
be released before scheduling cancellation or completion on the Python loop.
|
|
46
46
|
|
|
47
|
+
## Internal Request/Response Policy Seam
|
|
48
|
+
|
|
49
|
+
`src/core/policy/` is an internal, unstable seam for built-in transport
|
|
50
|
+
policies. It is not a public middleware API. The optional
|
|
51
|
+
`TransportPolicyHooks` bridge observes typed copies at selected stage edges;
|
|
52
|
+
it does not expose the core pipeline or transport adapter. The default request
|
|
53
|
+
path performs no Python callback, dynamic dispatch, policy-list allocation, or
|
|
54
|
+
hook-snapshot construction.
|
|
55
|
+
|
|
56
|
+
Policy stages run in this order:
|
|
57
|
+
|
|
58
|
+
1. Before send, the pipeline selects the direct or proxy transport for the
|
|
59
|
+
normalized request URL.
|
|
60
|
+
2. After response headers, it may produce an opaque pending redirect decision.
|
|
61
|
+
3. After the redirect response body has been consumed, it validates the
|
|
62
|
+
redirect limit, request-body replayability, and environment-derived proxy
|
|
63
|
+
boundary before returning a typed request mutation.
|
|
64
|
+
4. `RequestState` applies the mutation before the next send. The policy layer
|
|
65
|
+
never owns sockets, permits, response bodies, or Python objects.
|
|
66
|
+
|
|
67
|
+
The current mutation surface can replace the method and URL, remove request
|
|
68
|
+
headers, and either preserve or drop the request body. A non-replayable body is
|
|
69
|
+
never resent. Environment-derived proxy decisions are not reused across
|
|
70
|
+
origins and therefore fail closed until per-hop environment resolution exists.
|
|
71
|
+
Responses are observed through immutable status and header views; the current
|
|
72
|
+
seam does not mutate response status, headers, or body content.
|
|
73
|
+
Policy diagnostics may include a normalized origin, but must not include URL
|
|
74
|
+
userinfo, path, query parameters, or fragments.
|
|
75
|
+
|
|
76
|
+
Error and timeout policy stages are intentionally absent until the retry work
|
|
77
|
+
defines a Rust-owned failure taxonomy. Core policy code must not accept or
|
|
78
|
+
return `PyErr` merely to reserve a future hook.
|
|
79
|
+
|
|
80
|
+
The PyO3 bridge lives outside `src/core/policy/`. It invokes only callbacks
|
|
81
|
+
resolved when `RawClient` is created, rejects non-`None` callback returns, and
|
|
82
|
+
passes immutable Python snapshots without transport resources. Built-in
|
|
83
|
+
validation runs before a Python hook can veto a redirect mutation. See
|
|
84
|
+
[Transport policy hooks](./policy-hooks.md) for the public execution and
|
|
85
|
+
threading contract.
|
|
86
|
+
|
|
47
87
|
## Review Checklist
|
|
48
88
|
|
|
49
89
|
For PRs touching PyO3, runtime, cancellation, close/aclose, streaming, or
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
Development requires a Rust toolchain with `cargo` available in `PATH`.
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
uv run --extra dev --with "maturin>=1.7,<2" maturin develop
|
|
8
|
+
uv run --extra dev --with "maturin>=1.7,<2" maturin develop --locked --skip-install
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
Runtime requirements:
|
|
@@ -713,6 +713,28 @@ monotonic `snapshot_sequence` within one Rust transport lifetime. Use
|
|
|
713
713
|
`TransportStats` for dashboards and alert-oriented metrics; see
|
|
714
714
|
[Telemetry contract](./telemetry.md) for the current guarantees.
|
|
715
715
|
|
|
716
|
+
For trusted lightweight admission checks, configure synchronous transport
|
|
717
|
+
policy hooks. The hook receives the full normalized target, may reject by
|
|
718
|
+
raising, and cannot mutate transport state:
|
|
719
|
+
|
|
720
|
+
```python
|
|
721
|
+
def require_https(request: foghttp.TransportPolicyRequest) -> None:
|
|
722
|
+
if foghttp.URL(request.url).scheme != "https":
|
|
723
|
+
raise PermissionError("HTTPS is required")
|
|
724
|
+
|
|
725
|
+
|
|
726
|
+
hooks = foghttp.TransportPolicyHooks(before_send=require_https)
|
|
727
|
+
|
|
728
|
+
with foghttp.Client(policy_hooks=hooks) as client:
|
|
729
|
+
response = client.get("https://httpbin.org/get")
|
|
730
|
+
```
|
|
731
|
+
|
|
732
|
+
Hooks run inline and can execute on transport worker threads, so they must be
|
|
733
|
+
fast, synchronous, thread-safe, and non-reentrant. Their snapshots are not
|
|
734
|
+
telemetry-safe: full URLs and response header values may contain secrets. See
|
|
735
|
+
[Transport policy hooks](./policy-hooks.md) for stage ordering, redirect-body
|
|
736
|
+
scope, error propagation, and lifecycle constraints.
|
|
737
|
+
|
|
716
738
|
For opt-in event hooks, pass a typed telemetry config. Hooks receive redacted
|
|
717
739
|
`TelemetryEvent` objects and are intended for logging/tracing bridges, not for
|
|
718
740
|
mutating requests or responses. Hooks run inline, so keep sinks fast and
|
|
@@ -129,41 +129,37 @@ query at a different origin.
|
|
|
129
129
|
## Security Policy
|
|
130
130
|
|
|
131
131
|
FogHTTP applies a conservative redirect security policy on every redirect hop.
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
- `Authorization`
|
|
140
|
-
- `
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
-
|
|
155
|
-
|
|
156
|
-
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
FogHTTP preserves the method but drops the body and body-specific headers
|
|
164
|
-
before the next request. This prevents JSON payloads, tokens, form data, and
|
|
165
|
-
other request bodies from being forwarded to a different origin by a redirect
|
|
166
|
-
response.
|
|
132
|
+
The policy runs after the target URL and body action have been resolved and
|
|
133
|
+
before the next request is sent.
|
|
134
|
+
|
|
135
|
+
| Header category | Fields | Redirect behavior |
|
|
136
|
+
|---|---|---|
|
|
137
|
+
| Transport routing, framing, proxy, and connection | `Host`, `Content-Length`, `Transfer-Encoding`, `Connection`, `Keep-Alive`, `Proxy-Authorization`, `Proxy-Connection`, `TE`, `Trailer`, `Upgrade`, plus fields named by `Connection` | Always removed from the previous request. The transport derives fresh routing and framing fields for the new URL and body and applies proxy credentials for the selected route. |
|
|
138
|
+
| Conditional validators | `If-Match`, `If-None-Match`, `If-Modified-Since`, `If-Unmodified-Since`, `If-Range` | Always removed because the validator describes the previous target resource. |
|
|
139
|
+
| Origin-scoped credentials and metadata | `Authorization`, `Cookie`, `Origin`, `Referer` | Preserved for same-origin redirects and removed for cross-origin redirects. |
|
|
140
|
+
| Content metadata | Every `Content-*` field, including `Content-Type`, `Content-Encoding`, `Content-Language`, `Content-Location`, `Content-Range`, `Content-Disposition`, and `Content-Digest`; also legacy `Digest`, current `Repr-Digest`, and `Last-Modified` | Preserved only while the request body is preserved. Removed when a method rewrite or cross-origin policy drops the body. |
|
|
141
|
+
| Other caller headers | For example, `Accept` and application-specific fields | Preserved. |
|
|
142
|
+
|
|
143
|
+
Same-origin means that the scheme, normalized host, and effective port all
|
|
144
|
+
match. A change to any of those components is cross-origin.
|
|
145
|
+
|
|
146
|
+
The safe API already rejects manual transport-managed fields. Rebuilding them
|
|
147
|
+
inside the Rust redirect policy also protects the lower-level boundary and
|
|
148
|
+
prevents stale authority, framing, proxy credentials, or connection state from
|
|
149
|
+
crossing a hop.
|
|
150
|
+
|
|
151
|
+
The conditional and content rules follow the redirect guidance in
|
|
152
|
+
[RFC 9110](https://www.rfc-editor.org/rfc/rfc9110.html). FogHTTP recognizes both
|
|
153
|
+
the obsolete `Digest` field and its current
|
|
154
|
+
[RFC 9530](https://www.rfc-editor.org/rfc/rfc9530.html) replacements.
|
|
155
|
+
|
|
156
|
+
For same-origin method-preserving redirects, FogHTTP resends a replayable body.
|
|
157
|
+
For cross-origin method-preserving redirects, FogHTTP preserves the method but
|
|
158
|
+
drops any body and its content metadata before the next request. This rule also
|
|
159
|
+
protects bodies supplied through the generic `request()` API for methods whose
|
|
160
|
+
convenience helpers do not accept body arguments. It prevents JSON payloads,
|
|
161
|
+
tokens, form data, and other request bodies from being forwarded to a different
|
|
162
|
+
origin by a redirect response.
|
|
167
163
|
|
|
168
164
|
FogHTTP also blocks `https -> http` redirects. Scheme downgrade redirects are
|
|
169
165
|
too easy to misuse once credentials, cookies, body replay, or future auth helpers
|
|
@@ -174,6 +170,12 @@ Direct streaming bodies use the explicit non-replayable path and are not resent
|
|
|
174
170
|
automatically. Factory-backed streams are replayable because each attempt gets
|
|
175
171
|
a fresh provider.
|
|
176
172
|
|
|
173
|
+
Automatic redirects cannot infer whether an arbitrary application header such
|
|
174
|
+
as `X-API-Key` contains an origin-scoped secret. Keep automatic redirects
|
|
175
|
+
disabled and follow the response explicitly when custom credentials require a
|
|
176
|
+
different forwarding policy. This is also the explicit escape hatch for callers
|
|
177
|
+
that need behavior looser than the built-in matrix.
|
|
178
|
+
|
|
177
179
|
## Proxy Policy
|
|
178
180
|
|
|
179
181
|
Redirects interact with proxy routing because a redirect target can change the
|
|
@@ -196,7 +198,8 @@ recomputation is planned separately.
|
|
|
196
198
|
## Redirect Limit
|
|
197
199
|
|
|
198
200
|
`max_redirects` defaults to `20`. If the limit is exceeded, FogHTTP raises
|
|
199
|
-
`RequestError`.
|
|
201
|
+
`RequestError`. The diagnostic identifies the normalized origin but omits URL
|
|
202
|
+
userinfo, path, query parameters, and fragments.
|
|
200
203
|
|
|
201
204
|
```python
|
|
202
205
|
with foghttp.Client(follow_redirects=True, max_redirects=5) as client:
|
|
@@ -18,6 +18,7 @@ the current FogHTTP API. The same flow is available as a runnable example in
|
|
|
18
18
|
| `params` | Supported | Accepts mappings, repeated pairs, and raw query strings. Existing URL query is preserved. |
|
|
19
19
|
| client default `params` | Supported | Passed as `Client(params=...)` or `AsyncClient(params=...)`. Appended after URL query and before per-request params. |
|
|
20
20
|
| `headers` | Supported | Accepts mappings, pairs, and `foghttp.Headers`. Lookups are case-insensitive and repeated values are preserved. |
|
|
21
|
+
| `extensions` | Supported | Immutable request-scoped metadata for policy and application coordination. It is never serialized into the HTTP message. |
|
|
21
22
|
| client default `headers` | Supported | Passed as `Client(headers=...)` or `AsyncClient(headers=...)`. Per-request headers override defaults case-insensitively. |
|
|
22
23
|
| `json` | Supported | Encoded with `orjson`. Adds `content-type: application/json` unless explicitly set. |
|
|
23
24
|
| `content` | Supported | Accepts buffered `bytes` or `str`, binary file-like objects, sync bytes-like iterables, zero-arg byte-stream factories, and async bytes-like iterables/factories on `AsyncClient`. Strings are encoded as UTF-8. No semantic content type is added. |
|
|
@@ -88,6 +89,54 @@ Per-request headers override client defaults case-insensitively. Repeated
|
|
|
88
89
|
headers from defaults are preserved when the request does not override that
|
|
89
90
|
header name.
|
|
90
91
|
|
|
92
|
+
## Request Extensions
|
|
93
|
+
|
|
94
|
+
Use `extensions=` for request-scoped application metadata that policy hooks,
|
|
95
|
+
auth, retry, proxy, or tracing integrations may need without placing service
|
|
96
|
+
state in HTTP headers. The name is deliberately `extensions`, not `context`:
|
|
97
|
+
the value belongs to a prepared request and does not imply `contextvars`, event
|
|
98
|
+
loop, or task-context propagation.
|
|
99
|
+
|
|
100
|
+
```python
|
|
101
|
+
import foghttp
|
|
102
|
+
from foghttp.methods import GET
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
with foghttp.Client() as client:
|
|
106
|
+
request = client.build_request(
|
|
107
|
+
GET,
|
|
108
|
+
"https://api.example.com/resource",
|
|
109
|
+
extensions={"example.request_id": "request-42"},
|
|
110
|
+
)
|
|
111
|
+
response = client.send(request)
|
|
112
|
+
assert response.request.extensions["example.request_id"] == "request-42"
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
`Request`, `build_request()`, `request()`, `stream()`, and every method shortcut
|
|
116
|
+
accept `extensions=`. FogHTTP makes a shallow immutable copy represented by
|
|
117
|
+
`RequestExtensions`; later changes to the source mapping do not change the
|
|
118
|
+
prepared request. Values remain caller-owned references, so keep them small and
|
|
119
|
+
treat mutable values as immutable while a request, response, or hook may retain
|
|
120
|
+
them. Do not attach open files, sockets, clients, tasks, or other lifecycle-owned
|
|
121
|
+
resources.
|
|
122
|
+
|
|
123
|
+
Keys must be non-empty strings. Libraries should use a package or reverse-domain
|
|
124
|
+
namespace rather than generic names. The case-insensitive `foghttp.*` namespace
|
|
125
|
+
is reserved for present and future internal timeout, trace, proxy, retry, and
|
|
126
|
+
other policy decisions; callers cannot set it. Reserved internal state is not a
|
|
127
|
+
public configuration API.
|
|
128
|
+
|
|
129
|
+
Extensions are available as `request.extensions`, on
|
|
130
|
+
`TransportPolicyRequest.extensions`, and on `response.request.extensions`,
|
|
131
|
+
including redirect history. They are not copied into the URL, headers, or body.
|
|
132
|
+
Their keys and values are omitted from request, response, and policy snapshot
|
|
133
|
+
`repr()` output, but application code must still avoid logging the raw mapping
|
|
134
|
+
when it contains sensitive metadata.
|
|
135
|
+
|
|
136
|
+
When `extensions` is omitted, requests share one empty immutable snapshot and
|
|
137
|
+
the native boundary receives `None`; no per-request metadata mapping or Python
|
|
138
|
+
policy callback is introduced.
|
|
139
|
+
|
|
91
140
|
## Sync Example
|
|
92
141
|
|
|
93
142
|
```python
|
|
@@ -24,6 +24,7 @@ __all__ = (
|
|
|
24
24
|
"ReadTimeout",
|
|
25
25
|
"Request",
|
|
26
26
|
"RequestError",
|
|
27
|
+
"RequestExtensions",
|
|
27
28
|
"RequestInfo",
|
|
28
29
|
"Response",
|
|
29
30
|
"ResponseBodyBudgetExceededError",
|
|
@@ -43,6 +44,10 @@ __all__ = (
|
|
|
43
44
|
"TimeoutError",
|
|
44
45
|
"TimeoutPhase",
|
|
45
46
|
"Timeouts",
|
|
47
|
+
"TransportPolicyBodyState",
|
|
48
|
+
"TransportPolicyHooks",
|
|
49
|
+
"TransportPolicyRequest",
|
|
50
|
+
"TransportPolicyResponse",
|
|
46
51
|
"TransportState",
|
|
47
52
|
"TransportStats",
|
|
48
53
|
"UnclosedClientError",
|
|
@@ -81,8 +86,15 @@ from .lifecycle_debug import (
|
|
|
81
86
|
AsyncLifecycleDebugSnapshot,
|
|
82
87
|
)
|
|
83
88
|
from .limits import Limits
|
|
89
|
+
from .policy import (
|
|
90
|
+
TransportPolicyBodyState,
|
|
91
|
+
TransportPolicyHooks,
|
|
92
|
+
TransportPolicyRequest,
|
|
93
|
+
TransportPolicyResponse,
|
|
94
|
+
)
|
|
84
95
|
from .pool_diagnostics import OriginPoolDiagnostics, PoolBlockingReason, PoolDiagnostics
|
|
85
96
|
from .request import Request
|
|
97
|
+
from .request_extensions import RequestExtensions
|
|
86
98
|
from .request_info import RequestInfo
|
|
87
99
|
from .response import Response
|
|
88
100
|
from .stream_response import AsyncStreamResponse, StreamResponse
|