Showing preview only (1,755K chars total). Download the full file or copy to clipboard to get everything.
Repository: tokio-rs/axum
Branch: main
Commit: bc2ab88afe29
Files: 480
Total size: 1.6 MB
Directory structure:
gitextract_tcp4if_v/
├── .clippy.toml
├── .github/
│ ├── DISCUSSION_TEMPLATE/
│ │ └── q-a.yml
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug_report.md
│ │ ├── config.yml
│ │ └── feature_request.md
│ ├── PULL_REQUEST_TEMPLATE.md
│ └── workflows/
│ └── CI.yml
├── .gitignore
├── CHANGELOG.md
├── CONTRIBUTING.md
├── Cargo.toml
├── ECOSYSTEM.md
├── LICENSE
├── axum/
│ ├── CHANGELOG.md
│ ├── Cargo.toml
│ ├── README.md
│ ├── benches/
│ │ └── benches.rs
│ ├── src/
│ │ ├── body/
│ │ │ └── mod.rs
│ │ ├── boxed.rs
│ │ ├── docs/
│ │ │ ├── debugging_handler_type_errors.md
│ │ │ ├── error_handling.md
│ │ │ ├── extract.md
│ │ │ ├── handlers_intro.md
│ │ │ ├── method_routing/
│ │ │ │ ├── fallback.md
│ │ │ │ ├── layer.md
│ │ │ │ ├── merge.md
│ │ │ │ └── route_layer.md
│ │ │ ├── middleware.md
│ │ │ ├── response.md
│ │ │ └── routing/
│ │ │ ├── fallback.md
│ │ │ ├── into_make_service_with_connect_info.md
│ │ │ ├── layer.md
│ │ │ ├── merge.md
│ │ │ ├── method_not_allowed_fallback.md
│ │ │ ├── nest.md
│ │ │ ├── route.md
│ │ │ ├── route_layer.md
│ │ │ ├── route_service.md
│ │ │ ├── with_state.md
│ │ │ └── without_v07_checks.md
│ │ ├── error_handling/
│ │ │ └── mod.rs
│ │ ├── extension.rs
│ │ ├── extract/
│ │ │ ├── connect_info.rs
│ │ │ ├── matched_path.rs
│ │ │ ├── mod.rs
│ │ │ ├── multipart.rs
│ │ │ ├── nested_path.rs
│ │ │ ├── original_uri.rs
│ │ │ ├── path/
│ │ │ │ ├── de.rs
│ │ │ │ └── mod.rs
│ │ │ ├── query.rs
│ │ │ ├── raw_form.rs
│ │ │ ├── raw_query.rs
│ │ │ ├── rejection.rs
│ │ │ ├── state.rs
│ │ │ └── ws.rs
│ │ ├── form.rs
│ │ ├── handler/
│ │ │ ├── future.rs
│ │ │ ├── mod.rs
│ │ │ └── service.rs
│ │ ├── json.rs
│ │ ├── lib.rs
│ │ ├── macros.rs
│ │ ├── middleware/
│ │ │ ├── from_extractor.rs
│ │ │ ├── from_fn.rs
│ │ │ ├── map_request.rs
│ │ │ ├── map_response.rs
│ │ │ ├── mod.rs
│ │ │ └── response_axum_body.rs
│ │ ├── response/
│ │ │ ├── mod.rs
│ │ │ ├── redirect.rs
│ │ │ └── sse.rs
│ │ ├── routing/
│ │ │ ├── future.rs
│ │ │ ├── into_make_service.rs
│ │ │ ├── method_filter.rs
│ │ │ ├── method_routing.rs
│ │ │ ├── mod.rs
│ │ │ ├── not_found.rs
│ │ │ ├── path_router.rs
│ │ │ ├── route.rs
│ │ │ ├── strip_prefix.rs
│ │ │ ├── tests/
│ │ │ │ ├── fallback.rs
│ │ │ │ ├── get_to_head.rs
│ │ │ │ ├── handle_error.rs
│ │ │ │ ├── merge.rs
│ │ │ │ ├── mod.rs
│ │ │ │ └── nest.rs
│ │ │ └── url_params.rs
│ │ ├── serve/
│ │ │ ├── listener.rs
│ │ │ └── mod.rs
│ │ ├── service_ext.rs
│ │ ├── test_helpers/
│ │ │ ├── counting_cloneable_state.rs
│ │ │ ├── mod.rs
│ │ │ ├── test_client.rs
│ │ │ └── tracing_helpers.rs
│ │ └── util.rs
│ └── tests/
│ └── panic_location.rs
├── axum-core/
│ ├── CHANGELOG.md
│ ├── Cargo.toml
│ ├── README.md
│ └── src/
│ ├── body.rs
│ ├── error.rs
│ ├── ext_traits/
│ │ ├── mod.rs
│ │ ├── request.rs
│ │ └── request_parts.rs
│ ├── extract/
│ │ ├── default_body_limit.rs
│ │ ├── from_ref.rs
│ │ ├── mod.rs
│ │ ├── option.rs
│ │ ├── rejection.rs
│ │ ├── request_parts.rs
│ │ └── tuple.rs
│ ├── lib.rs
│ ├── macros.rs
│ └── response/
│ ├── append_headers.rs
│ ├── into_response.rs
│ ├── into_response_parts.rs
│ └── mod.rs
├── axum-extra/
│ ├── CHANGELOG.md
│ ├── Cargo.toml
│ ├── README.md
│ ├── src/
│ │ ├── body/
│ │ │ ├── async_read_body.rs
│ │ │ └── mod.rs
│ │ ├── either.rs
│ │ ├── extract/
│ │ │ ├── cached.rs
│ │ │ ├── cookie/
│ │ │ │ ├── mod.rs
│ │ │ │ ├── private.rs
│ │ │ │ └── signed.rs
│ │ │ ├── form.rs
│ │ │ ├── json_deserializer.rs
│ │ │ ├── mod.rs
│ │ │ ├── multipart.rs
│ │ │ ├── query.rs
│ │ │ └── with_rejection.rs
│ │ ├── handler/
│ │ │ ├── mod.rs
│ │ │ └── or.rs
│ │ ├── json_lines.rs
│ │ ├── lib.rs
│ │ ├── middleware.rs
│ │ ├── protobuf.rs
│ │ ├── response/
│ │ │ ├── attachment.rs
│ │ │ ├── content_disposition.rs
│ │ │ ├── erased_json.rs
│ │ │ ├── error_response.rs
│ │ │ ├── file_stream.rs
│ │ │ ├── mod.rs
│ │ │ └── multiple.rs
│ │ ├── routing/
│ │ │ ├── mod.rs
│ │ │ ├── resource.rs
│ │ │ └── typed.rs
│ │ └── typed_header.rs
│ └── test_files/
│ ├── index.html
│ ├── index_2.html
│ └── script.js
├── axum-macros/
│ ├── CHANGELOG.md
│ ├── Cargo.toml
│ ├── README.md
│ ├── rust-toolchain
│ ├── src/
│ │ ├── attr_parsing.rs
│ │ ├── axum_test.rs
│ │ ├── debug_handler.rs
│ │ ├── from_ref.rs
│ │ ├── from_request/
│ │ │ ├── attr.rs
│ │ │ └── mod.rs
│ │ ├── lib.rs
│ │ ├── typed_path.rs
│ │ └── with_position.rs
│ └── tests/
│ ├── debug_handler/
│ │ ├── fail/
│ │ │ ├── .gitkeep
│ │ │ ├── argument_not_extractor.rs
│ │ │ ├── argument_not_extractor.stderr
│ │ │ ├── duplicate_args.rs
│ │ │ ├── duplicate_args.stderr
│ │ │ ├── extension_not_clone.rs
│ │ │ ├── extension_not_clone.stderr
│ │ │ ├── extract_self_mut.rs
│ │ │ ├── extract_self_mut.stderr
│ │ │ ├── extract_self_ref.rs
│ │ │ ├── extract_self_ref.stderr
│ │ │ ├── generics.rs
│ │ │ ├── generics.stderr
│ │ │ ├── invalid_attrs.rs
│ │ │ ├── invalid_attrs.stderr
│ │ │ ├── json_not_deserialize.rs
│ │ │ ├── json_not_deserialize.stderr
│ │ │ ├── multiple_paths.rs
│ │ │ ├── multiple_paths.stderr
│ │ │ ├── multiple_request_consumers.rs
│ │ │ ├── multiple_request_consumers.stderr
│ │ │ ├── not_a_function.rs
│ │ │ ├── not_a_function.stderr
│ │ │ ├── not_async.rs
│ │ │ ├── not_async.stderr
│ │ │ ├── not_send.rs
│ │ │ ├── not_send.stderr
│ │ │ ├── output_tuple_too_many.rs
│ │ │ ├── output_tuple_too_many.stderr
│ │ │ ├── returning_request_parts.rs
│ │ │ ├── returning_request_parts.stderr
│ │ │ ├── single_wrong_return_tuple.rs
│ │ │ ├── single_wrong_return_tuple.stderr
│ │ │ ├── too_many_extractors.rs
│ │ │ ├── too_many_extractors.stderr
│ │ │ ├── wrong_order.rs
│ │ │ ├── wrong_order.stderr
│ │ │ ├── wrong_return_tuple.rs
│ │ │ ├── wrong_return_tuple.stderr
│ │ │ ├── wrong_return_type.rs
│ │ │ └── wrong_return_type.stderr
│ │ └── pass/
│ │ ├── associated_fn_without_self.rs
│ │ ├── deny_unreachable_code.rs
│ │ ├── impl_future.rs
│ │ ├── impl_into_response.rs
│ │ ├── infer_state.rs
│ │ ├── multiple_extractors.rs
│ │ ├── mut_extractor.rs
│ │ ├── ready.rs
│ │ ├── request_last.rs
│ │ ├── result_impl_into_response.rs
│ │ ├── returns_self.rs
│ │ ├── self_receiver.rs
│ │ ├── set_state.rs
│ │ └── state_and_body.rs
│ ├── debug_middleware/
│ │ ├── fail/
│ │ │ ├── doesnt_take_next.rs
│ │ │ ├── doesnt_take_next.stderr
│ │ │ ├── next_not_last.rs
│ │ │ ├── next_not_last.stderr
│ │ │ ├── takes_next_twice.rs
│ │ │ └── takes_next_twice.stderr
│ │ └── pass/
│ │ └── basic.rs
│ ├── from_ref/
│ │ ├── fail/
│ │ │ ├── generics.rs
│ │ │ └── generics.stderr
│ │ └── pass/
│ │ ├── basic.rs
│ │ ├── reference-types.rs
│ │ └── skip.rs
│ ├── from_request/
│ │ ├── fail/
│ │ │ ├── double_via_attr.rs
│ │ │ ├── double_via_attr.stderr
│ │ │ ├── enum_from_request_ident_in_variant.rs
│ │ │ ├── enum_from_request_ident_in_variant.stderr
│ │ │ ├── enum_from_request_on_variant.rs
│ │ │ ├── enum_from_request_on_variant.stderr
│ │ │ ├── enum_no_via.rs
│ │ │ ├── enum_no_via.stderr
│ │ │ ├── generic.rs
│ │ │ ├── generic.stderr
│ │ │ ├── generic_without_via.rs
│ │ │ ├── generic_without_via.stderr
│ │ │ ├── generic_without_via_rejection.rs
│ │ │ ├── generic_without_via_rejection.stderr
│ │ │ ├── not_enum_or_struct.rs
│ │ │ ├── not_enum_or_struct.stderr
│ │ │ ├── override_rejection_on_enum_without_via.rs
│ │ │ ├── override_rejection_on_enum_without_via.stderr
│ │ │ ├── parts_extracting_body.rs
│ │ │ ├── parts_extracting_body.stderr
│ │ │ ├── state_infer_multiple_different_types.rs
│ │ │ ├── state_infer_multiple_different_types.stderr
│ │ │ ├── unknown_attr_container.rs
│ │ │ ├── unknown_attr_container.stderr
│ │ │ ├── unknown_attr_field.rs
│ │ │ ├── unknown_attr_field.stderr
│ │ │ ├── via_on_container_and_field.rs
│ │ │ └── via_on_container_and_field.stderr
│ │ └── pass/
│ │ ├── container.rs
│ │ ├── container_parts.rs
│ │ ├── empty_named.rs
│ │ ├── empty_named_parts.rs
│ │ ├── empty_tuple.rs
│ │ ├── empty_tuple_parts.rs
│ │ ├── enum_via.rs
│ │ ├── enum_via_parts.rs
│ │ ├── named.rs
│ │ ├── named_parts.rs
│ │ ├── named_via.rs
│ │ ├── named_via_parts.rs
│ │ ├── override_rejection.rs
│ │ ├── override_rejection_non_generic.rs
│ │ ├── override_rejection_non_generic_parts.rs
│ │ ├── override_rejection_parts.rs
│ │ ├── override_rejection_with_via_on_enum.rs
│ │ ├── override_rejection_with_via_on_enum_parts.rs
│ │ ├── override_rejection_with_via_on_struct.rs
│ │ ├── override_rejection_with_via_on_struct_parts.rs
│ │ ├── state_cookie.rs
│ │ ├── state_enum_via.rs
│ │ ├── state_enum_via_parts.rs
│ │ ├── state_explicit.rs
│ │ ├── state_explicit_parts.rs
│ │ ├── state_field_explicit.rs
│ │ ├── state_field_infer.rs
│ │ ├── state_infer.rs
│ │ ├── state_infer_multiple.rs
│ │ ├── state_infer_parts.rs
│ │ ├── state_via.rs
│ │ ├── state_via_infer.rs
│ │ ├── state_via_parts.rs
│ │ ├── state_with_rejection.rs
│ │ ├── tuple.rs
│ │ ├── tuple_parts.rs
│ │ ├── tuple_same_type_twice.rs
│ │ ├── tuple_same_type_twice_parts.rs
│ │ ├── tuple_same_type_twice_via.rs
│ │ ├── tuple_same_type_twice_via_parts.rs
│ │ ├── tuple_via.rs
│ │ ├── tuple_via_parts.rs
│ │ ├── unit.rs
│ │ └── unit_parts.rs
│ └── typed_path/
│ ├── fail/
│ │ ├── missing_capture.rs
│ │ ├── missing_capture.stderr
│ │ ├── missing_field.rs
│ │ ├── missing_field.stderr
│ │ ├── not_deserialize.rs
│ │ ├── not_deserialize.stderr
│ │ ├── route_not_starting_with_slash.rs
│ │ ├── route_not_starting_with_slash.stderr
│ │ ├── route_not_starting_with_slash_non_empty.rs
│ │ ├── route_not_starting_with_slash_non_empty.stderr
│ │ ├── unit_with_capture.rs
│ │ └── unit_with_capture.stderr
│ └── pass/
│ ├── customize_rejection.rs
│ ├── into_uri.rs
│ ├── named_fields_struct.rs
│ ├── result_handler.rs
│ ├── tuple_struct.rs
│ ├── unit_struct.rs
│ ├── url_encoding.rs
│ └── wildcards.rs
├── contrib/
│ └── ide/
│ └── vscode/
│ └── settings.json
├── deny.toml
└── examples/
├── Cargo.toml
├── README.md
├── anyhow-error-response/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── async-graphql/
│ └── README.md
├── auto-reload/
│ ├── Cargo.toml
│ ├── README.md
│ └── src/
│ └── main.rs
├── chat/
│ ├── Cargo.toml
│ ├── chat.html
│ └── src/
│ └── main.rs
├── compression/
│ ├── Cargo.toml
│ ├── README.md
│ ├── data/
│ │ └── products.json
│ └── src/
│ ├── main.rs
│ └── tests.rs
├── consume-body-in-extractor-or-middleware/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── cors/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── customize-extractor-error/
│ ├── Cargo.toml
│ ├── README.md
│ └── src/
│ ├── custom_extractor.rs
│ ├── derive_from_request.rs
│ ├── main.rs
│ └── with_rejection.rs
├── customize-path-rejection/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── dependency-injection/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── diesel-async-postgres/
│ ├── Cargo.toml
│ ├── migrations/
│ │ └── 2023-03-14-180127_add_users/
│ │ ├── down.sql
│ │ └── up.sql
│ └── src/
│ └── main.rs
├── diesel-postgres/
│ ├── Cargo.toml
│ ├── migrations/
│ │ └── 2023-03-14-180127_add_users/
│ │ ├── down.sql
│ │ └── up.sql
│ └── src/
│ └── main.rs
├── error-handling/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── form/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── global-404-handler/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── graceful-shutdown/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── handle-head-request/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── hello-world/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── http-proxy/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── jwt/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── key-value-store/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── low-level-native-tls/
│ ├── Cargo.toml
│ ├── self_signed_certs/
│ │ ├── cert.pem
│ │ └── key.pem
│ └── src/
│ └── main.rs
├── low-level-openssl/
│ ├── Cargo.toml
│ ├── self_signed_certs/
│ │ ├── cert.pem
│ │ └── key.pem
│ └── src/
│ └── main.rs
├── low-level-rustls/
│ ├── Cargo.toml
│ ├── self_signed_certs/
│ │ ├── cert.pem
│ │ └── key.pem
│ └── src/
│ └── main.rs
├── mongodb/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── multipart-form/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── oauth/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── parse-body-based-on-content-type/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── print-request-response/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── prometheus-metrics/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── readme/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── request-id/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── reqwest-response/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── reverse-proxy/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── routes-and-handlers-close-together/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── serve-with-hyper/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── simple-router-wasm/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── sqlx-postgres/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── sse/
│ ├── Cargo.toml
│ ├── assets/
│ │ ├── index.html
│ │ └── script.js
│ └── src/
│ └── main.rs
├── static-file-server/
│ ├── Cargo.toml
│ ├── assets/
│ │ ├── index.html
│ │ └── script.js
│ └── src/
│ └── main.rs
├── stream-to-file/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── templates/
│ ├── Cargo.toml
│ ├── src/
│ │ └── main.rs
│ └── templates/
│ └── hello.html
├── templates-minijinja/
│ ├── Cargo.toml
│ ├── src/
│ │ └── main.rs
│ └── templates/
│ ├── about.jinja
│ ├── content.jinja
│ ├── home.jinja
│ └── layout.jinja
├── testing/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── testing-websockets/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── tls-graceful-shutdown/
│ ├── Cargo.toml
│ ├── self_signed_certs/
│ │ ├── cert.pem
│ │ └── key.pem
│ └── src/
│ └── main.rs
├── tls-rustls/
│ ├── Cargo.toml
│ ├── self_signed_certs/
│ │ ├── cert.pem
│ │ └── key.pem
│ └── src/
│ └── main.rs
├── todos/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── tokio-postgres/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── tokio-redis/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── tracing-aka-logging/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── unix-domain-socket/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── validator/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── versioning/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── websockets/
│ ├── Cargo.toml
│ ├── assets/
│ │ ├── index.html
│ │ └── script.js
│ └── src/
│ ├── client.rs
│ └── main.rs
└── websockets-http2/
├── Cargo.toml
├── assets/
│ ├── index.html
│ └── script.js
├── self_signed_certs/
│ ├── cert.pem
│ └── key.pem
└── src/
└── main.rs
================================================
FILE CONTENTS
================================================
================================================
FILE: .clippy.toml
================================================
allow-mixed-uninlined-format-args = false
disallowed-types = [
{ path = "tower::util::BoxCloneService", reason = "Use tower::util::BoxCloneSyncService instead" },
]
================================================
FILE: .github/DISCUSSION_TEMPLATE/q-a.yml
================================================
body:
- type: textarea
attributes:
label: Summary
description: 'Your question:'
validations:
required: true
- type: input
attributes:
label: axum version
description: 'Please look it up in `Cargo.lock`, or as described below'
validations:
required: true
- type: markdown
attributes:
value: |
> If you have `jq` installed, you can look up the version by running
>
> ```bash
> cargo metadata --format-version=1 | jq -r '.packages[] | select(.name == "axum") | .version'
> ```
================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: 🐛 Bug Report
about: If something isn't working as expected 🤔.
---
<!--
Thank you for reporting an issue.
Please fill in as much of the template below as you're able.
-->
- [ ] I have looked for existing issues (including closed) about this
## Bug Report
### Version
<!--
List the versions of all `axum` crates you are using. The easiest way to get
this information is using `cargo tree`:
`cargo tree | grep axum`
-->
### Platform
<!---
Output of `uname -a` (UNIX), or version and 32 or 64-bit (Windows)
-->
### Crates
<!--
If known, please specify the affected axum crates. Otherwise, delete this
section.
-->
### Description
<!--
Enter your issue details below this comment.
One way to structure the description:
<short summary of the bug>
I tried this code:
<code sample that causes the bug>
I expected to see this happen: <explanation>
Instead, this happened: <explanation>
-->
================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
contact_links:
- name: 🙏 Q&A (GitHub Discussions)
url: https://github.com/tokio-rs/axum/discussions/categories/q-a
about: Q&A all around axum usage
- name: 💬 Tokio Discord
url: https://discord.gg/tokio
about: Community chat for Tokio (axum channel is under libs)
================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.md
================================================
---
name: 💡 Feature Request
about: I have a suggestion (and may want to implement it 🙂)!
---
- [ ] I have looked for existing issues (including closed) about this
## Feature Request
### Motivation
<!--
Please describe the use case(s) or other motivation for the new feature.
-->
### Proposal
<!--
How should the new feature be implemented, and why? Add any considered
drawbacks.
-->
### Alternatives
<!--
Are there other ways to solve this problem that you've considered? What are
their potential drawbacks? Why was the proposed solution chosen over these
alternatives?
-->
================================================
FILE: .github/PULL_REQUEST_TEMPLATE.md
================================================
<!--
Thank you for your Pull Request. Please provide a description above and review
the requirements below.
Bug fixes and new features should include tests.
Contributors guide: https://github.com/tokio-rs/axum/blob/master/CONTRIBUTING.md
-->
## Motivation
<!--
Explain the context and why you're making that change. What is the problem
you're trying to solve? If a new feature is being added, describe the intended
use case that feature fulfills.
-->
## Solution
<!--
Summarize the solution and provide any necessary context needed to understand
the code change.
-->
================================================
FILE: .github/workflows/CI.yml
================================================
name: CI
env:
CARGO_TERM_COLOR: always
MSRV: '1.80'
on:
push:
branches:
- main
- v0.*
pull_request: {}
jobs:
check:
runs-on: ubuntu-24.04
strategy:
matrix:
workspace: [".", examples]
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@beta
with:
components: clippy, rustfmt
- uses: Swatinem/rust-cache@v2
with:
save-if: ${{ github.ref == 'refs/heads/main' }}
workspaces: ${{ matrix.workspace }}
- name: Check
run: cargo clippy --locked --manifest-path ${{ matrix.workspace }}/Cargo.toml --workspace --all-targets --all-features -- -D warnings
- name: rustfmt
run: cargo fmt --all --check --manifest-path ${{ matrix.workspace }}/Cargo.toml
check-docs:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
with:
save-if: ${{ github.ref == 'refs/heads/main' }}
- name: cargo doc -p axum-core
run: cargo doc --package axum-core --all-features --no-deps
- name: cargo doc -p axum
run: cargo doc --package axum --all-features --no-deps
- name: cargo doc -p axum-extra
run: cargo doc --package axum-extra --all-features --no-deps
env:
RUSTDOCFLAGS: "-D rustdoc::all -A rustdoc::private-doc-tests"
cargo-hack:
runs-on: ubuntu-24.04
env:
# Fail the build if there are any warnings
RUSTFLAGS: "-D warnings"
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
with:
save-if: ${{ github.ref == 'refs/heads/main' }}
- uses: taiki-e/install-action@cargo-hack
- name: cargo hack check
run: cargo hack check --each-feature --no-dev-deps --all
external-types:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@master
with:
toolchain: nightly-2025-10-18
- name: Install cargo-check-external-types
uses: taiki-e/cache-cargo-install-action@v2
with:
tool: cargo-check-external-types@0.4.0
- uses: taiki-e/install-action@cargo-hack
- uses: Swatinem/rust-cache@v2
with:
save-if: ${{ github.ref == 'refs/heads/main' }}
- run: cargo hack --no-private --exclude axum-macros check-external-types --all-features
test-versions:
needs: check
runs-on: ubuntu-24.04
strategy:
matrix:
rust: [stable, beta]
workspace: [".", examples]
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ matrix.rust }}
- uses: Swatinem/rust-cache@v2
with:
save-if: ${{ github.ref == 'refs/heads/main' }}
workspaces: ${{ matrix.workspace }}
- name: Run tests
run: cargo test --locked --workspace --all-features --all-targets --manifest-path ${{ matrix.workspace }}/Cargo.toml
# some examples don't support our MSRV so we only test axum itself on our MSRV
test-nightly:
needs: check
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- name: Get rust-toolchain version
id: rust-toolchain
run: echo "version=$(cat axum-macros/rust-toolchain)" >> $GITHUB_OUTPUT
- uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ steps.rust-toolchain.outputs.version }}
- uses: Swatinem/rust-cache@v2
with:
save-if: ${{ github.ref == 'refs/heads/main' }}
- name: Run nightly tests
working-directory: axum-macros
run: cargo test
# some examples don't support our MSRV (such as async-graphql)
# so we only test axum itself on our MSRV
test-msrv:
needs: check
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- name: "install Rust nightly"
uses: dtolnay/rust-toolchain@nightly
- name: Select minimal version
run: cargo +nightly update -Z minimal-versions
- name: Fix up Cargo.lock - crc32fast
run: cargo +nightly update -p crc32fast --precise 1.1.1
- name: Fix up Cargo.lock - version_check
run : cargo +nightly update -p version_check@0.1.0 --precise 0.1.4
- name: Fix up Cargo.lock - lazy_static
run: cargo +nightly update -p lazy_static --precise 1.1.0
- uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ env.MSRV }}
- uses: Swatinem/rust-cache@v2
with:
save-if: ${{ github.ref == 'refs/heads/main' }}
- name: Run tests
run: cargo +${{ env.MSRV }} test --locked --all-features
deny-check:
name: cargo-deny check
runs-on: ubuntu-24.04
continue-on-error: ${{ matrix.checks == 'advisories' }}
strategy:
matrix:
checks:
- advisories
- bans licenses sources
steps:
- uses: actions/checkout@v6
- uses: EmbarkStudios/cargo-deny-action@v2
with:
command: check ${{ matrix.checks }}
manifest-path: axum/Cargo.toml
armv5te-unknown-linux-musleabi:
needs: check
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@stable
with:
target: armv5te-unknown-linux-musleabi
- uses: Swatinem/rust-cache@v2
with:
save-if: ${{ github.ref == 'refs/heads/main' }}
- name: Check
env:
# Clang has native cross-compilation support
CC: clang
run: cargo check --all-targets --all-features --target armv5te-unknown-linux-musleabi
wasm32-unknown-unknown:
needs: check
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@stable
with:
target: wasm32-unknown-unknown
- uses: Swatinem/rust-cache@v2
with:
save-if: ${{ github.ref == 'refs/heads/main' }}
workspaces: examples
- name: Check
run: >
cargo
check
--manifest-path ./examples/simple-router-wasm/Cargo.toml
--target wasm32-unknown-unknown
dependencies-are-sorted:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- name: Install cargo-sort
uses: taiki-e/install-action@v2
with:
tool: cargo-sort@2.0.2
- name: Check dependency tables
run: cargo-sort --workspace --grouped --check
- name: Check examples dependency tables
run: cargo-sort --workspace --grouped --check
working-directory: examples
typos:
name: Spell Check with Typos
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- name: Check the spelling of the files in our repo
uses: crate-ci/typos@v1.29.4
================================================
FILE: .gitignore
================================================
target
.DS_Store
.vscode
================================================
FILE: CHANGELOG.md
================================================
axum's changelog has moved and now lives [here](https://github.com/tokio-rs/axum/blob/main/axum/CHANGELOG.md).
================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to axum
🎈 Thanks for your help improving the project! We are so happy to have
you!
There are opportunities to contribute to `axum` at any level. It doesn't
matter if you are just getting started with Rust or are the most weathered
expert, we can use your help.
**No contribution is too small and all contributions are valued.**
This guide will help you get started. **Do not let this guide intimidate you**.
It should be considered a map to help you navigate the process.
Don't know where to start? Check [issues labeled with "E-help-wanted"](https://github.com/tokio-rs/axum/issues?q=is%3Aopen+is%3Aissue+label%3AE-help-wanted) or ["E-easy"](https://github.com/tokio-rs/axum/issues?q=is%3Aopen+is%3Aissue+label%3AE-easy).
You may also get help with contributing in the [`axum` Discord
channel][discord], please join us!
[discord]: https://discord.gg/tokio
## Conduct
The `axum` project adheres to the [Rust Code of Conduct][coc]. This
describes the _minimum_ behavior expected from all contributors.
[coc]: https://github.com/rust-lang/rust/blob/master/CODE_OF_CONDUCT.md
## Contributing in Issues
For any issue, there are fundamentally three ways an individual can contribute:
1. By opening the issue for discussion: For instance, if you believe that you
have uncovered a bug in a `axum` crate, creating a new issue in the
tokio-rs/axum [issue tracker][issues] is the way to report it.
2. By helping to triage the issue: This can be done by providing
supporting details (a test case that demonstrates a bug), providing
suggestions on how to address the issue, or ensuring that the issue is tagged
correctly.
3. By helping to resolve the issue: Typically this is done either in the form of
demonstrating that the issue reported is not a problem after all, or more
often, by opening a Pull Request that changes some bit of something in
axum in a concrete and reviewable manner.
**Anybody can participate in any stage of contribution**. We urge you to
participate in the discussion around bugs and participate in reviewing PRs.
[issues]: https://github.com/tokio-rs/axum/issues
### Asking for General Help
If you have reviewed existing documentation and still have questions or are
having problems, you can open an issue asking for help.
In exchange for receiving help, we ask that you contribute back a documentation
PR that helps others avoid the problems that you encountered.
### Submitting a Bug Report
When opening a new issue in the `axum` issue tracker, users will
be presented with a [basic template][template] that should be filled in. If you
believe that you have uncovered a bug, please fill out this form, following the
template to the best of your ability. Do not worry if you cannot answer every
detail, just fill in what you can.
The two most important pieces of information we need in order to properly
evaluate the report is a description of the behavior you are seeing and a simple
test case we can use to recreate the problem on our own. If we cannot recreate
the issue, it becomes harder for us to fix.
See [How to create a Minimal, Complete, and Verifiable example][mcve].
[mcve]: https://stackoverflow.com/help/mcve
[template]: .github/ISSUE_TEMPLATE/bug_report.md
### Triaging a Bug Report
Once an issue has been opened, it is not uncommon for there to be discussion
around it. Some contributors may have differing opinions about the issue,
including whether the behavior being seen is a bug or a feature. This discussion
is part of the process and should be kept focused, helpful, and professional.
Short, clipped responses—that provide neither additional context nor supporting
detail—are not helpful or professional. To many, such responses are simply
annoying and unfriendly.
Contributors are encouraged to help one another make forward progress as much as
possible, empowering one another to solve issues collaboratively. If you choose
to comment on an issue that you feel either is not a problem that needs to be
fixed, or if you encounter information in an issue that you feel is incorrect,
explain why you feel that way with additional supporting context, and be willing
to be convinced that you may be wrong. By doing so, we can often reach the
correct outcome much faster.
### Resolving a Bug Report
In the majority of cases, issues are resolved by opening a Pull Request. The
process for opening and reviewing a Pull Request is similar to that of opening
and triaging issues, but carries with it a necessary review and approval
workflow that ensures that the proposed changes meet the minimal quality.
## Pull Requests
Pull Requests are the way concrete changes are made to the code, documentation,
and dependencies in the `axum` repository.
Even tiny pull requests (e.g., one character pull request fixing a typo in API
documentation) are greatly appreciated. Before making a large change, it is
usually a good idea to first open an issue describing the change to solicit
feedback and guidance. This will increase the likelihood of the PR getting
merged.
### Tests
If the change being proposed alters code (as opposed to only documentation for
example), it is either adding new functionality to a crate or it is fixing
existing, broken functionality. In both of these cases, the pull request should
include one or more tests to ensure that the crate does not regress in the future.
#### Documentation tests
Ideally, every API has at least one [documentation test] that demonstrates how to
use the API. Documentation tests are run with `cargo test --doc`. This ensures
that the example is correct and provides additional test coverage.
The trick to documentation tests is striking a balance between being succinct
for a reader to understand and actually testing the API.
In Rust documentation, lines that start with `/// #` are removed when the
documentation is generated. They are only there to get the test to run.
### Commits
It is a recommended best practice to keep your changes as logically grouped as
possible within individual commits. There is no limit to the number of commits
any single Pull Request may have, and many contributors find it easier to review
changes that are split across multiple commits.
Note that multiple commits often get squashed when they are landed (see the
notes about [commit squashing]).
#### Commit message guidelines
A good commit message should describe what changed and why.
1. The first line should:
* Contain a short description of the change (preferably 50 characters or less,
and no more than 72 characters)
2. Keep the second line blank.
3. Wrap all other lines at 72 columns (except for long URLs).
4. If your patch fixes an open issue, you can add a reference to it at the end
of the log. Use the `Fixes: #` prefix and the issue number. For other
references use `Refs: #`. `Refs` may include multiple issues, separated by a
comma.
Examples:
- `Fixes: #1337`
- `Refs: #1234, #42`
### Opening the Pull Request
From within GitHub, opening a new Pull Request will present you with a
[template] that should be filled out. Please try to do your best at filling out
the details, but feel free to skip parts if you're not sure what to put.
[template]: .github/PULL_REQUEST_TEMPLATE.md
### Discuss and update
You will probably get feedback or requests for changes to your Pull Request.
This is a big part of the submission process so don't be discouraged! Some
contributors may sign off on the Pull Request right away, others may have
more detailed comments or feedback. This is a necessary part of the process
in order to evaluate whether the changes are correct and necessary.
**Any community member can review a PR and you might get conflicting feedback**.
Keep an eye out for comments from code owners to provide guidance on conflicting
feedback.
**Once the PR is open, do not rebase the commits**. See [Commit Squashing] for
more details.
### Commit Squashing
In most cases, **do not squash commits that you add to your Pull Request during
the review process**. When the commits in your Pull Request land, they may be
squashed into one commit per logical change. Metadata will be added to the
commit message (including links to the Pull Request, links to relevant issues,
and the names of the reviewers). The commit history of your Pull Request,
however, will stay intact on the Pull Request page.
## Reviewing Pull Requests
**Any Tokio, Hyperium, and Tower, axum community member is welcome to review any pull request**.
All contributors who choose to review and provide feedback on Pull Requests have
a responsibility to both the project and the individual making the contribution.
Reviews and feedback must be helpful, insightful, and geared towards improving
the contribution as opposed to simply blocking it. If there are reasons why you
feel the PR should not land, explain what those are. Do not expect to be able to
block a Pull Request from advancing simply because you say "No" without giving
an explanation. Be open to having your mind changed. Be open to working with the
contributor to make the Pull Request better.
Reviews that are dismissive or disrespectful of the contributor or any other
reviewers are strictly counter to the Code of Conduct.
When reviewing a Pull Request, the primary goals are for the codebase to improve
and for the person submitting the request to succeed. **Even if a Pull Request
does not land, the submitters should come away from the experience feeling like
their effort was not wasted or unappreciated**. Every Pull Request from a new
contributor is an opportunity to grow the community.
### Review a bit at a time.
Do not overwhelm new contributors.
It is tempting to micro-optimize and make everything about relative performance,
perfect grammar, or exact style matches. Do not succumb to that temptation.
Focus first on the most significant aspects of the change:
1. Does this change make sense for axum?
2. Does this change make axum better, even if only incrementally?
3. Are there clear bugs or larger scale issues that need attending to?
4. Is the commit message readable and correct? If it contains a breaking change
is it clear enough?
Note that only **incremental** improvement is needed to land a PR. This means
that the PR does not need to be perfect, only better than the status quo. Follow
up PRs may be opened to continue iterating.
When changes are necessary, *request* them, do not *demand* them, and **do not
assume that the submitter already knows how to add a test or run a benchmark**.
Specific performance optimization techniques, coding styles and conventions
change over time. The first impression you give to a new contributor never does.
Nits (requests for small changes that are not essential) are fine, but try to
avoid stalling the Pull Request. Most nits can typically be fixed by the axum
Collaborator landing the Pull Request but they can also be an opportunity for
the contributor to learn a bit more about the project.
It is always good to clearly indicate nits when you comment: e.g.
`Nit: change foo() to bar(). But this is not blocking.`
If your comments were addressed but were not folded automatically after new
commits or if they proved to be mistaken, please, [hide them][hiding-a-comment]
with the appropriate reason to keep the conversation flow concise and relevant.
### Be aware of the person behind the code
Be aware that *how* you communicate requests and reviews in your feedback can
have a significant impact on the success of the Pull Request. Yes, we may land a
particular change that makes `axum` better, but the individual might just
not want to have anything to do with `axum` ever again. The goal is not
just having good code.
### Abandoned or Stalled Pull Requests
If a Pull Request appears to be abandoned or stalled, it is polite to first
check with the contributor to see if they intend to continue the work before
checking if they would mind if you took it over (especially if it just has nits
left). When doing so, it is courteous to give the original contributor credit
for the work they started, either by preserving their name and email address in
the commit log, or by using an `Author: ` meta-data tag in the commit.
[hiding-a-comment]: https://help.github.com/articles/managing-disruptive-comments/#hiding-a-comment
[documentation test]: https://doc.rust-lang.org/rustdoc/documentation-tests.html
[keep-a-changelog]: https://github.com/olivierlacan/keep-a-changelog/blob/master/CHANGELOG.md
================================================
FILE: Cargo.toml
================================================
[workspace]
members = ["axum", "axum-*"]
resolver = "2"
[workspace.package]
rust-version = "1.80"
[workspace.lints.rust]
unsafe_code = "forbid"
rust_2018_idioms = { level = "warn", priority = -1 }
missing_debug_implementations = "warn"
missing_docs = "warn"
unreachable_pub = "warn"
[workspace.lints.clippy]
type_complexity = "allow"
await_holding_lock = "warn"
dbg_macro = "warn"
empty_enums = "warn"
enum_glob_use = "warn"
equatable_if_let = "warn"
exit = "warn"
filter_map_next = "warn"
fn_params_excessive_bools = "warn"
if_let_mutex = "warn"
implicit_clone = "warn"
imprecise_flops = "warn"
inefficient_to_string = "warn"
linkedlist = "warn"
lossy_float_literal = "warn"
macro_use_imports = "warn"
manual_let_else = "warn"
match_same_arms = "warn"
match_wildcard_for_single_variants = "warn"
mem_forget = "warn"
must_use_candidate = "warn"
needless_borrow = "warn"
needless_continue = "warn"
needless_pass_by_ref_mut = "warn"
needless_pass_by_value = "warn"
option_option = "warn"
redundant_clone = "warn"
ref_option = "warn"
rest_pat_in_fully_bound_structs = "warn"
return_self_not_must_use = "warn"
single_match_else = "warn"
str_to_string = "warn"
suboptimal_flops = "warn"
todo = "warn"
trivially_copy_pass_by_ref = "warn"
uninlined_format_args = "warn"
unnested_or_patterns = "warn"
unused_self = "warn"
use_self = "warn"
verbose_file_reads = "warn"
# configuration for https://github.com/crate-ci/typos
[workspace.metadata.typos.default.extend-identifiers]
# These have been fixed in the past, but are still present in the changelog.
DefaultOnFailedUpdgrade = "DefaultOnFailedUpdgrade"
OnFailedUpdgrade = "OnFailedUpdgrade"
================================================
FILE: ECOSYSTEM.md
================================================
# Community Projects
If your project isn't listed here and you would like it to be, please feel free to create a PR.
## Community maintained axum ecosystem
- [axum-server](https://crates.io/crates/axum-server): axum-server is a hyper server implementation designed to be used with axum.
- [axum-typed-websockets](https://crates.io/crates/axum-typed-websockets): `axum::extract::ws` with type safe messages.
- [tower-cookies](https://crates.io/crates/tower-cookies): Cookie manager middleware
- [axum-flash](https://crates.io/crates/axum-flash): One-time notifications (aka flash messages) for axum.
- [axum-msgpack](https://crates.io/crates/axum-msgpack): MessagePack Extractors for axum.
- [axum-sqlx-tx](https://crates.io/crates/axum-sqlx-tx): Request-bound [SQLx](https://github.com/launchbadge/sqlx#readme) transactions with automatic commit/rollback based on response.
- [aliri_axum](https://docs.rs/aliri_axum) and [aliri_tower](https://docs.rs/aliri_tower): JWT validation middleware and OAuth2 scopes enforcing extractors.
- [ezsockets](https://github.com/gbaranski/ezsockets): Easy to use WebSocket library that integrates with axum.
- [axum_session](https://github.com/AscendingCreations/AxumSessions): Database persistent sessions like pythons flask_sessionstore for axum.
- [axum_session_auth](https://github.com/AscendingCreations/AxumSessionsAuth): Persistent session based user login with rights management for axum.
- [axum-auth](https://crates.io/crates/axum-auth): High-level http auth extractors for axum.
- [axum-keycloak-auth](https://github.com/lpotthast/axum-keycloak-auth): Protect axum routes with a JWT emitted by Keycloak.
- [axum-tungstenite](https://github.com/davidpdrsn/axum-tungstenite): WebSocket connections for axum directly using tungstenite
- [axum-jrpc](https://github.com/0xdeafbeef/axum-jrpc): Json-rpc extractor for axum
- [axum-tracing-opentelemetry](https://crates.io/crates/axum-tracing-opentelemetry): Middlewares and tools to integrate axum + tracing + opentelemetry
- [svelte-axum-project](https://github.com/jbertovic/svelte-axum-project): Template and example for Svelte frontend app with axum as backend
- [axum-streams](https://github.com/abdolence/axum-streams-rs): Streaming HTTP body with different formats: JSON, CSV, Protobuf.
- [axum-template](https://github.com/Altair-Bueno/axum-template): Layers, extractors and template engine wrappers for axum based Web MVC applications
- [axum-template](https://github.com/janos-r/axum-template): GraphQL and REST API, SurrealDb, JWT auth, direct error handling, request logs
- [axum-guard-logic](https://github.com/sjud/axum_guard_logic): Use AND/OR logic to extract types and check their values against `Service` inputs.
- [axum-casbin-auth](https://github.com/casbin-rs/axum-casbin-auth): Casbin access control middleware for axum
- [aide](https://docs.rs/aide): Code-first Open API documentation generator with [axum integration](https://docs.rs/aide/latest/aide/axum/index.html).
- [axum-typed-routing](https://docs.rs/axum-typed-routing/latest/axum_typed_routing/): Statically typed routing macros with OpenAPI generation using aide.
- [axum-jsonschema](https://docs.rs/axum-jsonschema/): A `Json<T>` extractor that does JSON schema validation of requests.
- [axum-login](https://docs.rs/axum-login): Session-based user authentication for axum.
- [axum-gate](https://docs.rs/axum-gate): JWT-based authentication and role-based authorization for axum (Cookie and Bearer, for monolithic and distributed applications).
- [axum-csrf-sync-pattern](https://crates.io/crates/axum-csrf-sync-pattern): A middleware implementing CSRF STP for AJAX backends and API endpoints.
- [axum-otel-metrics](https://github.com/ttys3/axum-otel-metrics/): A axum OpenTelemetry Metrics middleware with prometheus exporter supported.
- [tower-otel](https://github.com/mattiapenati/tower-otel): OpenTelemetry layer for HTTP/gRPC services with optional axum integration.
- [jwt-authorizer](https://crates.io/crates/jwt-authorizer): JWT authorization layer for axum (oidc discovery, validation options, claims extraction, etc.)
- [axum-typed-multipart](https://crates.io/crates/axum_typed_multipart): Type safe wrapper for `axum::extract::Multipart`.
- [tower-governor](https://crates.io/crates/tower_governor): A Tower service and layer that provides a rate-limiting backend by [governor](https://crates.io/crates/governor)
- [axum-restful](https://github.com/gongzhengyang/axum-restful): A restful framework based on axum and sea-orm, inspired by django-rest-framework.
- [springtime-web-axum](https://crates.io/crates/springtime-web-axum): A web framework built on Springtime and axum, leveraging dependency injection for easy app development.
- [rust-axum-with-google-oauth](https://github.com/randommm/rust-axum-with-google-oauth): website template for Google OAuth authentication on axum, using SQLite with SQLx or MongoDB and MiniJinja.
- [axum-htmx](https://github.com/robertwayne/axum-htmx): Htmx extractors and request guards for axum.
- [axum-prometheus](https://github.com/ptrskay3/axum-prometheus): A middleware library to collect HTTP metrics for axum applications, compatible with all [metrics.rs](https://metrics.rs) exporters.
- [axum-valid](https://github.com/gengteng/axum-valid): Extractors for data validation using validator, garde, and validify.
- [tower-sessions](https://github.com/maxcountryman/tower-sessions): Sessions as a `tower` and `axum` middleware.
- [socketioxide](https://github.com/totodore/socketioxide): An easy to use socket.io server implementation working as a `tower` layer/service.
- [axum-serde](https://github.com/gengteng/axum-serde): Provides multiple serde-based extractors / responses, also offers a macro to easily customize serde-based extractors / responses.
- [loco.rs](https://github.com/loco-rs/loco): A full stack Web and API productivity framework similar to Rails, based on axum.
- [axum-test](https://crates.io/crates/axum-test): High level library for writing Cargo tests that run against axum.
- [axum-messages](https://github.com/maxcountryman/axum-messages): One-time notification messages for axum.
- [spring-rs](https://github.com/spring-rs/spring-rs): spring-rs is a microservice framework written in rust inspired by java's spring-boot, based on axum
- [zino](https://github.com/zino-rs/zino): Zino is a next-generation framework for composable applications which provides full integrations with axum.
- [axum-rails-cookie](https://github.com/endoze/axum-rails-cookie): Extract rails session cookies in axum based apps.
- [axum-ws-broadcaster](https://github.com/Necoo33/axum-ws-broadcaster): A broadcasting liblary for both [axum-typed-websockets](https://crates.io/crates/axum-typed-websockets) and `axum::extract::ws`.
- [axum-negotiate-layer](https://github.com/2ndDerivative/axum-negotiate-layer): Middleware/Layer for Kerberos/NTLM "Negotiate" authentication.
- [axum-kit](https://github.com/4lkaid/axum-kit): Streamline the integration and usage of axum with SQLx and Redis.
- [tower_allowed_hosts](https://crates.io/crates/tower_allowed_hosts): Allowed hosts middleware which limits request from only allowed hosts.
- [baxe](https://github.com/zyphelabs/baxe): Simple macro for defining backend errors once and automatically generate standardized JSON error responses, saving time and reducing complexity
- [axum-html-minifier](https://crates.io/crates/axum_html_minifier): This middleware minify the html body content of a axum response.
- [static-serve](https://crates.io/crates/static-serve): A helper macro for compressing and embedding static assets in an axum webserver.
- [datastar](https://crates.io/crates/datastar): Rust implementation of the Datastar SDK specification with Axum support
- [axum-governor](https://crates.io/crates/axum-governor): An independent Axum middleware for rate limiting, powered by [lazy-limit](https://github.com/canmi21/lazy-limit) (not related to tower-governor).
- [axum-conditional-requests](https://crates.io/crates/axum-conditional-requests): A library for handling client-side caching HTTP headers
- [sigterm](https://github.com/canmi21/sigterm): Signal-aware async control and cancellation primitives for Tokio.
- [tower-resilience](https://github.com/joshrotenberg/tower-resilience): Resilience middleware for tower: circuit breaker, bulkhead, retry, rate limiter, and more.
## Project showcase
- [webshelf](https://github.com/aiqubits/webshelf): 🤘 A convenient way to develop your web service with one click.
- [HomeDisk](https://github.com/MedzikUser/HomeDisk): ☁️ Fast, lightweight and Open Source local cloud for your data.
- [Houseflow](https://github.com/gbaranski/houseflow): House automation platform written in Rust.
- [JWT Auth](https://github.com/Z4RX/axum_jwt_example): JWT auth service for educational purposes.
- [ROAPI](https://github.com/roapi/roapi): Create full-fledged APIs for static datasets without writing a single line of code.
- [notify.run](https://github.com/notify-run/notify-run-rs): HTTP-to-WebPush relay for sending desktop/mobile notifications to yourself, written in Rust.
- [turbo.fish](https://turbo.fish/) ([repository](https://github.com/jplatte/turbo.fish)): Find out for yourself 😉
- [Book Management](https://github.com/lz1998/axum-book-management): CRUD system of book-management with ORM and JWT for educational purposes.
- [realworld-axum-sqlx](https://github.com/launchbadge/realworld-axum-sqlx): A Rust implementation of the [Realworld] demo app spec using axum and [SQLx].
See https://github.com/davidpdrsn/realworld-axum-sqlx for a fork with up to date dependencies.
- [Rustapi](https://github.com/ndelvalle/rustapi): RESTful API template using MongoDB
- [axum-postgres-template](https://github.com/koskeller/axum-postgres-template): Production-ready axum + PostgreSQL application template
- [RUSTfulapi](https://github.com/robatipoor/rustfulapi): Reusable template for building REST Web Services in Rust. Uses axum and SeaORM.
- [Jotsy](https://github.com/ohsayan/jotsy): Self-hosted notes app powered by Skytable, axum and Tokio
- [Svix](https://www.svix.com) ([repository](https://github.com/svix/svix-webhooks)): Enterprise-ready webhook service
- [emojied](https://emojied.net) ([repository](https://github.com/sekunho/emojied)): Shorten URLs to emojis!
- [CLOMonitor](https://clomonitor.io) ([repository](https://github.com/cncf/clomonitor)): Checks open source projects repositories to verify they meet certain best practices.
- [Pinging.net](https://www.pinging.net) ([repository](https://github.com/benhansenslc/pinging)): A new way to check and monitor your internet connection.
- [wastebin](https://github.com/matze/wastebin): A minimalist pastebin service.
- [sandbox_axum_observability](https://github.com/davidB/sandbox_axum_observability) A Sandbox/showcase project to experiment axum and observability (tracing, opentelemetry, jaeger, grafana tempo,...)
- [axum_admin](https://github.com/lingdu1234/axum_admin): An admin panel built with **axum**, Sea-orm and Vue 3.
- [rgit](https://git.inept.dev/~doyle/rgit.git/about): A blazingly fast Git repository browser, compatible with- and heavily inspired by cgit.
- [Petclinic](https://github.com/danipardo/petclinic): A port of Spring Framework's Petclinic showcase project to axum
- [axum-middleware-example](https://github.com/casbin-rs/axum-middleware-example): A authorization application using axum, Casbin and Diesel, with JWT support.
- [circleci-hook](https://github.com/DavidS/circleci-hook): Translate CircleCI WebHooks to OpenTelemetry traces to improve your test insights. Add detail with otel-cli to capture individual commands. Use the TRACEPARENT integration to add details from your tests.
- [lishuuro.org](https://github.com/uros-5/backend-lishuuro): Small chess variant server that uses axum for the backend.
- [freedit](https://github.com/freedit-org/freedit): A forum powered by rust.
- [axum-http-auth-example](https://github.com/i0n/axum-http-auth-example): axum http auth example using postgres and redis.
- [Deaftone](https://github.com/Deaftone/Deaftone): Lightweight music server. With a clean and simple API
- [dropit](https://github.com/scotow/dropit): Temporary file hosting.
- [cobrust](https://github.com/scotow/cobrust): Multiplayer web based snake game.
- [meta-cross](https://github.com/scotow/meta-cross): Tweaked version of Tic-Tac-Toe.
- [httq](https://github.com/scotow/httq) HTTP to MQTT trivial proxy.
- [Pods-Blitz](https://pods-blitz.org) Self-hosted podcast publisher. Uses the crates axum-login, password-auth, sqlx and handlebars (for HTML templates).
- [ReductStore](https://github.com/reductstore/reductstore): A time series database for storing and managing large amounts of blob data
- [randoku](https://github.com/stchris/randoku): A tiny web service which generates random numbers and shuffles lists randomly
- [sero](https://github.com/clowzed/sero): Host static sites with custom subdomains as surge.sh does. But with full control and cool new features. (axum, sea-orm, postgresql)
- [Hatsu](https://github.com/importantimport/hatsu): 🩵 Self-hosted & Fully-automated ActivityPub Bridge for Static Sites.
- [Mini RPS](https://github.com/marcodpt/minirps): Mini reverse proxy server, HTTPS, CORS, static file hosting and template engine (minijinja).
- [fx](https://github.com/rikhuijzer/fx): A (micro)blogging server that you can self-host.
- [clean_axum_demo](https://github.com/sukjaelee/clean_axum_demo): A modern, clean-architecture Rust API server template built with Axum and SQLx. It incorporates domain-driven design, repository patterns, JWT authentication, file uploads, Swagger documentation, OpenTelemetry.
- [qiluo-admin](https://github.com/chelunfu/qiluo_admin) | Axum + SeaORM + JWT + Scheduled + Tasks + SnowId + Redis + Memory + VUE3 | DB: MySQL, Postgres, SQLite
- [openapi-rs](https://github.com/baerwang/openapi-rs/tree/main/examples/axum) | This project adds a middleware layer to axum using openapi-rs, enabling automatic request validation and processing based on OpenAPI 3.1 specifications. It helps ensure that the server behavior strictly follows the OpenAPI contract.
- [axum-rest-api-example](https://github.com/sheroz/axum-rest-api-sample): REST API Web service in Rust using axum, JSON Web Tokens (JWT), SQLx, PostgreSQL, Redis, Docker, structured error handling, and end-to-end API tests.
- [tower-mcp](https://github.com/joshrotenberg/tower-mcp): Tower-native Model Context Protocol (MCP) implementation
[Realworld]: https://github.com/gothinkster/realworld
[SQLx]: https://github.com/launchbadge/sqlx
## Tutorials
- [Rust on Nails](https://rust-on-nails.com/): A full stack architecture for Rust web applications
- [axum-tutorial] ([website][axum-tutorial-website]): axum tutorial for beginners
- [demo-rust-axum]: Demo of Rust and axum
- [Introduction to axum (talk)]: Talk about axum from the Copenhagen Rust Meetup
- [Getting Started with Axum]: axum tutorial, GET, POST endpoints and serving files
- [Using Rust, Axum, PostgreSQL, and Tokio to build a Blog]
- [Introduction to axum]: YouTube playlist
- [Rust Axum Full Course]: YouTube video
- [API Development with Rust](https://rust-api.dev/docs/front-matter/preface/): REST APIs based on axum
- [axum-rest-api-postgres-redis-jwt-docker]: Getting started with REST API Web Services in Rust using Axum, PostgreSQL, Redis, and JWT
[axum-tutorial]: https://github.com/programatik29/axum-tutorial
[axum-tutorial-website]: https://programatik29.github.io/axum-tutorial/
[demo-rust-axum]: https://github.com/joelparkerhenderson/demo-rust-axum
[Introduction to axum (talk)]: https://www.youtube.com/watch?v=ETdmhh7OQpA
[Getting Started with Axum]: https://carlosmv.hashnode.dev/getting-started-with-axum-rust
[Using Rust, Axum, PostgreSQL, and Tokio to build a Blog]: https://spacedimp.com/blog/using-rust-axum-postgresql-and-tokio-to-build-a-blog/
[Introduction to axum]: https://www.youtube.com/playlist?list=PLrmY5pVcnuE-_CP7XZ_44HN-mDrLQV4nS
[Rust Axum Full Course]: https://www.youtube.com/watch?v=XZtlD_m59sM
[axum-rest-api-postgres-redis-jwt-docker]: https://sheroz.com/pages/blog/rust-axum-rest-api-postgres-redis-jwt-docker.html
[Building a SaaS with Rust & Next.js](https://joshmo.bearblog.dev/lets-build-a-saas-with-rust/) A tutorial for combining Next.js with Rust via axum to make a SaaS.
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2019–2025 axum Contributors
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
================================================
FILE: axum/CHANGELOG.md
================================================
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
# Unreleased
- **breaking:** Router fallbacks are now properly merged for nested routers ([#3158])
- **breaking:** `#[from_request(via(Extractor))]` now uses the extractor's
rejection type instead of `axum::response::Response` ([#3261])
- **breaking:** `axum::serve` now applies hyper's default `header_read_timeout` ([#3478])
- **breaking:** `axum::serve` future output type has been adjusted to remove `io::Result`
(never returned `Err`) and be an uninhabited type if `with_graceful_shutdown` is not used
(because it was already never terminating if that method wasn't used) ([#3601])
- **added:** New `ListenerExt::limit_connections` allows limiting concurrent `axum::serve` connections ([#3489])
- **added:** `MethodRouter::method_filter` ([#3586])
- **added:** `WebSocketUpgrade::{requested_protocols, set_selected_protocol}` for more
flexible subprotocol selection ([#3597])
- **changed:** `serve` has an additional generic argument and can now work with any response body
type, not just `axum::body::Body` ([#3205])
- **changed:** Update minimum rust version to 1.80 ([#3620])
- **changed:** `Redirect` constructors now accept any `impl Into<String>` ([#3635])
[#3158]: https://github.com/tokio-rs/axum/pull/3158
[#3261]: https://github.com/tokio-rs/axum/pull/3261
[#3205]: https://github.com/tokio-rs/axum/pull/3205
[#3478]: https://github.com/tokio-rs/axum/pull/3478
[#3601]: https://github.com/tokio-rs/axum/pull/3601
[#3489]: https://github.com/tokio-rs/axum/pull/3489
[#3586]: https://github.com/tokio-rs/axum/pull/3586
[#3597]: https://github.com/tokio-rs/axum/pull/3597
[#3620]: https://github.com/tokio-rs/axum/pull/3620
# 0.8.8
- Clarify documentation for `Router::route_layer` ([#3567])
[#3567]: https://github.com/tokio-rs/axum/pull/3567
# 0.8.7
- Relax implicit `Send` / `Sync` bounds on `RouterAsService`, `RouterIntoService` ([#3555])
- Make it easier to visually scan for default features ([#3550])
- Fix some documentation typos
[#3550]: https://github.com/tokio-rs/axum/pull/3550
[#3555]: https://github.com/tokio-rs/axum/pull/3555
# 0.8.6
Released without changes to fix docs.rs build.
# 0.8.5
- **fixed:** Reject JSON request bodies with trailing characters after the JSON document ([#3453])
- **added:** Implement `OptionalFromRequest` for `Multipart` ([#3220])
- **added:** Getter methods `Location::{status_code, location}`
- **added:** Support for writing arbitrary binary data into server-sent events ([#3425])]
- **added:** `middleware::ResponseAxumBodyLayer` for mapping response body to `axum::body::Body` ([#3469])
- **added:** `impl FusedStream for WebSocket` ([#3443])
- **changed:** The `sse` module and `Sse` type no longer depend on the `tokio` feature ([#3154])
- **changed:** If the location given to one of `Redirect`s constructors is not a valid
header value, instead of panicking on construction, the `IntoResponse` impl now returns
an HTTP 500, just like `Json` does when serialization fails ([#3377])
- **changed:** Update minimum rust version to 1.78 ([#3412])
[#3154]: https://github.com/tokio-rs/axum/pull/3154
[#3220]: https://github.com/tokio-rs/axum/pull/3220
[#3377]: https://github.com/tokio-rs/axum/pull/3377
[#3412]: https://github.com/tokio-rs/axum/pull/3412
[#3425]: https://github.com/tokio-rs/axum/pull/3425
[#3443]: https://github.com/tokio-rs/axum/pull/3443
[#3453]: https://github.com/tokio-rs/axum/pull/3453
[#3469]: https://github.com/tokio-rs/axum/pull/3469
# 0.8.4
- **added:** `Router::reset_fallback` ([#3320])
- **added:** `WebSocketUpgrade::selected_protocol` ([#3248])
- **fixed:** Panic location for overlapping method routes ([#3319])
- **fixed:** Don't leak a tokio task when using `serve` without graceful shutdown ([#3129])
[#3319]: https://github.com/tokio-rs/axum/pull/3319
[#3320]: https://github.com/tokio-rs/axum/pull/3320
[#3248]: https://github.com/tokio-rs/axum/pull/3248
[#3129]: https://github.com/tokio-rs/axum/pull/3129
# 0.8.3
- **added:** Implement `From<Bytes>` for `Message` ([#3273])
- **added:** Implement `OptionalFromRequest` for `Json` ([#3142])
- **added:** Implement `OptionalFromRequest` for `Extension` ([#3157])
- **added:** Allow setting the read buffer capacity of `WebSocketUpgrade` ([#3178])
- **changed:** Improved code size / compile time of dependent crates ([#3285], [#3294])
[#3273]: https://github.com/tokio-rs/axum/pull/3273
[#3142]: https://github.com/tokio-rs/axum/pull/3142
[#3157]: https://github.com/tokio-rs/axum/pull/3157
[#3178]: https://github.com/tokio-rs/axum/pull/3178
[#3285]: https://github.com/tokio-rs/axum/pull/3285
[#3294]: https://github.com/tokio-rs/axum/pull/3294
# 0.8.2
Yanked from crates.io due to unforeseen breaking change, see [#3190] for details.
[#3190]: https://github.com/tokio-rs/axum/pull/3190
# 0.8.1
- **fixed:** Removed the warning about breaking changes from README
# 0.8.0
## since rc.1
<details>
- **breaking:** `axum::extract::ws::Message` now uses `Bytes` in place of `Vec<u8>`,
and a new `Utf8Bytes` type in place of `String`, for its variants ([#3078])
- **breaking:** Remove `OptionalFromRequestParts` impl for `Query` ([#3088])
- **changed:** Upgraded `tokio-tungstenite` to 0.26 ([#3078])
- **changed:** Query/Form: Use `serde_path_to_error` to report fields that failed to parse ([#3081])
[#3088]: https://github.com/tokio-rs/axum/pull/3088
</details>
## full changelog
*Note: there are further relevant changes in [axum-core's changelog][core-changelog]*
- **breaking:** Upgrade matchit to 0.8, changing the path parameter syntax from `/:single` and `/*many`
to `/{single}` and `/{*many}`; the old syntax produces a panic to avoid silent change in behavior ([#2645])
- **breaking:** Require `Sync` for all handlers and services added to `Router`
and `MethodRouter` ([#2473])
- **breaking:** The tuple and tuple_struct `Path` extractor deserializers now check that the number of parameters matches the tuple length exactly ([#2931])
- **breaking:** Move `Host` extractor to `axum-extra` ([#2956])
- **breaking:** Remove `WebSocket::close`.
Users should explicitly send close messages themselves. ([#2974])
- **breaking:** Make `serve` generic over the listener and IO types ([#2941])
- **breaking:** Remove `Serve::tcp_nodelay` and `WithGracefulShutdown::tcp_nodelay`.
See `serve::ListenerExt` for an API that let you set arbitrary TCP stream properties. ([#2941])
- **breaking:** `Option<Path<T>>` no longer swallows all error conditions,
instead rejecting the request in many cases; see its documentation for details ([#2475])
- **breaking:** `axum::extract::ws::Message` now uses `Bytes` in place of `Vec<u8>`,
and a new `Utf8Bytes` type in place of `String`, for its variants ([#3078])
- **fixed:** Skip SSE incompatible chars of `serde_json::RawValue` in `Event::json_data` ([#2992])
- **fixed:** Don't panic when array type is used for path segment ([#3039])
- **fixed:** Avoid setting `content-length` before middleware.
This allows middleware to add bodies to requests without needing to manually set `content-length` ([#2897])
- **change:** Update minimum rust version to 1.75 ([#2943])
- **changed:** Upgraded `tokio-tungstenite` to 0.26 ([#3078])
- **changed:** Query/Form: Use `serde_path_to_error` to report fields that failed to parse ([#3081])
- **added:** Add `method_not_allowed_fallback` to set a fallback when a path matches but there is no handler for the given HTTP method ([#2903])
- **added:** Add `NoContent` as a self-described shortcut for `StatusCode::NO_CONTENT` ([#2978])
- **added:** Add support for WebSockets over HTTP/2.
They can be enabled by changing `get(ws_endpoint)` handlers to `any(ws_endpoint)` ([#2894])
- **added:** Add `MethodFilter::CONNECT`, `routing::connect[_service]`
and `MethodRouter::connect[_service]` ([#2961])
- **added:** Extend `FailedToDeserializePathParams::kind` enum with (`ErrorKind::DeserializeError`)
This new variant captures both `key`, `value`, and `message` from named path parameters parse errors,
instead of only deserialization error message in `ErrorKind::Message`. ([#2720])
[#3078]: https://github.com/tokio-rs/axum/pull/3078
[#3081]: https://github.com/tokio-rs/axum/pull/3081
## rc.1
*Note: there are further relevant changes in [axum-core's changelog][core-changelog]*
- **breaking:** Move `Host` extractor to `axum-extra` ([#2956])
- **breaking:** Remove `WebSocket::close`.
Users should explicitly send close messages themselves. ([#2974])
- **breaking:** Make `serve` generic over the listener and IO types ([#2941])
- **breaking:** Remove `Serve::tcp_nodelay` and `WithGracefulShutdown::tcp_nodelay`.
See `serve::ListenerExt` for an API that let you set arbitrary TCP stream properties. ([#2941])
- **breaking:** `Option<Path<T>>` and `Option<Query<T>>` no longer swallow all error conditions,
instead rejecting the request in many cases; see their documentation for details ([#2475])
- **fixed:** Skip SSE incompatible chars of `serde_json::RawValue` in `Event::json_data` ([#2992])
- **fixed:** Don't panic when array type is used for path segment ([#3039])
- **fixed:** Avoid setting `content-length` before middleware.
This allows middleware to add bodies to requests without needing to manually set `content-length` ([#2897])
- **added:** Add `method_not_allowed_fallback` to set a fallback when a path matches but there is no handler for the given HTTP method ([#2903])
- **added:** Add `NoContent` as a self-described shortcut for `StatusCode::NO_CONTENT` ([#2978])
- **added:** Add support for WebSockets over HTTP/2.
They can be enabled by changing `get(ws_endpoint)` handlers to `any(ws_endpoint)` ([#2894])
- **added:** Add `MethodFilter::CONNECT`, `routing::connect[_service]`
and `MethodRouter::connect[_service]` ([#2961])
- **added:** Extend `FailedToDeserializePathParams::kind` enum with (`ErrorKind::DeserializeError`)
This new variant captures both `key`, `value`, and `message` from named path parameters parse errors,
instead of only deserialization error message in `ErrorKind::Message`. ([#2720])
[core-changelog]: ../axum-core/CHANGELOG.md
[#2475]: https://github.com/tokio-rs/axum/pull/2475
[#2897]: https://github.com/tokio-rs/axum/pull/2897
[#2903]: https://github.com/tokio-rs/axum/pull/2903
[#2894]: https://github.com/tokio-rs/axum/pull/2894
[#2956]: https://github.com/tokio-rs/axum/pull/2956
[#2961]: https://github.com/tokio-rs/axum/pull/2961
[#2974]: https://github.com/tokio-rs/axum/pull/2974
[#2978]: https://github.com/tokio-rs/axum/pull/2978
[#2992]: https://github.com/tokio-rs/axum/pull/2992
[#2720]: https://github.com/tokio-rs/axum/pull/2720
[#3039]: https://github.com/tokio-rs/axum/pull/3039
[#2941]: https://github.com/tokio-rs/axum/pull/2941
## alpha.1
- **breaking:** Require `Sync` for all handlers and services added to `Router`
and `MethodRouter` ([#2473])
- **breaking:** The tuple and tuple_struct `Path` extractor deserializers now check that the number of parameters matches the tuple length exactly ([#2931])
- **breaking:** Upgrade matchit to 0.8, changing the path parameter syntax from `/:single` and `/*many`
to `/{single}` and `/{*many}`; the old syntax produces a panic to avoid silent change in behavior ([#2645])
- **change:** Update minimum rust version to 1.75 ([#2943])
[#2473]: https://github.com/tokio-rs/axum/pull/2473
[#2645]: https://github.com/tokio-rs/axum/pull/2645
[#2931]: https://github.com/tokio-rs/axum/pull/2931
[#2943]: https://github.com/tokio-rs/axum/pull/2943
# 0.7.9
- **fixed:** Avoid setting content-length before middleware ([#3031])
[#3031]:https://github.com/tokio-rs/axum/pull/3031
# 0.7.8
- **fixed:** Skip SSE incompatible chars of `serde_json::RawValue` in `Event::json_data` ([#2992])
- **added:** Add `method_not_allowed_fallback` to set a fallback when a path matches but there is no handler for the given HTTP method ([#2903])
- **added:** Add `MethodFilter::CONNECT`, `routing::connect[_service]`
and `MethodRouter::connect[_service]` ([#2961])
- **added:** Add `NoContent` as a self-described shortcut for `StatusCode::NO_CONTENT` ([#2978])
[#2903]: https://github.com/tokio-rs/axum/pull/2903
[#2961]: https://github.com/tokio-rs/axum/pull/2961
[#2978]: https://github.com/tokio-rs/axum/pull/2978
[#2992]: https://github.com/tokio-rs/axum/pull/2992
# 0.7.7
- **change**: Remove manual tables of content from the documentation, since
rustdoc now generates tables of content in the sidebar ([#2921])
[#2921]: https://github.com/tokio-rs/axum/pull/2921
# 0.7.6
- **change:** Avoid cloning `Arc` during deserialization of `Path`
- **added:** `axum::serve::Serve::tcp_nodelay` and `axum::serve::WithGracefulShutdown::tcp_nodelay` ([#2653])
- **added:** `Router::has_routes` function ([#2790])
- **change:** Update tokio-tungstenite to 0.23 ([#2841])
- **added:** `Serve::local_addr` and `WithGracefulShutdown::local_addr` functions ([#2881])
[#2653]: https://github.com/tokio-rs/axum/pull/2653
[#2790]: https://github.com/tokio-rs/axum/pull/2790
[#2841]: https://github.com/tokio-rs/axum/pull/2841
[#2881]: https://github.com/tokio-rs/axum/pull/2881
# 0.7.5 (24. March, 2024)
- **fixed:** Fixed layers being cloned when calling `axum::serve` directly with
a `Router` or `MethodRouter` ([#2586])
- **fixed:** `h2` is no longer pulled as a dependency unless the `http2` feature
is enabled ([#2605])
- **added:** Add `#[debug_middleware]` ([#1993], [#2725])
[#1993]: https://github.com/tokio-rs/axum/pull/1993
[#2725]: https://github.com/tokio-rs/axum/pull/2725
[#2586]: https://github.com/tokio-rs/axum/pull/2586
[#2605]: https://github.com/tokio-rs/axum/pull/2605
# 0.7.4 (13. January, 2024)
- **fixed:** Fix performance regression present since axum 0.7.0 ([#2483])
- **fixed:** Improve `debug_handler` on tuple response types ([#2201])
- **added:** Add `must_use` attribute to `Serve` and `WithGracefulShutdown` ([#2484])
- **added:** Re-export `axum_core::body::BodyDataStream` from axum
[#2201]: https://github.com/tokio-rs/axum/pull/2201
[#2483]: https://github.com/tokio-rs/axum/pull/2483
[#2484]: https://github.com/tokio-rs/axum/pull/2484
# 0.7.3 (29. December, 2023)
- **added:** `Body` implements `From<()>` now ([#2411])
- **change:** Update version of multer used internally for multipart ([#2433])
- **change:** Update tokio-tungstenite to 0.21 ([#2435])
- **added:** Enable `tracing` feature by default ([#2460])
- **added:** Support graceful shutdown on `serve` ([#2398])
- **added:** `RouterIntoService` implements `Clone` ([#2456])
[#2411]: https://github.com/tokio-rs/axum/pull/2411
[#2433]: https://github.com/tokio-rs/axum/pull/2433
[#2435]: https://github.com/tokio-rs/axum/pull/2435
[#2460]: https://github.com/tokio-rs/axum/pull/2460
[#2398]: https://github.com/tokio-rs/axum/pull/2398
[#2456]: https://github.com/tokio-rs/axum/pull/2456
# 0.7.2 (03. December, 2023)
- **added:** Add `axum::body::to_bytes` ([#2373])
- **fixed:** Gracefully handle accept errors in `serve` ([#2400])
[#2373]: https://github.com/tokio-rs/axum/pull/2373
[#2400]: https://github.com/tokio-rs/axum/pull/2400
# 0.7.1 (27. November, 2023)
- **fix**: Fix readme.
# 0.7.0 (27. November, 2023)
- **breaking:** Update public dependencies. axum now requires
- [hyper](https://crates.io/crates/hyper) 1.0
- [http](https://crates.io/crates/http) 1.0
- [http-body](https://crates.io/crates/http-body) 1.0
- **breaking:** axum now requires [tower-http](https://crates.io/crates/tower-http) 0.5
- **breaking:** Remove deprecated `WebSocketUpgrade::max_send_queue`
- **breaking:** The following types/traits are no longer generic over the request body
(i.e. the `B` type param has been removed) ([#1751] and [#1789]):
- `FromRequestParts`
- `FromRequest`
- `HandlerService`
- `HandlerWithoutStateExt`
- `Handler`
- `LayeredFuture`
- `Layered`
- `MethodRouter`
- `Next`
- `RequestExt`
- `RouteFuture`
- `Route`
- `Router`
- **breaking:** axum no longer re-exports `hyper::Body` as that type is removed
in hyper 1.0. Instead axum has its own body type at `axum::body::Body` ([#1751])
- **breaking:** `extract::BodyStream` has been removed as `body::Body`
implements `Stream` and `FromRequest` directly ([#1751])
- **breaking:** Change `sse::Event::json_data` to use `axum_core::Error` as its error type ([#1762])
- **breaking:** Rename `DefaultOnFailedUpdgrade` to `DefaultOnFailedUpgrade` ([#1664])
- **breaking:** Rename `OnFailedUpdgrade` to `OnFailedUpgrade` ([#1664])
- **breaking:** `TypedHeader` has been moved to `axum-extra` as `axum_extra::TypedHeader` and requires enabling the `typed-header` feature on `axum-extra`. The `headers` feature has been removed from axum; what it provided under `axum::headers` is now found in `axum_extra::headers` by default. ([#1850])
- **breaking:** Removed re-exports of `Empty` and `Full`. Use
`axum::body::Body::empty` and `axum::body::Body::from` respectively ([#1789])
- **breaking:** The response returned by `IntoResponse::into_response` must use
`axum::body::Body` as the body type. `axum::response::Response` does this
([#1789])
- **breaking:** Removed the `BoxBody` type alias and its `box_body`
constructor. Use `axum::body::Body::new` instead ([#1789])
- **breaking:** Remove `RawBody` extractor. `axum::body::Body` implements `FromRequest` directly ([#1789])
- **breaking:** The following types from `http-body` no longer implement `IntoResponse`:
- `Full`, use `Body::from` instead
- `Empty`, use `Body::empty` instead
- `BoxBody`, use `Body::new` instead
- `UnsyncBoxBody`, use `Body::new` instead
- `MapData`, use `Body::new` instead
- `MapErr`, use `Body::new` instead
- **added:** Add `axum::extract::Request` type alias where the body is `axum::body::Body` ([#1789])
- **added:** Add `Router::as_service` and `Router::into_service` to workaround
type inference issues when calling `ServiceExt` methods on a `Router` ([#1835])
- **breaking:** Removed `axum::Server` as it was removed in hyper 1.0. Instead
use `axum::serve(listener, service)` or hyper/hyper-util for more configuration options ([#1868])
- **breaking:** Only inherit fallbacks for routers nested with `Router::nest`.
Routers nested with `Router::nest_service` will no longer inherit fallbacks ([#1956])
- **fixed:** Don't remove the `Sec-WebSocket-Key` header in `WebSocketUpgrade` ([#1972])
- **added:** Add `axum::extract::Query::try_from_uri` ([#2058])
- **added:** Implement `IntoResponse` for `Box<str>` and `Box<[u8]>` ([#2035])
- **breaking:** Simplify `MethodFilter`. It no longer uses bitflags ([#2073])
- **fixed:** Fix bugs around merging routers with nested fallbacks ([#2096])
- **fixed:** Fix `.source()` of composite rejections ([#2030])
- **fixed:** Allow unreachable code in `#[debug_handler]` ([#2014])
- **change:** axum's MSRV is now 1.66 ([#1882])
- **added:** Implement `IntoResponse` for `(R,) where R: IntoResponse` ([#2143])
- **changed:** For SSE, add space between field and value for compatibility ([#2149])
- **added:** Add `NestedPath` extractor ([#1924])
- **added:** Add `handle_error` function to existing `ServiceExt` trait ([#2235])
- **breaking:** `impl<T> IntoResponse(Parts) for Extension<T>` now requires
`T: Clone`, as that is required by the http crate ([#1882])
- **added:** Add `axum::Json::from_bytes` ([#2244])
- **added:** Implement `FromRequestParts` for `http::request::Parts` ([#2328])
- **added:** Implement `FromRequestParts` for `http::Extensions` ([#2328])
- **fixed:** Clearly document applying `DefaultBodyLimit` to individual routes ([#2157])
[#1664]: https://github.com/tokio-rs/axum/pull/1664
[#1751]: https://github.com/tokio-rs/axum/pull/1751
[#1762]: https://github.com/tokio-rs/axum/pull/1762
[#1789]: https://github.com/tokio-rs/axum/pull/1789
[#1835]: https://github.com/tokio-rs/axum/pull/1835
[#1850]: https://github.com/tokio-rs/axum/pull/1850
[#1868]: https://github.com/tokio-rs/axum/pull/1868
[#1882]: https://github.com/tokio-rs/axum/pull/1882
[#1924]: https://github.com/tokio-rs/axum/pull/1924
[#1956]: https://github.com/tokio-rs/axum/pull/1956
[#1972]: https://github.com/tokio-rs/axum/pull/1972
[#2014]: https://github.com/tokio-rs/axum/pull/2014
[#2021]: https://github.com/tokio-rs/axum/pull/2021
[#2030]: https://github.com/tokio-rs/axum/pull/2030
[#2058]: https://github.com/tokio-rs/axum/pull/2058
[#2073]: https://github.com/tokio-rs/axum/pull/2073
[#2096]: https://github.com/tokio-rs/axum/pull/2096
[#2140]: https://github.com/tokio-rs/axum/pull/2140
[#2143]: https://github.com/tokio-rs/axum/pull/2143
[#2149]: https://github.com/tokio-rs/axum/pull/2149
[#2157]: https://github.com/tokio-rs/axum/pull/2157
[#2235]: https://github.com/tokio-rs/axum/pull/2235
[#2244]: https://github.com/tokio-rs/axum/pull/2244
[#2328]: https://github.com/tokio-rs/axum/pull/2328
# 0.6.20 (03. August, 2023)
- **added:** `WebSocketUpgrade::write_buffer_size` and `WebSocketUpgrade::max_write_buffer_size`
- **changed:** Deprecate `WebSocketUpgrade::max_send_queue`
- **change:** Update tokio-tungstenite to 0.20
- **added:** Implement `Handler` for `T: IntoResponse` ([#2140])
[#2140]: https://github.com/tokio-rs/axum/pull/2140
# 0.6.19 (17. July, 2023)
- **added:** Add `axum::extract::Query::try_from_uri` ([#2058])
- **added:** Implement `IntoResponse` for `Box<str>` and `Box<[u8]>` ([#2035])
- **fixed:** Fix bugs around merging routers with nested fallbacks ([#2096])
- **fixed:** Fix `.source()` of composite rejections ([#2030])
- **fixed:** Allow unreachable code in `#[debug_handler]` ([#2014])
- **change:** Update tokio-tungstenite to 0.19 ([#2021])
- **change:** axum's MSRV is now 1.63 ([#2021])
[#2014]: https://github.com/tokio-rs/axum/pull/2014
[#2021]: https://github.com/tokio-rs/axum/pull/2021
[#2030]: https://github.com/tokio-rs/axum/pull/2030
[#2035]: https://github.com/tokio-rs/axum/pull/2035
[#2058]: https://github.com/tokio-rs/axum/pull/2058
[#2096]: https://github.com/tokio-rs/axum/pull/2096
# 0.6.18 (30. April, 2023)
- **fixed:** Don't remove the `Sec-WebSocket-Key` header in `WebSocketUpgrade` ([#1972])
[#1972]: https://github.com/tokio-rs/axum/pull/1972
# 0.6.17 (25. April, 2023)
- **fixed:** Fix fallbacks causing a panic on `CONNECT` requests ([#1958])
[#1958]: https://github.com/tokio-rs/axum/pull/1958
# 0.6.16 (18. April, 2023)
- **fixed:** Don't allow extracting `MatchedPath` in fallbacks ([#1934])
- **fixed:** Fix panic if `Router` with something nested at `/` was used as a fallback ([#1934])
- **added:** Document that `Router::new().fallback(...)` isn't optimal ([#1940])
[#1934]: https://github.com/tokio-rs/axum/pull/1934
[#1940]: https://github.com/tokio-rs/axum/pull/1940
# 0.6.15 (12. April, 2023)
- **fixed:** Removed additional leftover debug messages ([#1927])
[#1927]: https://github.com/tokio-rs/axum/pull/1927
# 0.6.14 (11. April, 2023)
- **fixed:** Removed leftover "path_router hit" debug message ([#1925])
[#1925]: https://github.com/tokio-rs/axum/pull/1925
# 0.6.13 (11. April, 2023)
- **added:** Log rejections from built-in extractors with the
`axum::rejection=trace` target ([#1890])
- **fixed:** Fixed performance regression with `Router::nest` introduced in
0.6.0. `nest` now flattens the routes which performs better ([#1711])
- **fixed:** Extracting `MatchedPath` in nested handlers now gives the full
matched path, including the nested path ([#1711])
- **added:** Implement `Deref` and `DerefMut` for built-in extractors ([#1922])
[#1711]: https://github.com/tokio-rs/axum/pull/1711
[#1890]: https://github.com/tokio-rs/axum/pull/1890
[#1922]: https://github.com/tokio-rs/axum/pull/1922
# 0.6.12 (22. March, 2023)
- **added:** Implement `IntoResponse` for `MultipartError` ([#1861])
- **fixed:** More clearly document what wildcards matches ([#1873])
[#1861]: https://github.com/tokio-rs/axum/pull/1861
[#1873]: https://github.com/tokio-rs/axum/pull/1873
# 0.6.11 (13. March, 2023)
- **fixed:** Don't require `S: Debug` for `impl Debug for Router<S>` ([#1836])
- **fixed:** Clone state a bit less when handling requests ([#1837])
- **fixed:** Unpin itoa dependency ([#1815])
[#1815]: https://github.com/tokio-rs/axum/pull/1815
[#1836]: https://github.com/tokio-rs/axum/pull/1836
[#1837]: https://github.com/tokio-rs/axum/pull/1837
# 0.6.10 (03. March, 2023)
- **fixed:** Add `#[must_use]` attributes to types that do nothing unless used ([#1809])
- **fixed:** Gracefully handle missing headers in the `TypedHeader` extractor ([#1810])
- **fixed:** Fix routing issues when loading a `Router` via a dynamic library ([#1806])
[#1806]: https://github.com/tokio-rs/axum/pull/1806
[#1809]: https://github.com/tokio-rs/axum/pull/1809
[#1810]: https://github.com/tokio-rs/axum/pull/1810
# 0.6.9 (24. February, 2023)
- **changed:** Update to tower-http 0.4. axum is still compatible with tower-http 0.3 ([#1783])
[#1783]: https://github.com/tokio-rs/axum/pull/1783
# 0.6.8 (24. February, 2023)
- **fixed:** Fix `Allow` missing from routers with middleware ([#1773])
- **added:** Add `KeepAlive::event` for customizing the event sent for SSE keep alive ([#1729])
[#1729]: https://github.com/tokio-rs/axum/pull/1729
[#1773]: https://github.com/tokio-rs/axum/pull/1773
# 0.6.7 (17. February, 2023)
- **added:** Add `FormRejection::FailedToDeserializeFormBody` which is returned
if the request body couldn't be deserialized into the target type, as opposed
to `FailedToDeserializeForm` which is only for query parameters ([#1683])
- **added:** Add `MockConnectInfo` for setting `ConnectInfo` during tests ([#1767])
[#1683]: https://github.com/tokio-rs/axum/pull/1683
[#1767]: https://github.com/tokio-rs/axum/pull/1767
# 0.6.6 (12. February, 2023)
- **fixed:** Enable passing `MethodRouter` to `Router::fallback` ([#1730])
[#1730]: https://github.com/tokio-rs/axum/pull/1730
# 0.6.5 (11. February, 2023)
- **fixed:** Fix `#[debug_handler]` sometimes giving wrong borrow related suggestions ([#1710])
- Document gotchas related to using `impl IntoResponse` as the return type from handler functions ([#1736])
[#1710]: https://github.com/tokio-rs/axum/pull/1710
[#1736]: https://github.com/tokio-rs/axum/pull/1736
# 0.6.4 (22. January, 2023)
- Depend on axum-macros 0.3.2
# 0.6.3 (20. January, 2023)
- **added:** Implement `IntoResponse` for `&'static [u8; N]` and `[u8; N]` ([#1690])
- **fixed:** Make `Path` support types using `serde::Deserializer::deserialize_any` ([#1693])
- **added:** Add `RawPathParams` ([#1713])
- **added:** Implement `Clone` and `Service` for `axum::middleware::Next` ([#1712])
- **fixed:** Document required tokio features to run "Hello, World!" example ([#1715])
[#1690]: https://github.com/tokio-rs/axum/pull/1690
[#1693]: https://github.com/tokio-rs/axum/pull/1693
[#1712]: https://github.com/tokio-rs/axum/pull/1712
[#1713]: https://github.com/tokio-rs/axum/pull/1713
[#1715]: https://github.com/tokio-rs/axum/pull/1715
# 0.6.2 (9. January, 2023)
- **added:** Add `body_text` and `status` methods to built-in rejections ([#1612])
- **added:** Enable the `runtime` feature of `hyper` when using `tokio` ([#1671])
[#1612]: https://github.com/tokio-rs/axum/pull/1612
[#1671]: https://github.com/tokio-rs/axum/pull/1671
# 0.6.1 (29. November, 2022)
- **added:** Expand the docs for `Router::with_state` ([#1580])
[#1580]: https://github.com/tokio-rs/axum/pull/1580
# 0.6.0 (25. November, 2022)
## Routing
- **fixed:** Nested routers are now allowed to have fallbacks ([#1521]):
```rust
let api_router = Router::new()
.route("/users", get(|| { ... }))
.fallback(api_fallback);
let app = Router::new()
// this would panic in 0.5 but in 0.6 it just works
//
// requests starting with `/api` but not handled by `api_router`
// will go to `api_fallback`
.nest("/api", api_router);
```
The outer router's fallback will still apply if a nested router doesn't have
its own fallback:
```rust
// this time without a fallback
let api_router = Router::new().route("/users", get(|| { ... }));
let app = Router::new()
.nest("/api", api_router)
// `api_router` will inherit this fallback
.fallback(app_fallback);
```
- **breaking:** The request `/foo/` no longer matches `/foo/*rest`. If you want
to match `/foo/` you have to add a route specifically for that ([#1086])
For example:
```rust
use axum::{Router, routing::get, extract::Path};
let app = Router::new()
// this will match `/foo/bar/baz`
.route("/foo/*rest", get(handler))
// this will match `/foo/`
.route("/foo/", get(handler))
// if you want `/foo` to match you must also add an explicit route for it
.route("/foo", get(handler));
async fn handler(
// use an `Option` because `/foo/` and `/foo` don't have any path params
params: Option<Path<String>>,
) {}
```
- **breaking:** Path params for wildcard routes no longer include the prefix
`/`. e.g. `/foo.js` will match `/*filepath` with a value of `foo.js`, _not_
`/foo.js` ([#1086])
For example:
```rust
use axum::{Router, routing::get, extract::Path};
let app = Router::new().route("/foo/*rest", get(handler));
async fn handler(
Path(params): Path<String>,
) {
// for the request `/foo/bar/baz` the value of `params` will be `bar/baz`
//
// on 0.5 it would be `/bar/baz`
}
```
- **fixed:** Routes like `/foo` and `/*rest` are no longer considered
overlapping. `/foo` will take priority ([#1086])
For example:
```rust
use axum::{Router, routing::get};
let app = Router::new()
// this used to not be allowed but now just works
.route("/foo/*rest", get(foo))
.route("/foo/bar", get(bar));
async fn foo() {}
async fn bar() {}
```
- **breaking:** Automatic trailing slash redirects have been removed.
Previously if you added a route for `/foo`, axum would redirect calls to
`/foo/` to `/foo` (or vice versa for `/foo/`):
```rust
use axum::{Router, routing::get};
let app = Router::new()
// a request to `GET /foo/` will now get `404 Not Found`
// whereas in 0.5 axum would redirect to `/foo`
//
// same goes the other way if you had the route `/foo/`
// axum will no longer redirect from `/foo` to `/foo/`
.route("/foo", get(handler));
async fn handler() {}
```
Either explicitly add routes for `/foo` and `/foo/` or use
`axum_extra::routing::RouterExt::route_with_tsr` if you want the old behavior
([#1119])
- **breaking:** `Router::fallback` now only accepts `Handler`s (similarly to
what `get`, `post`, etc. accept). Use the new `Router::fallback_service` for
setting any `Service` as the fallback ([#1155])
This fallback on 0.5:
```rust
use axum::{Router, handler::Handler};
let app = Router::new().fallback(fallback.into_service());
async fn fallback() {}
```
Becomes this in 0.6
```rust
use axum::Router;
let app = Router::new().fallback(fallback);
async fn fallback() {}
```
- **breaking:** It is no longer supported to `nest` twice at the same path, i.e.
`.nest("/foo", a).nest("/foo", b)` will panic. Instead use `.nest("/foo", a.merge(b))`
- **breaking:** It is no longer supported to `nest` a router and add a route at
the same path, such as `.nest("/a", _).route("/a", _)`. Instead use
`.nest("/a/", _).route("/a", _)`.
- **changed:** `Router::nest` now only accepts `Router`s, the general-purpose
`Service` nesting method has been renamed to `nest_service` ([#1368])
- **breaking:** Allow `Error: Into<Infallible>` for `Route::{layer, route_layer}` ([#924])
- **breaking:** `MethodRouter` now panics on overlapping routes ([#1102])
- **breaking:** `Router::route` now only accepts `MethodRouter`s created with
`get`, `post`, etc. Use the new `Router::route_service` for routing to
any `Service`s ([#1155])
- **breaking:** Adding a `.route_layer` onto a `Router` or `MethodRouter`
without any routes will now result in a panic. Previously, this just did
nothing. [#1327]
- **breaking:** `RouterService` has been removed since `Router` now implements
`Service` when the state is `()`. Use `Router::with_state` to provide the
state and get a `Router<()>`. Note that `RouterService` only existed in the
pre-releases, not 0.5 ([#1552])
## Extractors
- **added:** Added new type safe `State` extractor. This can be used with
`Router::with_state` and gives compile errors for missing states, whereas
`Extension` would result in runtime errors ([#1155])
We recommend migrating from `Extension` to `State` for sharing application state since that is more type
safe and faster. That is done by using `Router::with_state` and `State`.
This setup in 0.5
```rust
use axum::{routing::get, Extension, Router};
let app = Router::new()
.route("/", get(handler))
.layer(Extension(AppState {}));
async fn handler(Extension(app_state): Extension<AppState>) {}
#[derive(Clone)]
struct AppState {}
```
Becomes this in 0.6 using `State`:
```rust
use axum::{routing::get, extract::State, Router};
let app = Router::new()
.route("/", get(handler))
.with_state(AppState {});
async fn handler(State(app_state): State<AppState>) {}
#[derive(Clone)]
struct AppState {}
```
If you have multiple extensions, you can use fields on `AppState` and implement
`FromRef`:
```rust
use axum::{extract::{State, FromRef}, routing::get, Router};
let state = AppState {
client: HttpClient {},
database: Database {},
};
let app = Router::new().route("/", get(handler)).with_state(state);
async fn handler(
State(client): State<HttpClient>,
State(database): State<Database>,
) {}
// the derive requires enabling the "macros" feature
#[derive(Clone, FromRef)]
struct AppState {
client: HttpClient,
database: Database,
}
#[derive(Clone)]
struct HttpClient {}
#[derive(Clone)]
struct Database {}
```
- **breaking:** It is now only possible for one extractor per handler to consume
the request body. In 0.5 doing so would result in runtime errors but in 0.6 it
is a compile error ([#1272])
axum enforces this by only allowing the _last_ extractor to consume the
request.
For example:
```rust
use axum::{Json, http::HeaderMap};
// This won't compile on 0.6 because both `Json` and `String` need to consume
// the request body. You can use either `Json` or `String`, but not both.
async fn handler_1(
json: Json<serde_json::Value>,
string: String,
) {}
// This won't work either since `Json` is not the last extractor.
async fn handler_2(
json: Json<serde_json::Value>,
headers: HeaderMap,
) {}
// This works!
async fn handler_3(
headers: HeaderMap,
json: Json<serde_json::Value>,
) {}
```
This is done by reworking the `FromRequest` trait and introducing a new
`FromRequestParts` trait.
If your extractor needs to consume the request body then you should implement
`FromRequest`, otherwise implement `FromRequestParts`.
This extractor in 0.5:
```rust
struct MyExtractor { /* ... */ }
impl<B> FromRequest<B> for MyExtractor
where
B: Send,
{
type Rejection = StatusCode;
async fn from_request(req: &mut RequestParts<B>) -> Result<Self, Self::Rejection> {
// ...
}
}
```
Becomes this in 0.6:
```rust
use axum::{
extract::{FromRequest, FromRequestParts},
http::{StatusCode, Request, request::Parts},
};
struct MyExtractor { /* ... */ }
// implement `FromRequestParts` if you don't need to consume the request body
impl<S> FromRequestParts<S> for MyExtractor
where
S: Send + Sync,
{
type Rejection = StatusCode;
async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> {
// ...
}
}
// implement `FromRequest` if you do need to consume the request body
impl<S, B> FromRequest<S, B> for MyExtractor
where
S: Send + Sync,
B: Send + 'static,
{
type Rejection = StatusCode;
async fn from_request(req: Request<B>, state: &S) -> Result<Self, Self::Rejection> {
// ...
}
}
```
For an example of how to write an extractor that accepts different
`Content-Types` see the [`parse-body-based-on-content-type`] example.
- **added:** `FromRequest` and `FromRequestParts` derive macro re-exports from
[`axum-macros`] behind the `macros` feature ([#1352])
- **added:** Add `RequestExt` and `RequestPartsExt` which adds convenience
methods for running extractors to `http::Request` and `http::request::Parts` ([#1301])
- **added**: `JsonRejection` now displays the path at which a deserialization
error occurred ([#1371])
- **added:** Add `extract::RawForm` for accessing raw urlencoded query bytes or request body ([#1487])
- **fixed:** Used `400 Bad Request` for `FailedToDeserializeQueryString`
rejections, instead of `422 Unprocessable Entity` ([#1387])
- **changed**: The inner error of a `JsonRejection` is now
`serde_path_to_error::Error<serde_json::Error>`. Previously it was
`serde_json::Error` ([#1371])
- **changed:** The default body limit now applies to the `Multipart` extractor ([#1420])
- **breaking:** `ContentLengthLimit` has been removed. Use `DefaultBodyLimit` instead ([#1400])
- **breaking:** `RequestParts` has been removed as part of the `FromRequest`
rework ([#1272])
- **breaking:** `BodyAlreadyExtracted` has been removed ([#1272])
- **breaking:** The following types or traits have a new `S` type param
which represents the state ([#1155]):
- `Router`, defaults to `()`
- `MethodRouter`, defaults to `()`
- `FromRequest`, no default
- `Handler`, no default
- **breaking:** `MatchedPath` can now no longer be extracted in middleware for
nested routes. In previous versions it returned invalid data when extracted
from a middleware applied to a nested router. `MatchedPath` can still be
extracted from handlers and middleware that aren't on nested routers ([#1462])
- **breaking:** Rename `FormRejection::FailedToDeserializeQueryString` to
`FormRejection::FailedToDeserializeForm` ([#1496])
## Middleware
- **added:** Support running extractors on `middleware::from_fn` functions ([#1088])
- **added**: Add `middleware::from_fn_with_state` to enable running extractors that require
state ([#1342])
- **added:** Add `middleware::from_extractor_with_state` ([#1396])
- **added:** Add `map_request`, `map_request_with_state` for transforming the
request with an async function ([#1408])
- **added:** Add `map_response`, `map_response_with_state` for transforming the
response with an async function ([#1414])
- **added:** Support any middleware response that implements `IntoResponse` ([#1152])
- **breaking:** Remove `extractor_middleware` which was previously deprecated.
Use `axum::middleware::from_extractor` instead ([#1077])
- **breaking:** Require middleware added with `Handler::layer` to have
`Infallible` as the error type ([#1152])
## Misc
- **added:** Support compiling to WASM. See the `simple-router-wasm` example
for more details ([#1382])
- **added:** Add `ServiceExt` with methods for turning any `Service` into a
`MakeService` similarly to `Router::into_make_service` ([#1302])
- **added:** String and binary `From` impls have been added to `extract::ws::Message`
to be more inline with `tungstenite` ([#1421])
- **added:** Add `#[derive(axum::extract::FromRef)]` ([#1430])
- **added:** Add `accept_unmasked_frames` setting in WebSocketUpgrade ([#1529])
- **added:** Add `WebSocketUpgrade::on_failed_upgrade` to customize what to do
when upgrading a connection fails ([#1539])
- **fixed:** Annotate panicking functions with `#[track_caller]` so the error
message points to where the user added the invalid route, rather than
somewhere internally in axum ([#1248])
- **changed:** axum's MSRV is now 1.60 ([#1239])
- **changed:** For methods that accept some `S: Service`, the bounds have been
relaxed so the response type must implement `IntoResponse` rather than being a
literal `Response`
- **breaking:** New `tokio` default feature needed for WASM support. If you
don't need WASM support but have `default_features = false` for other reasons
you likely need to re-enable the `tokio` feature ([#1382])
- **breaking:** `handler::{WithState, IntoService}` are merged into one type,
named `HandlerService` ([#1418])
[#924]: https://github.com/tokio-rs/axum/pull/924
[#1077]: https://github.com/tokio-rs/axum/pull/1077
[#1086]: https://github.com/tokio-rs/axum/pull/1086
[#1088]: https://github.com/tokio-rs/axum/pull/1088
[#1102]: https://github.com/tokio-rs/axum/pull/1102
[#1119]: https://github.com/tokio-rs/axum/pull/1119
[#1152]: https://github.com/tokio-rs/axum/pull/1152
[#1155]: https://github.com/tokio-rs/axum/pull/1155
[#1239]: https://github.com/tokio-rs/axum/pull/1239
[#1248]: https://github.com/tokio-rs/axum/pull/1248
[#1272]: https://github.com/tokio-rs/axum/pull/1272
[#1301]: https://github.com/tokio-rs/axum/pull/1301
[#1302]: https://github.com/tokio-rs/axum/pull/1302
[#1327]: https://github.com/tokio-rs/axum/pull/1327
[#1342]: https://github.com/tokio-rs/axum/pull/1342
[#1346]: https://github.com/tokio-rs/axum/pull/1346
[#1352]: https://github.com/tokio-rs/axum/pull/1352
[#1368]: https://github.com/tokio-rs/axum/pull/1368
[#1371]: https://github.com/tokio-rs/axum/pull/1371
[#1382]: https://github.com/tokio-rs/axum/pull/1382
[#1387]: https://github.com/tokio-rs/axum/pull/1387
[#1389]: https://github.com/tokio-rs/axum/pull/1389
[#1396]: https://github.com/tokio-rs/axum/pull/1396
[#1397]: https://github.com/tokio-rs/axum/pull/1397
[#1400]: https://github.com/tokio-rs/axum/pull/1400
[#1408]: https://github.com/tokio-rs/axum/pull/1408
[#1414]: https://github.com/tokio-rs/axum/pull/1414
[#1418]: https://github.com/tokio-rs/axum/pull/1418
[#1420]: https://github.com/tokio-rs/axum/pull/1420
[#1421]: https://github.com/tokio-rs/axum/pull/1421
[#1430]: https://github.com/tokio-rs/axum/pull/1430
[#1462]: https://github.com/tokio-rs/axum/pull/1462
[#1487]: https://github.com/tokio-rs/axum/pull/1487
[#1496]: https://github.com/tokio-rs/axum/pull/1496
[#1521]: https://github.com/tokio-rs/axum/pull/1521
[#1529]: https://github.com/tokio-rs/axum/pull/1529
[#1532]: https://github.com/tokio-rs/axum/pull/1532
[#1539]: https://github.com/tokio-rs/axum/pull/1539
[#1552]: https://github.com/tokio-rs/axum/pull/1552
[`axum-macros`]: https://docs.rs/axum-macros/latest/axum_macros/
[`parse-body-based-on-content-type`]: https://github.com/tokio-rs/axum/blob/main/examples/parse-body-based-on-content-type/src/main.rs
<details>
<summary>0.6.0 Pre-Releases</summary>
# 0.6.0-rc.5 (18. November, 2022)
- **breaking:** `Router::with_state` is no longer a constructor. It is instead
used to convert the router into a `RouterService` ([#1532])
This nested router on 0.6.0-rc.4
```rust
Router::with_state(state).route(...);
```
Becomes this in 0.6.0-rc.5
```rust
Router::new().route(...).with_state(state);
```
- **breaking:** `Router::inherit_state` has been removed. Use
`Router::with_state` instead ([#1532])
- **breaking:** `Router::nest` and `Router::merge` now only supports nesting
routers that use the same state type as the router they're being merged into.
Use `FromRef` for substates ([#1532])
- **added:** Add `accept_unmasked_frames` setting in WebSocketUpgrade ([#1529])
- **fixed:** Nested routers will now inherit fallbacks from outer routers ([#1521])
- **added:** Add `WebSocketUpgrade::on_failed_upgrade` to customize what to do
when upgrading a connection fails ([#1539])
[#1521]: https://github.com/tokio-rs/axum/pull/1521
[#1529]: https://github.com/tokio-rs/axum/pull/1529
[#1532]: https://github.com/tokio-rs/axum/pull/1532
[#1539]: https://github.com/tokio-rs/axum/pull/1539
# 0.6.0-rc.4 (9. November, 2022)
- **changed**: The inner error of a `JsonRejection` is now
`serde_path_to_error::Error<serde_json::Error>`. Previously it was
`serde_json::Error` ([#1371])
- **added**: `JsonRejection` now displays the path at which a deserialization
error occurred ([#1371])
- **fixed:** Support streaming/chunked requests in `ContentLengthLimit` ([#1389])
- **fixed:** Used `400 Bad Request` for `FailedToDeserializeQueryString`
rejections, instead of `422 Unprocessable Entity` ([#1387])
- **added:** Add `middleware::from_extractor_with_state` ([#1396])
- **added:** Add `DefaultBodyLimit::max` for changing the default body limit ([#1397])
- **added:** Add `map_request`, `map_request_with_state` for transforming the
request with an async function ([#1408])
- **added:** Add `map_response`, `map_response_with_state` for transforming the
response with an async function ([#1414])
- **breaking:** `ContentLengthLimit` has been removed. Use `DefaultBodyLimit` instead ([#1400])
- **changed:** `Router` no longer implements `Service`, call `.into_service()`
on it to obtain a `RouterService` that does ([#1368])
- **added:** Add `Router::inherit_state`, which creates a `Router` with an
arbitrary state type without actually supplying the state; such a `Router`
can't be turned into a service directly (`.into_service()` will panic), but
can be nested or merged into a `Router` with the same state type ([#1368])
- **changed:** `Router::nest` now only accepts `Router`s, the general-purpose
`Service` nesting method has been renamed to `nest_service` ([#1368])
- **added:** Support compiling to WASM. See the `simple-router-wasm` example
for more details ([#1382])
- **breaking:** New `tokio` default feature needed for WASM support. If you
don't need WASM support but have `default_features = false` for other reasons
you likely need to re-enable the `tokio` feature ([#1382])
- **breaking:** `handler::{WithState, IntoService}` are merged into one type,
named `HandlerService` ([#1418])
- **changed:** The default body limit now applies to the `Multipart` extractor ([#1420])
- **added:** String and binary `From` impls have been added to `extract::ws::Message`
to be more inline with `tungstenite` ([#1421])
- **added:** Add `#[derive(axum::extract::FromRef)]` ([#1430])
- **added:** `FromRequest` and `FromRequestParts` derive macro re-exports from
[`axum-macros`] behind the `macros` feature ([#1352])
- **breaking:** `MatchedPath` can now no longer be extracted in middleware for
nested routes ([#1462])
- **added:** Add `extract::RawForm` for accessing raw urlencoded query bytes or request body ([#1487])
- **breaking:** Rename `FormRejection::FailedToDeserializeQueryString` to
`FormRejection::FailedToDeserializeForm` ([#1496])
[#1352]: https://github.com/tokio-rs/axum/pull/1352
[#1368]: https://github.com/tokio-rs/axum/pull/1368
[#1371]: https://github.com/tokio-rs/axum/pull/1371
[#1382]: https://github.com/tokio-rs/axum/pull/1382
[#1387]: https://github.com/tokio-rs/axum/pull/1387
[#1389]: https://github.com/tokio-rs/axum/pull/1389
[#1396]: https://github.com/tokio-rs/axum/pull/1396
[#1397]: https://github.com/tokio-rs/axum/pull/1397
[#1400]: https://github.com/tokio-rs/axum/pull/1400
[#1408]: https://github.com/tokio-rs/axum/pull/1408
[#1414]: https://github.com/tokio-rs/axum/pull/1414
[#1418]: https://github.com/tokio-rs/axum/pull/1418
[#1420]: https://github.com/tokio-rs/axum/pull/1420
[#1421]: https://github.com/tokio-rs/axum/pull/1421
[#1430]: https://github.com/tokio-rs/axum/pull/1430
[#1462]: https://github.com/tokio-rs/axum/pull/1462
[#1487]: https://github.com/tokio-rs/axum/pull/1487
[#1496]: https://github.com/tokio-rs/axum/pull/1496
# 0.6.0-rc.3 (8. November, 2022)
Yanked, as it didn't compile in release mode.
# 0.6.0-rc.2 (10. September, 2022)
## Security
- **breaking:** Added default limit to how much data `Bytes::from_request` will
consume. Previously it would attempt to consume the entire request body
without checking its length. This meant if a malicious peer sent an large (or
infinite) request body your server might run out of memory and crash.
The default limit is at 2 MB and can be disabled by adding the new
`DefaultBodyLimit::disable()` middleware. See its documentation for more
details.
This also applies to these extractors which used `Bytes::from_request`
internally:
- `Form`
- `Json`
- `String`
([#1346])
## Routing
- **breaking:** Adding a `.route_layer` onto a `Router` or `MethodRouter`
without any routes will now result in a panic. Previously, this just did
nothing. [#1327]
[`axum-macros`]: https://docs.rs/axum-macros/latest/axum_macros/
## Middleware
- **added**: Add `middleware::from_fn_with_state` and
`middleware::from_fn_with_state_arc` to enable running extractors that require
state ([#1342])
[#1327]: https://github.com/tokio-rs/axum/pull/1327
[#1342]: https://github.com/tokio-rs/axum/pull/1342
[#1346]: https://github.com/tokio-rs/axum/pull/1346
# 0.6.0-rc.1 (23. August, 2022)
## Routing
- **breaking:** Nested `Router`s will no longer delegate to the outer `Router`'s
fallback. Instead you must explicitly set a fallback on the inner `Router` ([#1086])
This nested router on 0.5:
```rust
use axum::{Router, handler::Handler};
let api_routes = Router::new();
let app = Router::new()
.nest("/api", api_routes)
.fallback(fallback.into_service());
async fn fallback() {}
```
Becomes this in 0.6:
```rust
use axum::Router;
let api_routes = Router::new()
// we have to explicitly set the fallback here
// since nested routers no longer delegate to the outer
// router's fallback
.fallback(fallback);
let app = Router::new()
.nest("/api", api_routes)
.fallback(fallback);
async fn fallback() {}
```
- **breaking:** The request `/foo/` no longer matches `/foo/*rest`. If you want
to match `/foo/` you have to add a route specifically for that ([#1086])
For example:
```rust
use axum::{Router, routing::get, extract::Path};
let app = Router::new()
// this will match `/foo/bar/baz`
.route("/foo/*rest", get(handler))
// this will match `/foo/`
.route("/foo/", get(handler))
// if you want `/foo` to match you must also add an explicit route for it
.route("/foo", get(handler));
async fn handler(
// use an `Option` because `/foo/` and `/foo` don't have any path params
params: Option<Path<String>>,
) {}
```
- **breaking:** Path params for wildcard routes no longer include the prefix
`/`. e.g. `/foo.js` will match `/*filepath` with a value of `foo.js`, _not_
`/foo.js` ([#1086])
For example:
```rust
use axum::{Router, routing::get, extract::Path};
let app = Router::new().route("/foo/*rest", get(handler));
async fn handler(
Path(params): Path<String>,
) {
// for the request `/foo/bar/baz` the value of `params` will be `bar/baz`
//
// on 0.5 it would be `/bar/baz`
}
```
- **fixed:** Routes like `/foo` and `/*rest` are no longer considered
overlapping. `/foo` will take priority ([#1086])
For example:
```rust
use axum::{Router, routing::get};
let app = Router::new()
// this used to not be allowed but now just works
.route("/foo/*rest", get(foo))
.route("/foo/bar", get(bar));
async fn foo() {}
async fn bar() {}
```
- **breaking:** Trailing slash redirects have been removed. Previously if you
added a route for `/foo`, axum would redirect calls to `/foo/` to `/foo` (or
vice versa for `/foo/`). That is no longer supported and such requests will
now be sent to the fallback. Consider using
`axum_extra::routing::RouterExt::route_with_tsr` if you want the old behavior
([#1119])
For example:
```rust
use axum::{Router, routing::get};
let app = Router::new()
// a request to `GET /foo/` will now get `404 Not Found`
// whereas in 0.5 axum would redirect to `/foo`
//
// same goes the other way if you had the route `/foo/`
// axum will no longer redirect from `/foo` to `/foo/`
.route("/foo", get(handler));
async fn handler() {}
```
- **breaking:** `Router::fallback` now only accepts `Handler`s (similarly to
what `get`, `post`, etc accept). Use the new `Router::fallback_service` for
setting any `Service` as the fallback ([#1155])
This fallback on 0.5:
```rust
use axum::{Router, handler::Handler};
let app = Router::new().fallback(fallback.into_service());
async fn fallback() {}
```
Becomes this in 0.6
```rust
use axum::Router;
let app = Router::new().fallback(fallback);
async fn fallback() {}
```
- **breaking:** Allow `Error: Into<Infallible>` for `Route::{layer, route_layer}` ([#924])
- **breaking:** `MethodRouter` now panics on overlapping routes ([#1102])
- **breaking:** `Router::route` now only accepts `MethodRouter`s created with
`get`, `post`, etc. Use the new `Router::route_service` for routing to
any `Service`s ([#1155])
## Extractors
- **added:** Added new type safe `State` extractor. This can be used with
`Router::with_state` and gives compile errors for missing states, whereas
`Extension` would result in runtime errors ([#1155])
We recommend migrating from `Extension` to `State` since that is more type
safe and faster. That is done by using `Router::with_state` and `State`.
This setup in 0.5
```rust
use axum::{routing::get, Extension, Router};
let app = Router::new()
.route("/", get(handler))
.layer(Extension(AppState {}));
async fn handler(Extension(app_state): Extension<AppState>) {}
#[derive(Clone)]
struct AppState {}
```
Becomes this in 0.6 using `State`:
```rust
use axum::{routing::get, extract::State, Router};
let app = Router::with_state(AppState {})
.route("/", get(handler));
async fn handler(State(app_state): State<AppState>) {}
#[derive(Clone)]
struct AppState {}
```
If you have multiple extensions you can use fields on `AppState` and implement
`FromRef`:
```rust
use axum::{extract::{State, FromRef}, routing::get, Router};
let state = AppState {
client: HttpClient {},
database: Database {},
};
let app = Router::with_state(state).route("/", get(handler));
async fn handler(
State(client): State<HttpClient>,
State(database): State<Database>,
) {}
#[derive(Clone)]
struct AppState {
client: HttpClient,
database: Database,
}
#[derive(Clone)]
struct HttpClient {}
impl FromRef<AppState> for HttpClient {
fn from_ref(state: &AppState) -> Self {
state.client.clone()
}
}
#[derive(Clone)]
struct Database {}
impl FromRef<AppState> for Database {
fn from_ref(state: &AppState) -> Self {
state.database.clone()
}
}
```
- **breaking:** It is now only possible for one extractor per handler to consume
the request body. In 0.5 doing so would result in runtime errors but in 0.6 it
is a compile error ([#1272])
axum enforces this by only allowing the _last_ extractor to consume the
request.
For example:
```rust
use axum::{Json, http::HeaderMap};
// This won't compile on 0.6 because both `Json` and `String` need to consume
// the request body. You can use either `Json` or `String`, but not both.
async fn handler_1(
json: Json<serde_json::Value>,
string: String,
) {}
// This won't work either since `Json` is not the last extractor.
async fn handler_2(
json: Json<serde_json::Value>,
headers: HeaderMap,
) {}
// This works!
async fn handler_3(
headers: HeaderMap,
json: Json<serde_json::Value>,
) {}
```
This is done by reworking the `FromRequest` trait and introducing a new
`FromRequestParts` trait.
If your extractor needs to consume the request body then you should implement
`FromRequest`, otherwise implement `FromRequestParts`.
This extractor in 0.5:
```rust
struct MyExtractor { /* ... */ }
impl<B> FromRequest<B> for MyExtractor
where
B: Send,
{
type Rejection = StatusCode;
async fn from_request(req: &mut RequestParts<B>) -> Result<Self, Self::Rejection> {
// ...
}
}
```
Becomes this in 0.6:
```rust
use axum::{
extract::{FromRequest, FromRequestParts},
http::{StatusCode, Request, request::Parts},
};
struct MyExtractor { /* ... */ }
// implement `FromRequestParts` if you don't need to consume the request body
impl<S> FromRequestParts<S> for MyExtractor
where
S: Send + Sync,
{
type Rejection = StatusCode;
async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> {
// ...
}
}
// implement `FromRequest` if you do need to consume the request body
impl<S, B> FromRequest<S, B> for MyExtractor
where
S: Send + Sync,
B: Send + 'static,
{
type Rejection = StatusCode;
async fn from_request(req: Request<B>, state: &S) -> Result<Self, Self::Rejection> {
// ...
}
}
```
- **breaking:** `RequestParts` has been removed as part of the `FromRequest`
rework ([#1272])
- **breaking:** `BodyAlreadyExtracted` has been removed ([#1272])
- **breaking:** The following types or traits have a new `S` type param
which represents the state ([#1155]):
- `Router`, defaults to `()`
- `MethodRouter`, defaults to `()`
- `FromRequest`, no default
- `Handler`, no default
- **added:** Add `RequestExt` and `RequestPartsExt` which adds convenience
methods for running extractors to `http::Request` and `http::request::Parts` ([#1301])
## Middleware
- **breaking:** Remove `extractor_middleware` which was previously deprecated.
Use `axum::middleware::from_extractor` instead ([#1077])
- **added:** Support running extractors on `middleware::from_fn` functions ([#1088])
- **added:** Support any middleware response that implements `IntoResponse` ([#1152])
- **breaking:** Require middleware added with `Handler::layer` to have
`Infallible` as the error type ([#1152])
## Misc
- **changed:** axum's MSRV is now 1.60 ([#1239])
- **changed:** For methods that accept some `S: Service`, the bounds have been
relaxed so the response type must implement `IntoResponse` rather than being a
literal `Response`
- **fixed:** Annotate panicking functions with `#[track_caller]` so the error
message points to where the user added the invalid route, rather than
somewhere internally in axum ([#1248])
- **added:** Add `ServiceExt` with methods for turning any `Service` into a
`MakeService` similarly to `Router::into_make_service` ([#1302])
[#1077]: https://github.com/tokio-rs/axum/pull/1077
[#1086]: https://github.com/tokio-rs/axum/pull/1086
[#1088]: https://github.com/tokio-rs/axum/pull/1088
[#1102]: https://github.com/tokio-rs/axum/pull/1102
[#1119]: https://github.com/tokio-rs/axum/pull/1119
[#1152]: https://github.com/tokio-rs/axum/pull/1152
[#1155]: https://github.com/tokio-rs/axum/pull/1155
[#1239]: https://github.com/tokio-rs/axum/pull/1239
[#1248]: https://github.com/tokio-rs/axum/pull/1248
[#1272]: https://github.com/tokio-rs/axum/pull/1272
[#1301]: https://github.com/tokio-rs/axum/pull/1301
[#1302]: https://github.com/tokio-rs/axum/pull/1302
[#924]: https://github.com/tokio-rs/axum/pull/924
</details>
# 0.5.16 (10. September, 2022)
## Security
- **breaking:** Added default limit to how much data `Bytes::from_request` will
consume. Previously it would attempt to consume the entire request body
without checking its length. This meant if a malicious peer sent an large (or
infinite) request body your server might run out of memory and crash.
The default limit is at 2 MB and can be disabled by adding the new
`DefaultBodyLimit::disable()` middleware. See its documentation for more
details.
This also applies to these extractors which used `Bytes::from_request`
internally:
- `Form`
- `Json`
- `String`
([#1346])
[#1346]: https://github.com/tokio-rs/axum/pull/1346
# 0.5.15 (9. August, 2022)
- **fixed:** Don't expose internal type names in `QueryRejection` response. ([#1171])
- **fixed:** Improve performance of JSON serialization ([#1178])
- **fixed:** Improve build times by generating less IR ([#1192])
[#1171]: https://github.com/tokio-rs/axum/pull/1171
[#1178]: https://github.com/tokio-rs/axum/pull/1178
[#1192]: https://github.com/tokio-rs/axum/pull/1192
# 0.5.14 (25. July, 2022)
Yanked, as it contained an accidental breaking change.
# 0.5.13 (15. July, 2022)
- **fixed:** If `WebSocketUpgrade` cannot upgrade the connection it will return a
`WebSocketUpgradeRejection::ConnectionNotUpgradable` rejection ([#1135])
- **changed:** `WebSocketUpgradeRejection` has a new variant `ConnectionNotUpgradable`
variant ([#1135])
[#1135]: https://github.com/tokio-rs/axum/pull/1135
# 0.5.12 (10. July, 2022)
- **added:** Added `debug_handler` which is an attribute macro that improves
type errors when applied to handler function. It is re-exported from
`axum-macros` ([#1144])
[#1144]: https://github.com/tokio-rs/axum/pull/1144
# 0.5.11 (02. July, 2022)
- **added:** Implement `TryFrom<http::Method>` for `MethodFilter` and use new
`NoMatchingMethodFilter` error in case of failure ([#1130])
- **added:** Document how to run extractors from middleware ([#1140])
[#1130]: https://github.com/tokio-rs/axum/pull/1130
[#1140]: https://github.com/tokio-rs/axum/pull/1140
# 0.5.10 (28. June, 2022)
- **fixed:** Make `Router` cheaper to clone ([#1123])
- **fixed:** Fix possible panic when doing trailing slash redirect ([#1124])
[#1123]: https://github.com/tokio-rs/axum/pull/1123
[#1124]: https://github.com/tokio-rs/axum/pull/1124
# 0.5.9 (20. June, 2022)
- **fixed:** Fix compile error when the `headers` is enabled and the `form`
feature is disabled ([#1107])
[#1107]: https://github.com/tokio-rs/axum/pull/1107
# 0.5.8 (18. June, 2022)
- **added:** Support resolving host name via `Forwarded` header in `Host`
extractor ([#1078])
- **added:** Implement `IntoResponse` for `Form` ([#1095])
- **changed:** axum's MSRV is now 1.56 ([#1098])
[#1078]: https://github.com/tokio-rs/axum/pull/1078
[#1095]: https://github.com/tokio-rs/axum/pull/1095
[#1098]: https://github.com/tokio-rs/axum/pull/1098
# 0.5.7 (08. June, 2022)
- **added:** Implement `Default` for `Extension` ([#1043])
- **fixed:** Support deserializing `Vec<(String, String)>` in `extract::Path<_>` to get vector of
key/value pairs ([#1059])
- **added:** Add `extract::ws::close_code` which contains constants for close codes ([#1067])
- **fixed:** Use `impl IntoResponse` less in docs ([#1049])
[#1043]: https://github.com/tokio-rs/axum/pull/1043
[#1049]: https://github.com/tokio-rs/axum/pull/1049
[#1059]: https://github.com/tokio-rs/axum/pull/1059
[#1067]: https://github.com/tokio-rs/axum/pull/1067
# 0.5.6 (15. May, 2022)
- **added:** Add `WebSocket::protocol` to return the selected WebSocket subprotocol, if there is one. ([#1022])
- **fixed:** Improve error message for `PathRejection::WrongNumberOfParameters` to hint at using
`Path<(String, String)>` or `Path<SomeStruct>` ([#1023])
- **fixed:** `PathRejection::WrongNumberOfParameters` now uses `500 Internal Server Error` since
it's a programmer error and not a client error ([#1023])
- **fixed:** Fix `InvalidFormContentType` mentioning the wrong content type
[#1022]: https://github.com/tokio-rs/axum/pull/1022
[#1023]: https://github.com/tokio-rs/axum/pull/1023
# 0.5.5 (10. May, 2022)
- **fixed:** Correctly handle `GET`, `HEAD`, and `OPTIONS` requests in `ContentLengthLimit`.
Request with these methods are now accepted if they _do not_ have a `Content-Length` header, and
the request body will not be checked. If they do have a `Content-Length` header they'll be
rejected. This allows `ContentLengthLimit` to be used as middleware around several routes,
including `GET` routes ([#989])
- **added:** Add `MethodRouter::{into_make_service, into_make_service_with_connect_info}` ([#1010])
[#989]: https://github.com/tokio-rs/axum/pull/989
[#1010]: https://github.com/tokio-rs/axum/pull/1010
# 0.5.4 (26. April, 2022)
- **added:** Add `response::ErrorResponse` and `response::Result` for
`IntoResponse`-based error handling ([#921])
- **added:** Add `middleware::from_extractor` and deprecate `extract::extractor_middleware` ([#957])
- **changed:** Update to tower-http 0.3 ([#965])
[#921]: https://github.com/tokio-rs/axum/pull/921
[#957]: https://github.com/tokio-rs/axum/pull/957
[#965]: https://github.com/tokio-rs/axum/pull/965
# 0.5.3 (19. April, 2022)
- **added:** Add `AppendHeaders` for appending headers to a response rather than overriding them ([#927])
- **added:** Add `axum::extract::multipart::Field::chunk` method for streaming a single chunk from
the field ([#901])
- **fixed:** Fix trailing slash redirection with query parameters ([#936])
[#901]: https://github.com/tokio-rs/axum/pull/901
[#927]: https://github.com/tokio-rs/axum/pull/927
[#936]: https://github.com/tokio-rs/axum/pull/936
# 0.5.2 (19. April, 2022)
Yanked, as it contained an accidental breaking change.
# 0.5.1 (03. April, 2022)
- **added:** Add `RequestParts::extract` which allows applying an extractor as a method call ([#897])
[#897]: https://github.com/tokio-rs/axum/pull/897
# 0.5.0 (31. March, 2022)
- **added:** Document sharing state between handler and middleware ([#783])
- **added:** `Extension<_>` can now be used in tuples for building responses, and will set an
extension on the response ([#797])
- **added:** `extract::Host` for extracting the hostname of a request ([#827])
- **added:** Add `IntoResponseParts` trait which allows defining custom response
types for adding headers or extensions to responses ([#797])
- **added:** `TypedHeader` implements the new `IntoResponseParts` trait so they
can be returned from handlers as parts of a response ([#797])
- **changed:** `Router::merge` now accepts `Into<Router>` ([#819])
- **breaking:** `sse::Event` now accepts types implementing `AsRef<str>` instead of `Into<String>`
as field values.
- **breaking:** `sse::Event` now panics if a setter method is called twice instead of silently
overwriting old values.
- **breaking:** Require `Output = ()` on `WebSocketStream::on_upgrade` ([#644])
- **breaking:** Make `TypedHeaderRejectionReason` `#[non_exhaustive]` ([#665])
- **breaking:** Using `HeaderMap` as an extractor will no longer remove the headers and thus
they'll still be accessible to other extractors, such as `axum::extract::Json`. Instead
`HeaderMap` will clone the headers. You should prefer to use `TypedHeader` to extract only the
headers you need ([#698])
This includes these breaking changes:
- `RequestParts::take_headers` has been removed.
- `RequestParts::headers` returns `&HeaderMap`.
- `RequestParts::headers_mut` returns `&mut HeaderMap`.
- `HeadersAlreadyExtracted` has been removed.
- The `HeadersAlreadyExtracted` variant has been removed from these rejections:
- `RequestAlreadyExtracted`
- `RequestPartsAlreadyExtracted`
- `JsonRejection`
- `FormRejection`
- `ContentLengthLimitRejection`
- `WebSocketUpgradeRejection`
- `<HeaderMap as FromRequest<_>>::Rejection` has been changed to `std::convert::Infallible`.
- **breaking:** `axum::http::Extensions` is no longer an extractor (ie it
doesn't implement `FromRequest`). The `axum::extract::Extension` extractor is
_not_ impacted by this and works the same. This change makes it harder to
accidentally remove all extensions which would result in confusing errors
elsewhere ([#699])
This includes these breaking changes:
- `RequestParts::take_extensions` has been removed.
- `RequestParts::extensions` returns `&Extensions`.
- `RequestParts::extensions_mut` returns `&mut Extensions`.
- `RequestAlreadyExtracted` has been removed.
- `<Request as FromRequest>::Rejection` is now `BodyAlreadyExtracted`.
- `<http::request::Parts as FromRequest>::Rejection` is now `Infallible`.
- `ExtensionsAlreadyExtracted` has been removed.
- The `ExtensionsAlreadyExtracted` removed variant has been removed from these rejections:
- `ExtensionRejection`
- `PathRejection`
- `MatchedPathRejection`
- `WebSocketUpgradeRejection`
- **breaking:** `Redirect::found` has been removed ([#800])
- **breaking:** `AddExtensionLayer` has been removed. Use `Extension` instead. It now implements
`tower::Layer` ([#807])
- **breaking:** `AddExtension` has been moved from the root module to `middleware`
- **breaking:** `.nest("/foo/", Router::new().route("/bar", _))` now does the right thing and
results in a route at `/foo/bar` instead of `/foo//bar` ([#824])
- **breaking:** Routes are now required to start with `/`. Previously routes such as `:foo` would
be accepted but most likely result in bugs ([#823])
- **breaking:** `Headers` has been removed. Arrays of tuples directly implement
`IntoResponseParts` so `([("x-foo", "foo")], response)` now works ([#797])
- **breaking:** `InvalidJsonBody` has been replaced with `JsonDataError` to clearly signal that the
request body was syntactically valid JSON but couldn't be deserialized into the target type
- **breaking:** `Handler` is no longer an `#[async_trait]` but instead has an
associated `Future` type. That allows users to build their own `Handler` types
without paying the cost of `#[async_trait]` ([#879])
- **changed:** New `JsonSyntaxError` variant added to `JsonRejection`. This is returned when the
request body contains syntactically invalid JSON
- **fixed:** Correctly set the `Content-Length` header for response to `HEAD`
requests ([#734])
- **fixed:** Fix wrong `content-length` for `HEAD` requests to endpoints that returns chunked
responses ([#755])
- **fixed:** Fixed several routing bugs related to nested "opaque" tower services (i.e.
non-`Router` services) ([#841] and [#842])
- **changed:** Update to tokio-tungstenite 0.17 ([#791])
- **breaking:** `Redirect::{to, temporary, permanent}` now accept `&str` instead
of `Uri` ([#889])
- **breaking:** Remove second type parameter from `Router::into_make_service_with_connect_info`
and `Handler::into_make_service_with_connect_info` to support `MakeService`s
that accept multiple targets ([#892])
[#644]: https://github.com/tokio-rs/axum/pull/644
[#665]: https://github.com/tokio-rs/axum/pull/665
[#698]: https://github.com/tokio-rs/axum/pull/698
[#699]: https://github.com/tokio-rs/axum/pull/699
[#734]: https://github.com/tokio-rs/axum/pull/734
[#755]: https://github.com/tokio-rs/axum/pull/755
[#783]: https://github.com/tokio-rs/axum/pull/783
[#791]: https://github.com/tokio-rs/axum/pull/791
[#797]: https://github.com/tokio-rs/axum/pull/797
[#800]: https://github.com/tokio-rs/axum/pull/800
[#807]: https://github.com/tokio-rs/axum/pull/807
[#819]: https://github.com/tokio-rs/axum/pull/819
[#823]: https://github.com/tokio-rs/axum/pull/823
[#824]: https://github.com/tokio-rs/axum/pull/824
[#827]: https://github.com/tokio-rs/axum/pull/827
[#841]: https://github.com/tokio-rs/axum/pull/841
[#842]: https://github.com/tokio-rs/axum/pull/842
[#879]: https://github.com/tokio-rs/axum/pull/879
[#889]: https://github.com/tokio-rs/axum/pull/889
[#892]: https://github.com/tokio-rs/axum/pull/892
# 0.4.8 (2. March, 2022)
- Use correct path for `AddExtensionLayer` and `AddExtension::layer` deprecation
notes ([#812])
[#812]: https://github.com/tokio-rs/axum/pull/812
# 0.4.7 (1. March, 2022)
- **added:** Implement `tower::Layer` for `Extension` ([#801])
- **changed:** Deprecate `AddExtensionLayer`. Use `Extension` instead ([#805])
[#801]: https://github.com/tokio-rs/axum/pull/801
[#805]: https://github.com/tokio-rs/axum/pull/805
# 0.4.6 (22. February, 2022)
- **added:** `middleware::from_fn` for creating middleware from async functions.
This previously lived in axum-extra but has been moved to axum ([#719])
- **fixed:** Set `Allow` header when responding with `405 Method Not Allowed` ([#733])
[#719]: https://github.com/tokio-rs/axum/pull/719
[#733]: https://github.com/tokio-rs/axum/pull/733
# 0.4.5 (31. January, 2022)
- Reference [axum-macros] instead of [axum-debug]. The latter has been superseded by
axum-macros and is deprecated ([#738])
[#738]: https://github.com/tokio-rs/axum/pull/738
[axum-debug]: https://docs.rs/axum-debug
[axum-macros]: https://docs.rs/axum-macros
# 0.4.4 (13. January, 2022)
- **fixed:** Fix using incorrect path prefix when nesting `Router`s at `/` ([#691])
- **fixed:** Make `nest("", service)` work and mean the same as `nest("/", service)` ([#691])
- **fixed:** Replace response code `301` with `308` for trailing slash redirects. Also deprecates
`Redirect::found` (`302`) in favor of `Redirect::temporary` (`307`) or `Redirect::to` (`303`).
This is to prevent clients from changing non-`GET` requests to `GET` requests ([#682])
[#691]: https://github.com/tokio-rs/axum/pull/691
[#682]: https://github.com/tokio-rs/axum/pull/682
# 0.4.3 (21. December, 2021)
- **added:** `axum::AddExtension::layer` ([#607])
- **added:** Re-export the headers crate when the headers feature is active ([#630])
- **fixed:** `sse::Event` will no longer drop the leading space of data, event ID and name values
that have it ([#600])
- **fixed:** `sse::Event` is more strict about what field values it supports, disallowing any SSE
events that break the specification (such as field values containing carriage returns) ([#599])
- **fixed:** Improve documentation of `sse::Event` ([#601])
- **fixed:** Make `Path` fail with `ExtensionsAlreadyExtracted` if another extractor (such as
`Request`) has previously taken the request extensions. Thus `PathRejection` now contains a
variant with `ExtensionsAlreadyExtracted`. This is not a breaking change since `PathRejection` is
marked as `#[non_exhaustive]` ([#619])
- **fixed:** Fix misleading error message for `PathRejection` if extensions had
previously been extracted ([#619])
- **fixed:** Use `AtomicU32` internally, rather than `AtomicU64`, to improve portability ([#616])
[#599]: https://github.com/tokio-rs/axum/pull/599
[#600]: https://github.com/tokio-rs/axum/pull/600
[#601]: https://github.com/tokio-rs/axum/pull/601
[#607]: https://github.com/tokio-rs/axum/pull/607
[#616]: https://github.com/tokio-rs/axum/pull/616
[#619]: https://github.com/tokio-rs/axum/pull/619
[#619]: https://github.com/tokio-rs/axum/pull/619
[#630]: https://github.com/tokio-rs/axum/pull/630
# 0.4.2 (06. December, 2021)
- **fix:** Depend on the correct version of `axum-core` ([#592])
[#592]: https://github.com/tokio-rs/axum/pull/592
# 0.4.1 (06. December, 2021)
- **added:** `axum::response::Response` now exists as a shorthand for writing `Response<BoxBody>` ([#590])
[#590]: https://github.com/tokio-rs/axum/pull/590
# 0.4.0 (02. December, 2021)
- **breaking:** New `MethodRouter` that works similarly to `Router`:
- Route to handlers and services with the same type
- Add middleware to some routes more easily with `MethodRouter::layer` and
`MethodRouter::route_layer`.
- Merge method routers with `MethodRouter::merge`
- Customize response for unsupported methods with `MethodRouter::fallback`
- **breaking:** The default for the type parameter in `FromRequest` and
`RequestParts` has been removed. Use `FromRequest<Body>` and
`RequestParts<Body>` to get the previous behavior ([#564])
- **added:** `FromRequest` and `IntoResponse` are now defined in a new called
`axum-core`. This crate is intended for library authors to depend on, rather
than `axum` itself, if possible. `axum-core` has a smaller API and will thus
receive fewer breaking changes. `FromRequest` and `IntoResponse` are
re-exported from `axum` in the same location so nothing is changed for `axum`
users ([#564])
- **breaking:** The previously deprecated `axum::body::box_body` function has
been removed. Use `axum::body::boxed` instead.
- **fixed:** Adding the same route with different methods now works ie
`.route("/", get(_)).route("/", post(_))`.
- **breaking:** `routing::handler_method_router` and
`routing::service_method_router` has been removed in favor of
`routing::{get, get_service, ..., MethodRouter}`.
- **breaking:** `HandleErrorExt` has been removed in favor of
`MethodRouter::handle_error`.
- **breaking:** `HandleErrorLayer` now requires the handler function to be
`async` ([#534])
- **added:** `HandleErrorLayer` now supports running extractors.
- **breaking:** The `Handler<B, T>` trait is now defined as `Handler<T, B =
Body>`. That is the type parameters have been swapped and `B` defaults to
`axum::body::Body` ([#527])
- **breaking:** `Router::merge` will panic if both routers have fallbacks.
Previously the left side fallback would be silently discarded ([#529])
- **breaking:** `Router::nest` will panic if the nested router has a fallback.
Previously it would be silently discarded ([#529])
- Update WebSockets to use tokio-tungstenite 0.16 ([#525])
- **added:** Default to return `charset=utf-8` for text content type. ([#554])
- **breaking:** The `Body` and `BodyError` associated types on the
`IntoResponse` trait have been removed - instead, `.into_response()` will now
always return `Response<BoxBody>` ([#571])
- **breaking:** `PathParamsRejection` has been renamed to `PathRejection` and its
variants renamed to `FailedToDeserializePathParams` and `MissingPathParams`. This
makes it more consistent with the rest of axum ([#574])
- **added:** `Path`'s rejection type now provides data about exactly which part of
the path couldn't be deserialized ([#574])
[#525]: https://github.com/tokio-rs/axum/pull/525
[#527]: https://github.com/tokio-rs/axum/pull/527
[#529]: https://github.com/tokio-rs/axum/pull/529
[#534]: https://github.com/tokio-rs/axum/pull/534
[#554]: https://github.com/tokio-rs/axum/pull/554
[#564]: https://github.com/tokio-rs/axum/pull/564
[#571]: https://github.com/tokio-rs/axum/pull/571
[#574]: https://github.com/tokio-rs/axum/pull/574
# 0.3.4 (13. November, 2021)
- **changed:** `box_body` has been renamed to `boxed`. `box_body` still exists
but is deprecated ([#530])
[#530]: https://github.com/tokio-rs/axum/pull/530
# 0.3.3 (13. November, 2021)
- Implement `FromRequest` for [`http::request::Parts`] so it can be used an
extractor ([#489])
- Implement `IntoResponse` for `http::response::Parts` ([#490])
[#489]: https://github.com/tokio-rs/axum/pull/489
[#490]: https://github.com/tokio-rs/axum/pull/490
[`http::request::Parts`]: https://docs.rs/http/latest/http/request/struct.Parts.html
# 0.3.2 (08. November, 2021)
- **added:** Add `Router::route_layer` for applying middleware that
will only run on requests that match a route. This is useful for middleware
that return early, such as authorization ([#474])
[#474]: https://github.com/tokio-rs/axum/pull/474
# 0.3.1 (06. November, 2021)
- **fixed:** Implement `Clone` for `IntoMakeServiceWithConnectInfo` ([#471])
[#471]: https://github.com/tokio-rs/axum/pull/471
# 0.3.0 (02. November, 2021)
- Overall:
- **fixed:** All known compile time issues are resolved, including those with
`boxed` and those introduced by Rust 1.56 ([#404])
- **breaking:** The router's type is now always `Router` regardless of how many routes or
middleware are applied ([#404])
This means router types are all always nameable:
```rust
fn my_routes() -> Router {
Router::new().route(
"/users",
post(|| async { "Hello, World!" }),
)
}
```
- **breaking:** Added feature flags for HTTP1 and JSON. This enables removing a
few dependencies if your app only uses HTTP2 or doesn't use JSON. This is only a
breaking change if you depend on axum with `default_features = false`. ([#286])
- **breaking:** `Route::boxed` and `BoxRoute` have been removed as they're no longer
necessary ([#404])
- **breaking:** `Nested`, `Or` types are now private. They no longer had to be
public because `Router` is internally boxed ([#404])
- **breaking:** Remove `routing::Layered` as it didn't actually do anything and
thus wasn't necessary
- **breaking:** Vendor `AddExtensionLayer` and `AddExtension` to reduce public
dependencies
- **breaking:** `body::BoxBody` is now a type alias for
`http_body::combinators::UnsyncBoxBody` and thus is no longer `Sync`. This
is because bodies are streams and requiring streams to be `Sync` is
unnecessary.
- **added:** Implement `IntoResponse` for `http_body::combinators::UnsyncBoxBody`.
- **added:** Add `Handler::into_make_service` for serving a handler without a
`Router`.
- **added:** Add `Handler::into_make_service_with_connect_info` for serving a
handler without a `Router`, and storing info about the incoming connection.
- **breaking:** axum's minimum supported rust version is now 1.56
- Routing:
- Big internal refactoring of routing leading to several improvements ([#363])
- **added:** Wildcard routes like `.route("/api/users/*rest", service)` are now supported.
- **fixed:** The order routes are added in no longer matters.
- **fixed:** Adding a conflicting route will now cause a panic instead of silently making
a route unreachable.
- **fixed:** Route matching is faster as number of routes increases.
- **breaking:** Handlers for multiple HTTP methods must be added in the same
`Router::route` call. So `.route("/", get(get_handler).post(post_handler))` and
_not_ `.route("/", get(get_handler)).route("/", post(post_handler))`.
- **fixed:** Correctly handle trailing slashes in routes:
- If a route with a trailing slash exists and a request without a trailing
slash is received, axum will send a 301 redirection to the route with the
trailing slash.
- Or vice versa if a route without a trailing slash exists and a request
with a trailing slash is received.
- This can be overridden by explicitly defining two routes: One with and one
without a trailing slash.
- **breaking:** Method routing for handlers has been moved from `axum::handler`
to `axum::routing`. So `axum::handler::get` now lives at `axum::routing::get`
([#405])
- **breaking:** Method routing for services has been moved from `axum::service`
to `axum::routing::service_method_routing`. So `axum::service::get` now lives at
`axum::routing::service_method_routing::get`, etc. ([#405])
- **breaking:** `Router::or` renamed to `Router::merge` and will now panic on
overlapping routes. It now only accepts `Router`s and not general `Service`s.
Use `Router::fallback` for adding fallback routes ([#408])
- **added:** `Router::fallback` for adding handlers for request that didn't
match any routes. `Router::fallback` must be use instead of `nest("/", _)` ([#408])
- **breaking:** `EmptyRouter` has been renamed to `MethodNotAllowed` as it's only
used in method routers and not in path routers (`Router`)
- **breaking:** Remove support for routing based on the `CONNECT` method. An
example of combining axum with and HTTP proxy can be found [here][proxy] ([#428])
- Extractors:
- **fixed:** Expand accepted content types for JSON requests ([#378])
- **fixed:** Support deserializing `i128` and `u128` in `extract::Path`
- **breaking:** Automatically do percent decoding in `extract::Path`
([#272])
- **breaking:** Change `Connected::connect_info` to return `Self` and remove
the associated type `ConnectInfo` ([#396])
- **added:** Add `extract::MatchedPath` for accessing path in router that
matched the request ([#412])
- Error handling:
- **breaking:** Simplify error handling model ([#402]):
- All services part of the router are now required to be infallible.
- Error handling utilities have been moved to an `error_handling` module.
- `Router::check_infallible` has been removed since routers are always
infallible with the error handling changes.
- Error handling closures must now handle all errors and thus always return
something that implements `IntoResponse`.
With these changes handling errors from fallible middleware is done like so:
```rust,no_run
use axum::{
routing::get,
http::StatusCode,
error_handling::HandleErrorLayer,
response::IntoResponse,
Router, BoxError,
};
use tower::ServiceBuilder;
use std::time::Duration;
let middleware_stack = ServiceBuilder::new()
// Handle errors from middleware
//
// This middleware most be added above any fallible
// ones if you're using `ServiceBuilder`, due to how ordering works
.layer(HandleErrorLayer::new(handle_error))
// Return an error after 30 seconds
.timeout(Duration::from_secs(30));
let app = Router::new()
.route("/", get(|| async { /* ... */ }))
.layer(middleware_stack);
fn handle_error(_error: BoxError) -> impl IntoResponse {
StatusCode::REQUEST_TIMEOUT
}
```
And handling errors from fallible leaf services is done like so:
```rust
use axum::{
Router, service,
body::Body,
routing::service_method_routing::get,
response::IntoResponse,
http::{Request, Response},
error_handling::HandleErrorExt, // for `.handle_error`
};
use std::{io, convert::Infallible};
use tower::service_fn;
let app = Router::new()
.route(
"/",
get(service_fn(|_req: Request<Body>| async {
let contents = tokio::fs::read_to_string("some_file").await?;
Ok::<_, io::Error>(Response::new(Body::from(contents)))
}))
.handle_error(handle_io_error),
);
fn handle_io_error(error: io::Error) -> impl IntoResponse {
// ...
}
```
- Misc:
- `InvalidWebsocketVersionHeader` has been renamed to `InvalidWebSocketVersionHeader` ([#416])
- `WebsocketKeyHeaderMissing` has been renamed to `WebSocketKeyHeaderMissing` ([#416])
[#339]: https://github.com/tokio-rs/axum/pull/339
[#286]: https://github.com/tokio-rs/axum/pull/286
[#272]: https://github.com/tokio-rs/axum/pull/272
[#378]: https://github.com/tokio-rs/axum/pull/378
[#363]: https://github.com/tokio-rs/axum/pull/363
[#396]: https://github.com/tokio-rs/axum/pull/396
[#402]: https://github.com/tokio-rs/axum/pull/402
[#404]: https://github.com/tokio-rs/axum/pull/404
[#405]: https://github.com/tokio-rs/axum/pull/405
[#408]: https://github.com/tokio-rs/axum/pull/408
[#412]: https://github.com/tokio-rs/axum/pull/412
[#416]: https://github.com/tokio-rs/axum/pull/416
[#428]: https://github.com/tokio-rs/axum/pull/428
[proxy]: https://github.com/tokio-rs/axum/blob/main/examples/http-proxy/src/main.rs
# 0.2.8 (07. October, 2021)
- Document debugging handler type errors with "axum-debug" ([#372])
[#372]: https://github.com/tokio-rs/axum/pull/372
# 0.2.7 (06. October, 2021)
- Bump minimum version of async-trait ([#370])
[#370]: https://github.com/tokio-rs/axum/pull/370
# 0.2.6 (02. October, 2021)
- Clarify that `handler::any` and `service::any` only accepts standard HTTP
methods ([#337])
- Document how to customize error responses from extractors ([#359])
[#337]: https://github.com/tokio-rs/axum/pull/337
[#359]: https://github.com/tokio-rs/axum/pull/359
# 0.2.5 (18. September, 2021)
- Add accessors for `TypedHeaderRejection` fields ([#317])
- Improve docs for extractors ([#327])
[#317]: https://github.com/tokio-rs/axum/pull/317
[#327]: https://github.com/tokio-rs/axum/pull/327
# 0.2.4 (10. September, 2021)
- Document using `StreamExt::split` with `WebSocket` ([#291])
- Document adding middleware to multiple groups of routes ([#293])
[#291]: https://github.com/tokio-rs/axum/pull/291
[#293]: https://github.com/tokio-rs/axum/pull/293
# 0.2.3 (26. August, 2021)
- **fixed:** Fix accidental breaking change introduced by internal refactor.
`BoxRoute` used to be `Sync` but was accidental made `!Sync` ([#273](https://github.com/tokio-rs/axum/pull/273))
# 0.2.2 (26. August, 2021)
- **fixed:** Fix URI captures matching empty segments. This means requests with
URI `/` will no longer be matched by `/:key` ([#264](https://github.com/tokio-rs/axum/pull/264))
- **fixed:** Remove needless trait bounds from `Router::boxed` ([#269](https://github.com/tokio-rs/axum/pull/269))
# 0.2.1 (24. August, 2021)
- **added:** Add `Redirect::to` constructor ([#255](https://github.com/tokio-rs/axum/pull/255))
- **added:** Document how to implement `IntoResponse` for custom error type ([#258](https://github.com/tokio-rs/axum/pull/258))
# 0.2.0 (23. August, 2021)
- Overall:
- **fixed:** Overall compile time improvements. If you're having issues with compile time
please file an issue! ([#184](https://github.com/tokio-rs/axum/pull/184)) ([#198](https://github.com/tokio-rs/axum/pull/198)) ([#220](https://github.com/tokio-rs/axum/pull/220))
- **changed:** Remove `prelude`. Explicit imports are now required ([#195](https://github.com/tokio-rs/axum/pull/195))
- Routing:
- **added:** Add dedicated `Router` to replace the `RoutingDsl` trait ([#214](https://github.com/tokio-rs/axum/pull/214))
- **added:** Add `Router::or` for combining routes ([#108](https://github.com/tokio-rs/axum/pull/108))
- **fixed:** Support matching different HTTP methods for the same route that aren't defined
together. So `Router::new().route("/", get(...)).route("/", post(...))` now
accepts both `GET` and `POST`. Previously only `POST` would be accepted ([#224](https://github.com/tokio-rs/axum/pull/224))
- **fixed:** `get` routes will now also be called for `HEAD` requests but will always have
the response body removed ([#129](https://github.com/tokio-rs/axum/pull/129))
- **changed:** Replace `axum::route(...)` with `axum::Router::new().route(...)`. This means
there is now only one way to create a new router. Same goes for
`axum::routing::nest`. ([#215](https://github.com/tokio-rs/axum/pull/215))
- **changed:** Implement `routing::MethodFilter` via [`bitflags`](https://crates.io/crates/bitflags) ([#158](https://github.com/tokio-rs/axum/pull/158))
- **changed:** Move `handle_error` from `ServiceExt` to `service::OnMethod` ([#160](https://github.com/tokio-rs/axum/pull/160))
With these changes this app using 0.1:
```rust
use axum::{extract::Extension, prelude::*, routing::BoxRoute, AddExtensionLayer};
let app = route("/", get(|| async { "hi" }))
.nest("/api", api_routes())
.layer(AddExtensionLayer::new(state));
fn api_routes() -> BoxRoute<Body> {
route(
"/users",
post(|Extension(state): Extension<State>| async { "hi from nested" }),
)
.boxed()
}
```
Becomes this in 0.2:
```rust
use axum::{
extract::Extension,
handler::{get, post},
routing::BoxRoute,
Router,
};
let app = Router::new()
.route("/", get(|| async { "hi" }))
.nest("/api", api_routes());
fn api_routes() -> Router<BoxRoute> {
Router::new()
.route(
"/users",
post(|Extension(state): Extension<State>| async { "hi from nested" }),
)
.boxed()
}
```
- Extractors:
- **added:** Make `FromRequest` default to being generic over `body::Body` ([#146](https://github.com/tokio-rs/axum/pull/146))
- **added:** Implement `std::error::Error` for all rejections ([#153](https://github.com/tokio-rs/axum/pull/153))
- **added:** Add `OriginalUri` for extracting original request URI in nested services ([#197](https://github.com/tokio-rs/axum/pull/197))
- **added:** Implement `FromRequest` for `http::Extensions` ([#169](https://github.com/tokio-rs/axum/pull/169))
- **added:** Make `RequestParts::{new, try_into_request}` public so extractors can be used outside axum ([#194](https://github.com/tokio-rs/axum/pull/194))
- **added:** Implement `FromRequest` for `axum::body::Body` ([#241](https://github.com/tokio-rs/axum/pull/241))
- **changed:** Removed `extract::UrlParams` and `extract::UrlParamsMap`. Use `extract::Path` instead ([#154](https://github.com/tokio-rs/axum/pull/154))
- **changed:** `extractor_middleware` now requires `RequestBody: Default` ([#167](https://github.com/tokio-rs/axum/pull/167))
- **changed:** Convert `RequestAlreadyExtracted` to an enum with each possible error variant ([#167](https://github.com/tokio-rs/axum/pull/167))
- **changed:** `extract::BodyStream` is no longer generic over the request body ([#234](https://github.com/tokio-rs/axum/pull/234))
- **changed:** `extract::Body` has been renamed to `extract::RawBody` to avoid conflicting with `body::Body` ([#233](https://github.com/tokio-rs/axum/pull/233))
- **changed:** `RequestParts` changes ([#153](https://github.com/tokio-rs/axum/pull/153))
- `method` new returns an `&http::Method`
- `method_mut` new returns an `&mut http::Method`
- `take_method` has been removed
- `uri` new returns an `&http::Uri`
- `uri_mut` new returns an `&mut http::Uri`
- `take_uri` has been removed
- **changed:** Remove several rejection types that were no longer used ([#153](https://github.com/tokio-rs/axum/pull/153)) ([#154](https://github.com/tokio-rs/axum/pull/154))
- Responses:
- **added:** Add `Headers` for easily customizing headers on a response ([#193](https://github.com/tokio-rs/axum/pull/193))
- **added:** Add `Redirect` response ([#192](https://github.com/tokio-rs/axum/pull/192))
- **added:** Add `body::StreamBody` for easily responding with a stream of byte chunks ([#237](https://github.com/tokio-rs/axum/pull/237))
- **changed:** Add associated `Body` and `BodyError` types to `IntoResponse`. This is
required for returning responses with bodies other than `hyper::Body` from
handlers. See the docs for advice on how to implement `IntoResponse` ([#86](https://github.com/tokio-rs/axum/pull/86))
- **changed:** `tower::util::Either` no longer implements `IntoResponse` ([#229](https://github.com/tokio-rs/axum/pull/229))
This `IntoResponse` from 0.1:
```rust
use axum::{http::Response, prelude::*, response::IntoResponse};
struct MyResponse;
impl IntoResponse for MyResponse {
fn into_response(self) -> Response<Body> {
Response::new(Body::empty())
}
}
```
Becomes this in 0.2:
```rust
use axum::{body::Body, http::Response, response::IntoResponse};
struct MyResponse;
impl IntoResponse for MyResponse {
type Body = Body;
type BodyError = <Self::Body as axum::body::HttpBody>::Error;
fn into_response(self) -> Response<Self::Body> {
Response::new(Body::empty())
}
}
```
- SSE:
- **added:** Add `response::sse::Sse`. This implements SSE using a response rather than a service ([#98](https://github.com/tokio-rs/axum/pull/98))
- **changed:** Remove `axum::sse`. It has been replaced by `axum::response::sse` ([#98](https://github.com/tokio-rs/axum/pull/98))
Handler using SSE in 0.1:
```rust
use axum::{
prelude::*,
sse::{sse, Event},
};
use std::convert::Infallible;
let app = route(
"/",
sse(|| async {
let stream = futures::stream::iter(vec![Ok::<_, Infallible>(
Event::default().data("hi there!"),
)]);
Ok::<_, Infallible>(stream)
}),
);
```
Becomes this in 0.2:
```rust
use axum::{
handler::get,
response::sse::{Event, Sse},
Router,
};
use std::convert::Infallible;
let app = Router::new().route(
"/",
get(|| async {
let stream = futures::stream::iter(vec![Ok::<_, Infallible>(
Event::default().data("hi there!"),
)]);
Sse::new(stream)
}),
);
```
- WebSockets:
- **changed:** Change WebSocket API to use an extractor plus a response ([#121](https://github.com/tokio-rs/axum/pull/121))
- **changed:** Make WebSocket `Message` an enum ([#116](https://github.com/tokio-rs/axum/pull/116))
- **changed:** `WebSocket` now uses `Error` as its error type ([#150](https://github.com/tokio-rs/axum/pull/150))
Handler using WebSockets in 0.1:
```rust
use axum::{
prelude::*,
ws::{ws, WebSocket},
};
let app = route(
"/",
ws(|socket: WebSocket| async move {
// do stuff with socket
}),
);
```
Becomes this in 0.2:
```rust
use axum::{
extract::ws::{WebSocket, WebSocketUpgrade},
handler::get,
Router,
};
let app = Router::new().route(
"/",
get(|ws: WebSocketUpgrade| async move {
ws.on_upgrade(|socket: WebSocket| async move {
// do stuff with socket
})
}),
);
```
- Misc
- **added:** Add default feature `tower-log` which exposes `tower`'s `log` feature. ([#218](https://github.com/tokio-rs/axum/pull/218))
- **changed:** Replace `body::BoxStdError` with `axum::Error`, which supports downcasting ([#150](https://github.com/tokio-rs/axum/pull/150))
- **changed:** `EmptyRouter` now requires the response body to implement `Send + Sync + 'static'` ([#108](https://github.com/tokio-rs/axum/pull/108))
- **changed:** `Router::check_infallible` now returns a `CheckInfallible` service. This
is to improve compile times ([#198](https://github.com/tokio-rs/axum/pull/198))
- **changed:** `Router::into_make_service` now returns `routing::IntoMakeService` rather than
`tower::make::Shared` ([#229](https://github.com/tokio-rs/axum/pull/229))
- **changed:** All usage of `tower::BoxError` has been replaced with `axum::BoxError` ([#229](https://github.com/tokio-rs/axum/pull/229))
- **changed:** Several response future types have been moved into dedicated
`future` modules ([#133](https://github.com/tokio-rs/axum/pull/133))
- **changed:** `EmptyRouter`, `ExtractorMiddleware`, `ExtractorMiddlewareLayer`,
and `QueryStringMissing` no longer implement `Copy` ([#132](https://github.com/tokio-rs/axum/pull/132))
- **changed:** `service::OnMethod`, `handler::OnMethod`, and `routing::Nested` have new response future types ([#157](https://github.com/tokio-rs/axum/pull/157))
# 0.1.3 (06. August, 2021)
- Fix stripping prefix when nesting services at `/` ([#91](https://github.com/tokio-rs/axum/pull/91))
- Add support for WebSocket protocol negotiation ([#83](https://github.com/tokio-rs/axum/pull/83))
- Use `pin-project-lite` instead of `pin-project` ([#95](https://github.com/tokio-rs/axum/pull/95))
- Re-export `http` crate and `hyper::Server` ([#110](https://github.com/tokio-rs/axum/pull/110))
- Fix `Query` and `Form` extractors giving bad request error when query string is empty. ([#117](https://github.com/tokio-rs/axum/pull/117))
- Add `Path` extractor. ([#124](https://github.com/tokio-rs/axum/pull/124))
- Fixed the implementation of `IntoResponse` of `(HeaderMap, T)` and `(StatusCode, HeaderMap, T)` would ignore headers from `T` ([#137](https://github.com/tokio-rs/axum/pull/137))
- Deprecate `extract::UrlParams` and `extract::UrlParamsMap`. Use `extract::Path` instead ([#138](https://github.com/tokio-rs/axum/pull/138))
# 0.1.2 (01. August, 2021)
- Implement `Stream` for `WebSocket` ([#52](https://github.com/tokio-rs/axum/pull/52))
- Implement `Sink` for `WebSocket` ([#52](https://github.com/tokio-rs/axum/pull/52))
- Implement `Deref` most extractors ([#56](https://github.com/tokio-rs/axum/pull/56))
- Return `405 Method Not Allowed` for unsupported method for route ([#63](https://github.com/tokio-rs/axum/pull/63))
- Add extractor for remote connection info ([#55](https://github.com/tokio-rs/axum/pull/55))
- Improve error message of `MissingExtension` rejections ([#72](https://github.com/tokio-rs/axum/pull/72))
- Improve documentation for routing ([#71](https://github.com/tokio-rs/axum/pull/71))
- Clarify required response body type when routing to `tower::Service`s ([#69](https://github.com/tokio-rs/axum/pull/69))
- Add `axum::body::box_body` to converting an `http_body::Body` to `axum::body::BoxBody` ([#69](https://github.com/tokio-rs/axum/pull/69))
- Add `axum::sse` for Server-Sent Events ([#75](https://github.com/tokio-rs/axum/pull/75))
- Mention required dependencies in docs ([#77](https://github.com/tokio-rs/axum/pull/77))
- Fix WebSockets failing on Firefox ([#76](https://github.com/tokio-rs/axum/pull/76))
# 0.1.1 (30. July, 2021)
- Misc readme fixes.
# 0.1.0 (30. July, 2021)
- Initial release.
================================================
FILE: axum/Cargo.toml
================================================
[package]
name = "axum"
version = "0.8.8" # remember to bump the version that axum-extra depends on
categories = ["asynchronous", "network-programming", "web-programming::http-server"]
description = "HTTP routing and request handling library that focuses on ergonomics and modularity"
edition = "2021"
rust-version = { workspace = true }
homepage = "https://github.com/tokio-rs/axum"
keywords = ["http", "web", "routing"]
license = "MIT"
readme = "README.md"
repository = "https://github.com/tokio-rs/axum"
[package.metadata.docs.rs]
all-features = true
[package.metadata.playground]
features = ["http1", "http2", "json", "multipart", "ws"]
[package.metadata.cargo_check_external_types]
allowed_external_types = [
# our crates
"axum_core::*",
"axum_macros::*",
# not 1.0
"futures_core::*",
"futures_sink::*",
"futures_util::*",
"tower_layer::*",
"tower_service::*",
# >=1.0
"bytes::*",
"http",
"http::*",
"http_body::*",
"serde_core::*",
"tokio::*",
]
[features]
default = [
"form",
"http1",
"json",
"matched-path",
"original-uri",
"query",
"tokio",
"tower-log",
"tracing",
]
form = [
"dep:form_urlencoded",
"dep:serde_html_form",
"dep:serde_path_to_error",
"serde_html_form/ser",
"serde_html_form/de",
]
http1 = ["dep:hyper", "hyper?/http1", "hyper-util?/http1"]
http2 = ["dep:hyper", "hyper?/http2", "hyper-util?/http2"]
json = ["dep:serde_json", "dep:serde_path_to_error"]
macros = ["dep:axum-macros"]
matched-path = []
multipart = ["dep:multer"]
original-uri = []
query = [
"dep:form_urlencoded",
"dep:serde_html_form",
"dep:serde_path_to_error",
"serde_html_form/de",
]
tokio = [
"dep:hyper-util",
"dep:tokio",
"tokio/net",
"tokio/rt",
"tower/make",
"tokio/macros",
]
tower-log = ["tower/log"]
tracing = ["dep:tracing", "axum-core/tracing"]
ws = [
"dep:hyper",
"dep:futures-sink",
"tokio",
"dep:tokio-tungstenite",
"dep:sha1",
"dep:base64",
]
__private_docs = [
# We re-export some docs from axum-core via #[doc(inline)],
# but they need the same sort of treatment as below to be complete
"axum-core/__private_docs",
# Enables upstream things linked to in docs
"tower/full",
"dep:serde",
"dep:tower-http",
]
# This feature is used to enable private test helper usage
# in `axum-core` and `axum-extra`.
__private = ["tokio", "http1", "dep:reqwest"]
[dependencies]
axum-core = { path = "../axum-core", version = "0.5.6" }
bytes = "1.7"
futures-core = "0.3"
futures-util = { version = "0.3", default-features = false, features = ["alloc"] }
http = "1.0.0"
http-body = "1.0.0"
http-body-util = "0.1.0"
itoa = "1.0.5"
matchit = "=0.8.4"
memchr = "2.4.1"
mime = "0.3.16"
percent-encoding = "2.1"
pin-project-lite = "0.2.7"
serde_core = "1.0.221"
sync_wrapper = "1.0.0"
tower = { version = "0.5.2", default-features = false, features = ["util"] }
tower-layer = "0.3.2"
tower-service = "0.3"
# optional dependencies
axum-macros = { path = "../axum-macros", version = "0.5.0", optional = true }
base64 = { version = "0.22.1", optional = true }
form_urlencoded = { version = "1.1.0", optional = true }
futures-sink = { version = "0.3", optional = true }
hyper = { version = "1.4.0", optional = true }
hyper-util = { version = "0.1.4", features = ["tokio", "server", "service"], optional = true }
multer = { version = "3.0.0", optional = true }
reqwest = { version = "0.12", optional = true, default-features = false, features = ["json", "stream", "multipart"] }
serde_html_form = { version = "0.4.0", optional = true, default-features = false, features = ["std"] }
serde_json = { version = "1.0.29", features = ["raw_value"], optional = true }
serde_path_to_error = { version = "0.1.8", optional = true }
sha1 = { version = "0.10", optional = true }
tokio = { package = "tokio", version = "1.44", features = ["time"], optional = true }
tokio-tungstenite = { version = "0.29.0", optional = true }
tracing = { version = "0.1", default-features = false, optional = true }
# doc dependencies
serde = { version = "1.0.211", optional = true }
[dependencies.tower-http]
version = "0.6.8"
optional = true
features = [
# all tower-http features except (de)?compression-zstd which doesn't
# build on `--target armv5te-unknown-linux-musleabi`
"add-extension",
"auth",
"catch-panic",
"compression-br",
"compression-deflate",
"compression-gzip",
"cors",
"decompression-br",
"decompression-deflate",
"decompression-gzip",
"follow-redirect",
"fs",
"limit",
"map-request-body",
"map-response-body",
"metrics",
"normalize-path",
"propagate-header",
"redirect",
"request-id",
"sensitive-headers",
"set-header",
"set-status",
"timeout",
"trace",
"util",
"validate-request",
]
[dev-dependencies]
anyhow = "1.0"
axum-extra = { path = "../axum-extra", features = ["typed-header"] }
axum-macros = { path = "../axum-macros", features = ["__private"] }
hyper = { version = "1.1.0", features = ["client"] }
quickcheck = "1.0"
quickcheck_macros = "1.0"
reqwest = { version = "0.12", default-features = false, features = ["json", "stream", "multipart"] }
serde = { version = "1.0.221", features = ["derive"] }
serde_json = { version = "1.0.29", features = ["raw_value"] }
time = { version = "0.3", features = ["serde-human-readable"] }
tokio = { package = "tokio", version = "1.44.2", features = ["macros", "rt", "rt-multi-thread", "net", "test-util"] }
tokio-stream = "0.1"
tokio-tungstenite = "0.29.0"
tracing = "0.1"
tracing-subscriber = { version = "0.3.20", features = ["json"] }
uuid = { version = "1.0", features = ["serde", "v4"] }
[dev-dependencies.tower]
package = "tower"
version = "0.5.2"
features = [
"util",
"timeout",
"limit",
"load-shed",
"steer",
"filter",
]
[dev-dependencies.tower-http]
version = "0.6.8"
features = [
# all tower-http features except (de)?compression-zstd which doesn't
# build on `--target armv5te-unknown-linux-musleabi`
"add-extension",
"auth",
"catch-panic",
"compression-br",
"compression-deflate",
"compression-gzip",
"cors",
"decompression-br",
"decompression-deflate",
"decompression-gzip",
"follow-redirect",
"fs",
"limit",
"map-request-body",
"map-response-body",
"metrics",
"normalize-path",
"propagate-header",
"redirect",
"request-id",
"sensitive-headers",
"set-header",
"set-status",
"timeout",
"trace",
"util",
"validate-request",
]
[lints]
workspace = true
[[bench]]
name = "benches"
harness = false
================================================
FILE: axum/README.md
================================================
# axum
`axum` is an HTTP routing and request-handling library that focuses on ergonomics and modularity.
[](https://github.com/tokio-rs/axum/actions/workflows/CI.yml)
[](https://crates.io/crates/axum)
[][docs]
More information about this crate can be found in the [crate documentation][docs].
## High level features
- Route requests to handlers with a macro free API.
- Declaratively parse requests using extractors.
- Simple and predictable error handling model.
- Generate responses with minimal boilerplate.
- Take full advantage of the [`tower`] and [`tower-http`] ecosystem of
middleware, services, and utilities.
In particular the last point is what sets `axum` apart from other libraries / frameworks.
`axum` doesn't have its own middleware system but instead uses
[`tower::Service`]. This means `axum` gets timeouts, tracing, compression,
authorization, and more, for free. It also enables you to share middleware with
applications written using [`hyper`] or [`tonic`].
## ⚠ Breaking changes ⚠
We are currently working towards axum 0.9 so the `main` branch contains breaking
changes. See the [`0.8.x`] branch for what's released to crates.io.
[`0.8.x`]: https://github.com/tokio-rs/axum/tree/v0.8.x
## Usage example
```rust
use axum::{
routing::{get, post},
http::StatusCode,
Json, Router,
};
use serde::{Deserialize, Serialize};
#[tokio::main]
async fn main() {
// initialize tracing
tracing_subscriber::fmt::init();
// build our application with a route
let app = Router::new()
// `GET /` goes to `root`
.route("/", get(root))
// `POST /users` goes to `create_user`
.route("/users", post(create_user));
// run our app with hyper, listening globally on port 3000
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
axum::serve(listener, app).await;
}
// basic handler that responds with a static string
async fn root() -> &'static str {
"Hello, World!"
}
async fn create_user(
// this argument tells axum to parse the request body
// as JSON into a `CreateUser` type
Json(payload): Json<CreateUser>,
) -> (StatusCode, Json<User>) {
// insert your application logic here
let user = User {
id: 1337,
username: payload.username,
};
// this will be converted into a JSON response
// with a status code of `201 Created`
(StatusCode::CREATED, Json(user))
}
// the input to our `create_user` handler
#[derive(Deserialize)]
struct CreateUser {
username: String,
}
// the output to our `create_user` handler
#[derive(Serialize)]
struct User {
id: u64,
username: String,
}
```
You can find this [example][readme-example] as well as other example projects in
the [example directory][examples].
See the [crate documentation][docs] for way more examples.
## Performance
`axum` is a relatively thin layer on top of [`hyper`] and adds very little
overhead. So `axum`'s performance is comparable to [`hyper`]. You can find
benchmarks [here](https://github.com/programatik29/rust-web-benchmarks) and
[here](https://web-frameworks-benchmark.netlify.app/result?l=rust).
## Safety
This crate uses `#![forbid(unsafe_code)]` to ensure everything is implemented in
100% safe Rust.
## Minimum supported Rust version
axum's MSRV is 1.80.
## Examples
The [examples] folder contains various examples of how to use `axum`. The
[docs] also provide lots of code snippets and examples. For full-fledged examples, check out community-maintained [showcases] or [tutorials].
## Getting Help
In the `axum`'s repo we also have a [number of examples][examples] showing how
to put everything together. Community-maintained [showcases] and [tutorials] also demonstrate how to use `axum` for real-world applications. You're also welcome to ask in the [Discord channel][chat] or open a [discussion] with your question.
## Community projects
See [here][ecosystem] for a list of community maintained crates and projects
built with `axum`.
## Contributing
🎈 Thanks for your help improving the project! We are so happy to have
you! We have a [contributing guide][contributing] to help you get involved in the
`axum` project.
## License
This project is licensed under the [MIT license][license].
### Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in `axum` by you, shall be licensed as MIT, without any
additional terms or conditions.
[readme-example]: https://github.com/tokio-rs/axum/tree/main/examples/readme
[examples]: https://github.com/tokio-rs/axum/tree/main/examples
[docs]: https://docs.rs/axum
[`tower`]: https://crates.io/crates/tower
[`hyper`]: https://crates.io/crates/hyper
[`tower-http`]: https://crates.io/crates/tower-http
[`tonic`]: https://crates.io/crates/tonic
[contributing]: https://github.com/tokio-rs/axum/blob/main/CONTRIBUTING.md
[chat]: https://discord.gg/tokio
[discussion]: https://github.com/tokio-rs/axum/discussions/new?category=q-a
[`tower::Service`]: https://docs.rs/tower/latest/tower/trait.Service.html
[ecosystem]: https://github.com/tokio-rs/axum/blob/main/ECOSYSTEM.md
[showcases]: https://github.com/tokio-rs/axum/blob/main/ECOSYSTEM.md#project-showcase
[tutorials]: https://github.com/tokio-rs/axum/blob/main/ECOSYSTEM.md#tutorials
[license]: https://github.com/tokio-rs/axum/blob/main/axum/LICENSE
================================================
FILE: axum/benches/benches.rs
================================================
#![allow(missing_docs)]
use axum::{
extract::State,
routing::{get, post},
Extension, Json, Router,
};
use serde::{Deserialize, Serialize};
use std::{
future::IntoFuture,
io::BufRead,
process::{Command, Stdio},
};
fn main() {
if on_ci() {
install_rewrk();
} else {
ensure_rewrk_is_installed();
}
benchmark("minimal").run(Router::new);
benchmark("basic")
.path("/a/b/c")
.run(|| Router::new().route("/a/b/c", get(|| async { "Hello, World!" })));
benchmark("basic-merge").path("/a/b/c").run(|| {
let inner = Router::new().route("/a/b/c", get(|| async { "Hello, World!" }));
Router::new().merge(inner)
});
benchmark("basic-nest").path("/a/b/c").run(|| {
let c = Router::new().route("/c", get(|| async { "Hello, World!" }));
let b = Router::new().nest("/b", c);
Router::new().nest("/a", b)
});
benchmark("routing").path("/foo/bar/baz").run(|| {
let mut app = Router::new();
for a in 0..10 {
for b in 0..10 {
for c in 0..10 {
app = app.route(&format!("/foo-{a}/bar-{b}/baz-{c}"), get(|| async {}));
}
}
}
app.route("/foo/bar/baz", get(|| async {}))
});
benchmark("receive-json")
.method("post")
.headers(&[("content-type", "application/json")])
.body(r#"{"n": 123, "s": "hi there", "b": false}"#)
.run(|| Router::new().route("/", post(|_: Json<Payload>| async {})));
benchmark("send-json").run(|| {
Router::new().route(
"/",
get(|| async {
Json(Payload {
n: 123,
s: "hi there".to_owned(),
b: false,
})
}),
)
});
let state = AppState {
_string: "aaaaaaaaaaaaaaaaaa".to_owned(),
_vec: Vec::from([
"aaaaaaaaaaaaaaaaaa".to_owned(),
"bbbbbbbbbbbbbbbbbb".to_owned(),
"cccccccccccccccccc".to_owned(),
]),
};
benchmark("extension").run(|| {
Router::new()
.route("/", get(|_: Extension<AppState>| async {}))
.layer(Extension(state.clone()))
});
benchmark("state").run(|| {
Router::new()
.route("/", get(|_: State<AppState>| async {}))
.with_state(state.clone())
});
}
#[derive(Clone)]
struct AppState {
_string: String,
_vec: Vec<String>,
}
#[derive(Deserialize, Serialize)]
struct Payload {
n: u32,
s: String,
b: bool,
}
fn benchmark(name: &'static str) -> BenchmarkBuilder {
BenchmarkBuilder {
name,
path: None,
method: None,
headers: None,
body: None,
}
}
struct BenchmarkBuilder {
name: &'static str,
path: Option<&'static str>,
method: Option<&'static str>,
headers: Option<&'static [(&'static str, &'static str)]>,
body: Option<&'static str>,
}
macro_rules! config_method {
($name:ident, $ty:ty) => {
fn $name(mut self, $name: $ty) -> Self {
self.$name = Some($name);
self
}
};
}
impl BenchmarkBuilder {
config_method!(path, &'static str);
config_method!(method, &'static str);
config_method!(headers, &'static [(&'static str, &'static str)]);
config_method!(body, &'static str);
fn run<F>(self, f: F)
where
F: FnOnce() -> Router<()>,
{
// support only running some benchmarks with
// ```
// cargo bench -- routing send-json
// ```
let args = std::env::args().collect::<Vec<_>>();
if args.len() != 1 {
let names = &args[1..args.len() - 1];
if !names.is_empty() && !names.contains(&self.name.to_owned()) {
return;
}
}
let app = f();
let rt = tokio::runtime::Builder::new_multi_thread()
.enable_all()
.build()
.unwrap();
let listener = rt
.block_on(tokio::net::TcpListener::bind("0.0.0.0:0"))
.unwrap();
let addr = listener.local_addr().unwrap();
#[allow(unreachable_code)] // buggy lint, fixed in nightly
std::thread::spawn(move || {
rt.block_on(axum::serve(listener, app).into_future());
});
let mut cmd = Command::new("rewrk");
cmd.stdout(Stdio::piped());
cmd.arg("--host");
cmd.arg(format!("http://{addr}{}", self.path.unwrap_or("")));
cmd.args(["--connections", "10"]);
cmd.args(["--threads", "10"]);
if on_ci() {
// don't slow down CI by running the benchmarks for too long
// but do run them for a bit
cmd.args(["--duration", "1s"]);
} else {
cmd.args(["--duration", "10s"]);
}
if let Some(method) = self.method {
cmd.args(["--method", method]);
}
for (key, value) in self.headers.into_iter().flatten() {
cmd.arg("--header");
cmd.arg(format!("{key}: {value}"));
}
if let Some(body) = self.body {
cmd.args(["--body", body]);
}
eprintln!("Running {:?} benchmark", self.name);
// indent output from `rewrk` so it's easier to read when running multiple benchmarks
let mut child = cmd.spawn().unwrap();
let stdout = child.stdout.take().unwrap();
let stdout = std::io::BufReader::new(stdout);
for line in stdout.lines() {
let line = line.unwrap();
println!(" {line}");
}
let status = child.wait().unwrap();
if !status.success() {
eprintln!("`rewrk` command failed");
std::process::exit(status.code().unwrap());
}
}
}
fn install_rewrk() {
println!("installing rewrk");
let mut cmd = Command::new("cargo");
cmd.args([
"install",
"rewrk",
"--git",
"https://github.com/ChillFish8/rewrk.git",
]);
let status = cmd
.status()
.unwrap_or_else(|_| panic!("failed to install rewrk"));
if !status.success() {
panic!("failed to install rewrk");
}
}
fn ensure_rewrk_is_installed() {
let mut cmd = Command::new("rewrk");
cmd.arg("--help");
cmd.stdout(Stdio::null());
cmd.stderr(Stdio::null());
cmd.status().unwrap_or_else(|_| {
panic!("rewrk is not installed. See https://github.com/lnx-search/rewrk")
});
}
fn on_ci() -> bool {
std::env::var("GITHUB_ACTIONS").is_ok()
}
================================================
FILE: axum/src/body/mod.rs
================================================
//! HTTP body utilities.
#[doc(no_inline)]
pub use http_body::Body as HttpBody;
#[doc(no_inline)]
pub use bytes::Bytes;
#[doc(inline)]
pub use axum_core::body::{Body, BodyDataStream};
use http_body_util::{BodyExt, Limited};
/// Converts [`Body`] into [`Bytes`] and limits the maximum size of the body.
///
/// # Example
///
/// ```rust
/// use axum::body::{to_bytes, Body};
///
/// # async fn foo() -> Result<(), axum_core::Error> {
/// let body = Body::from(vec![1, 2, 3]);
/// // Use `usize::MAX` if you don't care about the maximum size.
/// let bytes = to_bytes(body, usize::MAX).await?;
/// assert_eq!(&bytes[..], &[1, 2, 3]);
/// # Ok(())
/// # }
/// ```
///
/// You can detect if the limit was hit by checking the source of the error:
///
/// ```rust
/// use axum::body::{to_bytes, Body};
/// use http_body_util::LengthLimitError;
///
/// # #[tokio::main]
/// # async fn main() {
/// let body = Body::from(vec![1, 2, 3]);
/// match to_bytes(body, 1).await {
/// Ok(_bytes) => panic!("should have hit the limit"),
/// Err(err) => {
/// let source = std::error::Error::source(&err).unwrap();
/// assert!(source.is::<LengthLimitError>());
/// }
/// }
/// # }
/// ```
pub async fn to_bytes(body: Body, limit: usize) -> Result<Bytes, axum_core::Error> {
Limited::new(body, limit)
.collect()
.await
.map(|col| col.to_bytes())
.map_err(axum_core::Error::new)
}
================================================
FILE: axum/src/boxed.rs
================================================
use std::{convert::Infallible, fmt};
use crate::extract::Request;
use tower::Service;
use crate::{
handler::Handler,
routing::{future::RouteFuture, Route},
Router,
};
pub(crate) struct BoxedIntoRoute<S, E>(Box<dyn ErasedIntoRoute<S, E>>);
impl<S> BoxedIntoRoute<S, Infallible>
where
S: Clone + Send + Sync + 'static,
{
pub(crate) fn from_handler<H, T>(handler: H) -> Self
where
H: Handler<T, S>,
T: 'static,
{
Self(Box::new(MakeErasedHandler {
handler,
into_route: |handler, state| Route::new(Handler::with_state(handler, state)),
}))
}
}
impl<S, E> BoxedIntoRoute<S, E> {
pub(crate) fn map<F, E2>(self, f: F) -> BoxedIntoRoute<S, E2>
where
S: 'static,
E: 'static,
F: FnOnce(Route<E>) -> Route<E2> + Clone + Send + Sync + 'static,
E2: 'static,
{
BoxedIntoRoute(Box::new(Map {
inner: self.0,
layer: Box::new(f),
}))
}
pub(crate) fn into_route(self, state: S) -> Route<E> {
self.0.into_route(state)
}
}
impl<S, E> Clone for BoxedIntoRoute<S, E> {
fn clone(&self) -> Self {
Self(self.0.clone_box())
}
}
impl<S, E> fmt::Debug for BoxedIntoRoute<S, E> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("BoxedIntoRoute").finish()
}
}
pub(crate) trait ErasedIntoRoute<S, E>: Send + Sync {
fn clone_box(&self) -> Box<dyn ErasedIntoRoute<S, E>>;
fn into_route(self: Box<Self>, state: S) -> Route<E>;
#[allow(dead_code)]
fn call_with_state(self: Box<Self>, request: Request, state: S) -> RouteFuture<E>;
}
pub(crate) struct MakeErasedHandler<H, S> {
pub(crate) handler: H,
pub(crate) into_route: fn(H, S) -> Route,
}
impl<H, S> ErasedIntoRoute<S, Infallible> for MakeErasedHandler<H, S>
where
H: Clone + Send + Sync + 'static,
S: 'static,
{
fn clone_box(&self) -> Box<dyn ErasedIntoRoute<S, Infallible>> {
Box::new(self.clone())
}
fn into_route(self: Box<Self>, state: S) -> Route {
(self.into_route)(self.handler, state)
}
fn call_with_state(self: Box<Self>, request: Request, state: S) -> RouteFuture<Infallible> {
self.into_route(state).call(request)
}
}
impl<H, S> Clone for MakeErasedHandler<H, S>
where
H: Clone,
{
fn clone(&self) -> Self {
Self {
handler: self.handler.clone(),
into_route: self.into_route,
}
}
}
#[allow(dead_code)]
pub(crate) struct MakeErasedRouter<S> {
pub(crate) router: Router<S>,
pub(crate) into_route: fn(Router<S>, S) -> Route,
}
impl<S> ErasedIntoRoute<S, Infallible> for MakeErasedRouter<S>
where
S: Clone + Send + Sync + 'static,
{
fn clone_box(&self) -> Box<dyn ErasedIntoRoute<S, Infallible>> {
Box::new(self.clone())
}
fn into_route(self: Box<Self>, state: S) -> Route {
(self.into_route)(self.router, state)
}
fn call_with_state(self: Box<Self>, request: Request, state: S) -> RouteFuture<Infallible> {
self.router.call_with_state(request, state)
}
}
impl<S> Clone for MakeErasedRouter<S>
where
S: Clone,
{
fn clone(&self) -> Self {
Self {
router: self.router.clone(),
into_route: self.into_route,
}
}
}
pub(crate) struct Map<S, E, E2> {
pub(crate) inner: Box<dyn ErasedIntoRoute<S, E>>,
pub(crate) layer: Box<dyn LayerFn<E, E2>>,
}
impl<S, E, E2> ErasedIntoRoute<S, E2> for Map<S, E, E2>
where
S: 'static,
E: 'static,
E2: 'static,
{
fn clone_box(&self) -> Box<dyn ErasedIntoRoute<S, E2>> {
Box::new(Self {
inner: self.inner.clone_box(),
layer: self.layer.clone_box(),
})
}
fn into_route(self: Box<Self>, state: S) -> Route<E2> {
(self.layer)(self.inner.into_route(state))
}
fn call_with_state(self: Box<Self>, request: Request, state: S) -> RouteFuture<E2> {
(self.layer)(self.inner.into_route(state)).call(request)
}
}
pub(crate) trait LayerFn<E, E2>: FnOnce(Route<E>) -> Route<E2> + Send + Sync {
fn clone_box(&self) -> Box<dyn LayerFn<E, E2>>;
}
impl<F, E, E2> LayerFn<E, E2> for F
where
F: FnOnce(Route<E>) -> Route<E2> + Clone + Send + Sync + 'static,
{
fn clone_box(&self) -> Box<dyn LayerFn<E, E2>> {
Box::new(self.clone())
}
}
================================================
FILE: axum/src/docs/debugging_handler_type_errors.md
================================================
## Debugging handler type errors
For a function to be used as a handler it must implement the [`Handler`] trait.
axum provides blanket implementations for functions that:
- Are `async fn`s.
- Take no more than 16 arguments that all implement `Send`.
- All except the last argument implement [`FromRequestParts`].
- The last argument implements [`FromRequest`].
- Returns something that implements [`IntoResponse`].
- If a closure is used it must implement `Clone + Send` and be
`'static`.
- Returns a future that is `Send`. The most common way to accidentally make a
future `!Send` is to hold a `!Send` type across an await.
Unfortunately Rust gives poor error messages if you try to use a function
that doesn't quite match what's required by [`Handler`].
You might get an error like this:
```not_rust
error[E0277]: the trait bound `fn(bool) -> impl Future {handler}: Handler<_, _>` is not satisfied
--> src/main.rs:13:44
|
13 | let app = Router::new().route("/", get(handler));
| ^^^^^^^ the trait `Handler<_, _>` is not implemented for `fn(bool) -> impl Future {handler}`
|
::: axum/src/handler/mod.rs:116:8
|
116 | H: Handler<T, B>,
| ------------- required by this bound in `axum::routing::get`
```
This error doesn't tell you _why_ your function doesn't implement
[`Handler`]. It's possible to improve the error with the [`debug_handler`]
proc-macro from the [axum-macros] crate.
[axum-macros]: https://docs.rs/axum-macros
[`debug_handler`]: https://docs.rs/axum-macros/latest/axum_macros/attr.debug_handler.html
================================================
FILE: axum/src/docs/error_handling.md
================================================
Error handling model and utilities
# axum's error handling model
axum is based on [`tower::Service`] which bundles errors through its associated
`Error` type. If you have a [`Service`] that produces an error and that error
makes it all the way up to hyper, the connection will be terminated _without_
sending a response. This is generally not desirable so axum makes sure you
always produce a response by relying on the type system.
axum does this by requiring all services have [`Infallible`] as their error
type. `Infallible` is the error type for errors that can never happen.
This means if you define a handler like:
```rust
use axum::http::StatusCode;
async fn handler() -> Result<String, StatusCode> {
# todo!()
// ...
}
```
While it looks like it might fail with a `StatusCode` this actually isn't an
"error". If this handler returns `Err(some_status_code)` that will still be
converted into a [`Response`] and sent back to the client. This is done
through `StatusCode`'s [`IntoResponse`] implementation.
It doesn't matter whether you return `Err(StatusCode::NOT_FOUND)` or
`Err(StatusCode::INTERNAL_SERVER_ERROR)`. These are not considered errors in
axum.
Instead of a direct `StatusCode`, it makes sense to use intermediate error type
that can ultimately be converted to `Response`. This allows using `?` operator
in handlers. See those examples:
* [`anyhow-error-response`][anyhow] for generic boxed errors
* [`error-handling`][error-handling] for application-specific detailed errors
[anyhow]: https://github.com/tokio-rs/axum/blob/main/examples/anyhow-error-response/src/main.rs
[error-handling]: https://github.com/tokio-rs/axum/blob/main/examples/error-handling/src/main.rs
This also applies to extractors. If an extractor doesn't match the request the
request will be rejected and a response will be returned without calling your
handler. See [`extract`](crate::extract) to learn more about handling extractor
failures.
# Routing to fallible services
You generally don't have to think about errors if you're only using async
functions as handlers. However if you're embedding general `Service`s or
applying middleware, which might produce errors you have to tell axum how to
convert those errors into responses.
```rust
use axum::{
Router,
body::Body,
http::{Request, Response, StatusCode},
error_handling::HandleError,
};
async fn thing_that_might_fail() -> Result<(), anyhow::Error> {
# Ok(())
// ...
}
// this service might fail with `anyhow::Error`
let some_fallible_service = tower::service_fn(|_req| async {
thing_that_might_fail().await?;
Ok::<_, anyhow::Error>(Response::new(Body::empty()))
});
let app = Router::new().route_service(
"/",
// we cannot route to `some_fallible_service` directly since it might fail.
// we have to use `handle_error` which converts its errors into responses
// and changes its error type from `anyhow::Error` to `Infallible`.
HandleError::new(some_fallible_service, handle_anyhow_error),
);
// handle errors by converting them into something that implements
// `IntoResponse`
async fn handle_anyhow_error(err: anyhow::Error) -> (StatusCode, String) {
(
StatusCode::INTERNAL_SERVER_ERROR,
format!("Something went wrong: {err}"),
)
}
# let _: Router = app;
```
# Applying fallible middleware
Similarly axum requires you to handle errors from middleware. That is done with
[`HandleErrorLayer`]:
```rust
use axum::{
Router,
BoxError,
routing::get,
http::StatusCode,
error_handling::HandleErrorLayer,
};
use std::time::Duration;
use tower::ServiceBuilder;
let app = Router::new()
.route("/", get(|| async {}))
.layer(
ServiceBuilder::new()
// `timeout` will produce an error if the handler takes
// too long so we must handle those
.layer(HandleErrorLayer::new(handle_timeout_error))
.timeout(Duration::from_secs(30))
);
async fn handle_timeout_error(err: BoxError) -> (StatusCode, String) {
if err.is::<tower::timeout::error::Elapsed>() {
(
StatusCode::REQUEST_TIMEOUT,
"Request took too long".to_string(),
)
} else {
(
StatusCode::INTERNAL_SERVER_ERROR,
format!("Unhandled internal error: {err}"),
)
}
}
# let _: Router = app;
```
# Running extractors for error handling
`HandleErrorLayer` also supports running extractors:
```rust
use axum::{
Router,
BoxError,
routing::get,
http::{StatusCode, Method, Uri},
error_handling::HandleErrorLayer,
};
use std::time::Duration;
use tower::ServiceBuilder;
let app = Router::new()
.route("/", get(|| async {}))
.layer(
ServiceBuilder::new()
// `timeout` will produce an error if the handler takes
// too long so we must handle those
.layer(HandleErrorLayer::new(handle_timeout_error))
.timeout(Duration::from_secs(30))
);
async fn handle_timeout_error(
// `Method` and `Uri` are extractors so they can be used here
method: Method,
uri: Uri,
// the last argument must be the error itself
err: BoxError,
) -> (StatusCode, String) {
(
StatusCode::INTERNAL_SERVER_ERROR,
format!("`{method} {uri}` failed with {err}"),
)
}
# let _: Router = app;
```
[`tower::Service`]: `tower::Service`
[`Infallible`]: std::convert::Infallible
[`Response`]: crate::response::Response
[`IntoResponse`]: crate::response::IntoResponse
================================================
FILE: axum/src/docs/extract.md
================================================
Types and traits for extracting data from requests.
# Intro
A handler function is an async function that takes any number of
"extractors" as arguments. An extractor is a type that implements
[`FromRequest`] or [`FromRequestParts`].
For example, [`Json`] is an extractor that consumes the request body and
deserializes it as JSON into some target type:
```rust,no_run
use axum::{
extract::Json,
routing::post,
handler::Handler,
Router,
};
use serde::Deserialize;
#[derive(Deserialize)]
struct CreateUser {
email: String,
password: String,
}
async fn create_user(Json(payload): Json<CreateUser>) {
// ...
}
let app = Router::new().route("/users", post(create_user));
# let _: Router = app;
```
# Common extractors
Some commonly used extractors are:
```rust,no_run
use axum::{
extract::{Request, Json, Path, Extension, Query},
routing::post,
http::header::HeaderMap,
body::{Bytes, Body},
Router,
};
use serde_json::Value;
use std::collections::HashMap;
// `Path` gives you the path parameters and deserializes them. See its docs for
// more details
async fn path(Path(user_id): Path<u32>) {}
// `Query` gives you the query parameters and deserializes them.
async fn query(Query(params): Query<HashMap<String, String>>) {}
// `HeaderMap` gives you all the headers
async fn headers(headers: HeaderMap) {}
// `String` consumes the request body and ensures it is valid utf-8
async fn string(body: String) {}
// `Bytes` gives you the raw request body
async fn bytes(body: Bytes) {}
// We've already seen `Json` for parsing the request body as json
async fn json(Json(payload): Json<Value>) {}
// `Request` gives you the whole request for maximum control
async fn request(request: Request) {}
// `Extension` extracts data from "request extensions"
// This is commonly used to share state with handlers
async fn extension(Extension(state): Extension<State>) {}
#[derive(Clone)]
struct State { /* ... */ }
let app = Router::new()
.route("/path/{user_id}", post(path))
.route("/query", post(query))
.route("/string", post(string))
.route("/bytes", post(bytes))
.route("/json", post(json))
.route("/request", post(request))
.route("/extension", post(extension));
# let _: Router = app;
```
# Applying multiple extractors
You can also apply multiple extractors:
```rust,no_run
use axum::{
extract::{Path, Query},
routing::get,
Router,
};
use uuid::Uuid;
use serde::Deserialize;
let app = Router::new().route("/users/{id}/things", get(get_user_things));
#[derive(Deserialize)]
struct Pagination {
page: usize,
per_page: usize,
}
async fn get_user_things(
Path(user_id): Path<Uuid>,
Query(pagination): Query<Pagination>,
) {
// ...
}
# let _: Router = app;
```
# The order of extractors
Extractors always run in the order of the function parameters that is from
left to right.
The request body is an asynchronous stream that can only be consumed once.
Therefore you can only have one extractor that consumes the request body. axum
enforces this by requiring such extractors to be the _last_ argument your
handler takes.
For example
```rust
use axum::{extract::State, http::{Method, HeaderMap}};
#
# #[derive(Clone)]
# struct AppState {
# }
async fn handler(
// `Method` and `HeaderMap` don't consume the request body so they can
// put anywhere in the argument list (but before `body`)
method: Method,
headers: HeaderMap,
// `State` is also an extractor so it needs to be before `body`
State(state): State<AppState>,
// `String` consumes the request body and thus must be the last extractor
body: String,
) {
// ...
}
#
# let _: axum::routing::MethodRouter<AppState> = axum::routing::get(handler);
```
We get a compile error if `String` isn't the last extractor:
```rust,compile_fail
use axum::http::Method;
async fn handler(
// this doesn't work since `String` must be the last argument
body: String,
method: Method,
) {
// ...
}
#
# let _: axum::routing::MethodRouter = axum::routing::get(handler);
```
This also means you cannot consume the request body twice:
```rust,compile_fail
use axum::Json;
use serde::Deserialize;
#[derive(Deserialize)]
struct Payload {}
async fn handler(
// `String` and `Json` both consume the request body
// so they cannot both be used
string_body: String,
json_body: Json<Payload>,
) {
// ...
}
#
# let _: axum::routing::MethodRouter = axum::routing::get(handler);
```
axum enforces this by requiring the last extractor implements [`FromRequest`]
and all others implement [`FromRequestParts`].
# Handling extractor rejections
If you want to handle the case of an extractor failing within a specific
handler, you can wrap it in `Result`, with the error being the rejection type
of the extractor:
```rust,no_run
use axum::{
extract::{Json, rejection::JsonRejection},
routing::post,
Router,
};
use serde_json::Value;
async fn create_user(payload: Result<Json<Value>, JsonRejection>) {
match payload {
Ok(payload) => {
// We got a valid JSON payload
}
Err(JsonRejection::MissingJsonContentType(_)) => {
// Request didn't have `Content-Type: application/json`
// header
}
Err(JsonRejection::JsonDataError(_)) => {
// Couldn't deserialize the body into the target type
}
Err(JsonRejection::JsonSyntaxError(_)) => {
// Syntax error in the body
}
Err(JsonRejection::BytesRejection(_)) => {
// Failed to extract the request body
}
Err(_) => {
// `JsonRejection` is marked `#[non_exhaustive]` so match must
// include a catch-all case.
}
}
}
let app = Router::new().route("/users", post(create_user));
# let _: Router = app;
```
# Optional extractors
Some extractors implement [`OptionalFromRequestParts`] in addition to
[`FromRequestParts`], or [`OptionalFromRequest`] in addition to [`FromRequest`].
These extractors can be used inside of `Option`. It depends on the particular
`OptionalFromRequestParts` or `OptionalFromRequest` implementation what this
does: For example for `TypedHeader` from axum-extra, you get `None` if the
header you're trying to extract is not part of the request, but if the header
is present and fails to parse, the request is rejected.
```rust,no_run
use axum::{routing::post, Router};
use axum_extra::{headers::UserAgent, TypedHeader};
use serde_json::Value;
async fn foo(user_agent: Option<TypedHeader<UserAgent>>) {
if let Some(TypedHeader(user_agent)) = user_agent {
// The client sent a user agent
} else {
// No user agent header
}
}
let app = Router::new().route("/foo", post(foo));
# let _: Router = app;
```
# Customizing extractor responses
If an extractor fails it will return a response with the error and your
handler will not be called. To customize the error response you have two
options:
1. Use `Result<T, T::Rejection>` as your extractor like shown in
["Handling extractor rejections"](#handling-extractor-rejections).
This works well if you're only using the extractor in a single handler.
2. Create your own extractor that in its [`FromRequest`] implementation calls
one of axum's built in extractors but returns a different response for
rejections. See the [customize-extractor-error] example for more details.
# Accessing inner errors
axum's built-in extractors don't directly expose the inner error. This gives us
more flexibility and allows us to change internal implementations without
breaking the public API.
For example that means while [`Json`] is implemented using [`serde_json`] it
doesn't directly expose the [`serde_json::Error`] that's contained in
[`JsonRejection::JsonDataError`]. However it is still possible to access via
methods from [`std::error::Error`]:
```rust
use std::error::Error;
use axum::{
extract::{Json, rejection::JsonRejection},
response::IntoResponse,
http::StatusCode,
};
use serde_json::{json, Value};
async fn handler(
result: Result<Json<Value>, JsonRejection>,
) -> Result<Json<Value>, (StatusCode, String)> {
match result {
// if the client sent valid JSON then we're good
Ok(Json(payload)) => Ok(Json(json!({ "payload": payload }))),
Err(err) => match err {
JsonRejection::JsonDataError(err) => {
Err(serde_json_error_response(err))
}
JsonRejection::JsonSyntaxError(err) => {
Err(serde_json_error_response(err))
}
// handle other rejections from the `Json` extractor
JsonRejection::MissingJsonContentType(_) => Err((
StatusCode::BAD_REQUEST,
"Missing `Content-Type: application/json` header".to_string(),
)),
JsonRejection::BytesRejection(_) => Err((
StatusCode::INTERNAL_SERVER_ERROR,
"Failed to buffer request body".to_string(),
)),
// we must provide a catch-all case since `JsonRejection` is marked
// `#[non_exhaustive]`
_ => Err((
StatusCode::INTERNAL_SERVER_ERROR,
"Unknown error".to_string(),
)),
},
}
}
// attempt to extract the inner `serde_path_to_error::Error<serde_json::Error>`,
// if that succeeds we can provide a more specific error.
//
// `Json` uses `serde_path_to_error` so the error will be wrapped in `serde_path_to_error::Error`.
fn serde_json_error_response<E>(err: E) -> (StatusCode, String)
where
E: Error + 'static,
{
if let Some(err) = find_error_source::<serde_path_to_error::Error<serde_json::Error>>(&err) {
let serde_json_err = err.inner();
(
StatusCode::BAD_REQUEST,
format!(
"Invalid JSON at line {} column {}",
serde_json_err.line(),
serde_json_err.column()
),
)
} else {
(StatusCode::BAD_REQUEST, "Unknown error".to_string())
}
}
// attempt to downcast `err` into a `T` and if that fails recursively try and
// downcast `err`'s source
fn find_error_source<'a, T>(err: &'a (dyn Error + 'static)) -> Option<&'a T>
where
T: Error + 'static,
{
if let Some(err) = err.downcast_ref::<T>() {
Some(err)
} else if let Some(source) = err.source() {
find_error_source(source)
} else {
None
}
}
#
# #[tokio::main]
# async fn main() {
# use axum::extract::FromRequest;
#
# let req = axum::http::Request::builder()
# .header("content-type", "application/json")
# .body(axum::body::Body::from("{"))
# .unwrap();
#
# let err = match Json::<serde_json::Value>::from_request(req, &()).await.unwrap_err() {
# JsonRejection::JsonSyntaxError(err) => err,
# _ => panic!(),
# };
#
# let (_, body) = serde_json_error_response(err);
# assert_eq!(body, "Invalid JSON at line 1 column 1");
# }
```
Note that while this approach works it might break in the future if axum changes
its implementation to use a different error type internally. Such changes might
happen without major breaking versions.
# Defining custom extractors
You can also define your own extractors by implementing either
[`FromRequestParts`] or [`FromRequest`].
## Implementing `FromRequestParts`
Implement `FromRequestParts` if your extractor doesn't need access to the
request body:
```rust,no_run
use axum::{
extract::FromRequestParts,
routing::get,
Router,
http::{
StatusCode,
header::{HeaderValue, USER_AGENT},
request::Parts,
},
};
struct ExtractUserAgent(HeaderValue);
impl<S> FromRequestParts<S> for ExtractUserAgent
where
S: Send + Sync,
{
type Rejection = (StatusCode, &'static str);
async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> {
if let Some(user_agent) = parts.headers.get(USER_AGENT) {
Ok(ExtractUserAgent(user_agent.clone()))
} else {
Err((StatusCode::BAD_REQUEST, "`User-Agent` header is missing"))
}
}
}
async fn handler(ExtractUserAgent(user_agent): ExtractUserAgent) {
// ...
}
let app = Router::new().route("/foo", get(handler));
# let _: Router = app;
```
## Implementing `FromRequest`
If your extractor needs to consume the request body you must implement [`FromRequest`]
```rust,no_run
use axum::{
extract::{Request, FromRequest},
response::{Response, IntoResponse},
body::{Bytes, Body},
routing::get,
Router,
http::{
StatusCode,
header::{HeaderValue, USER_AGENT},
},
};
struct ValidatedBody(Bytes);
impl<S> FromRequest<S> for ValidatedBody
where
Bytes: FromRequest<S>,
S: Send + Sync,
{
type Rejection = Response;
async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rejection> {
let body = Bytes::from_request(req, state)
.await
.map_err(IntoResponse::into_response)?;
// do validation...
Ok(Self(body))
}
}
async fn handler(ValidatedBody(body): ValidatedBody) {
// ...
}
let app = Router::new().route("/foo", get(handler));
# let _: Router = app;
```
## Cannot implement both `FromRequest` and `FromRequestParts`
Note that you will make your extractor unusable by implementing both
`FromRequest` and `FromRequestParts` directly for the same type, unless it is
wrapping another extractor:
```rust,compile_fail
use axum::{
Router,
routing::get,
extract::{FromRequest, Request, FromRequestParts},
http::request::Parts,
body::Body,
};
use std::convert::Infallible;
// Some extractor that doesn't wrap another extractor
struct MyExtractor;
// `MyExtractor` implements both `FromRequest`
impl<S> FromRequest<S> for MyExtractor
where
S: Send + Sync,
{
type Rejection = Infallible;
async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rejection> {
// ...
# todo!()
}
}
// and `FromRequestParts`
impl<S> FromRequestParts<S> for MyExtractor
where
S: Send + Sync,
{
type Rejection = Infallible;
async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> {
// ...
# todo!()
}
}
let app = Router::new().route(
"/",
// This fails when we go to actually use `MyExtractor` in a handler function.
// This is due to a limit in Rust's type system.
//
// The workaround is to implement either `FromRequest` or `FromRequestParts`
// but not both, if your extractor doesn't wrap another extractor.
//
// See "Wrapping extractors" for how to wrap other extractors.
get(|_: MyExtractor| async {}),
);
# let _: Router = app;
```
# Accessing other extractors in `FromRequest` or `FromRequestParts` implementations
When defining custom extractors you often need to access another extractor
in your implementation.
```rust
use axum::{
extract::{Extension, FromRequestParts},
http::{StatusCode, HeaderMap, request::Parts},
response::{IntoResponse, Response},
routing::get,
Router,
};
#[derive(Clone)]
struct State {
// ...
}
struct AuthenticatedUser {
// ...
}
impl<S> FromRequestParts<S> for AuthenticatedUser
where
S: Send + Sync,
{
type Rejection = Response;
async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> {
// You can either call them directly...
let headers = HeaderMap::from_request_parts(parts, state)
.await
.map_err(|err| match err {})?;
// ... or use `extract` / `extract_with_state` from `RequestExt` / `RequestPartsExt`
use axum::RequestPartsExt;
let Extension(state) = parts.extract::<Extension<State>>()
.await
.map_err(|err| err.into_response())?;
unimplemented!("actually perform the authorization")
}
}
async fn handler(user: AuthenticatedUser) {
// ...
}
let state = State { /* ... */ };
let app = Router::new().route("/", get(handler)).layer(Extension(state));
# let _: Router = app;
```
# Request body limits
For security reasons, [`Bytes`] will, by default, not accept bodies larger than
2MB. This also applies to extractors that uses [`Bytes`] internally such as
`String`, [`Json`], and [`Form`].
For more details, including how to disable this limit, see [`DefaultBodyLimit`].
# Wrapping extractors
If you want to write an extractor that generically wraps another extractor
(that may or may not consume the request body) you should implement both
[`FromRequest`] and [`FromRequestParts`]:
```rust
use axum::{
Router,
body::Body,
routing::get,
extract::{Request, FromRequest, FromRequestParts},
http::{HeaderMap, request::Parts},
};
use std::time::{Instant, Duration};
// an extractor that wraps another and measures how long time it takes to run
struct Timing<E> {
extractor: E,
duration: Duration,
}
// we must implement both `FromRequestParts`
impl<S, T> FromRequestParts<S> for Timing<T>
where
S: Send + Sync,
T: FromRequestParts<S>,
{
type Rejection = T::Rejection;
async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> {
let start = Instant::now();
let extractor = T::from_request_parts(parts, state).await?;
let duration = start.elapsed();
Ok(Timing {
extractor,
duration,
})
}
}
// and `FromRequest`
impl<S, T> FromRequest<S> for Timing<T>
where
S: Send + Sync,
T: FromRequest<S>,
{
type Rejection = T::Rejection;
async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rejection> {
let start = Instant::now();
let extractor = T::from_request(req, state).await?;
let duration = start.elapsed();
Ok(Timing {
extractor,
duration,
})
}
}
async fn handler(
// this uses the `FromRequestParts` impl
_: Timing<HeaderMap>,
// this uses the `FromRequest` impl
_: Timing<String>,
) {}
# let _: axum::routing::MethodRouter = axum::routing::get(handler);
```
# Logging rejections
All built-in extractors will log rejections for easier debugging. To see the
logs, enable the `tracing` feature for axum (enabled by default) and the
`axum::rejection=trace` tracing target, for example with
`RUST_LOG=info,axum::rejection=trace cargo run`.
[axum-extra]: https://docs.rs/axum-extra/latest/axum_extra/extract/index.html
[`body::Body`]: crate::body::Body
[`Bytes`]: crate::body::Bytes
[customize-extractor-error]: https://github.com/tokio-rs/axum/blob/main/examples/customize-extractor-error/src/main.rs
[`HeaderMap`]: https://docs.rs/http/latest/http/header/struct.HeaderMap.html
[`Request`]: https://docs.rs/http/latest/http/struct.Request.html
[`JsonRejection::JsonDataError`]: rejection::JsonRejection::JsonDataError
================================================
FILE: axum/src/docs/handlers_intro.md
================================================
In axum a "handler" is an async function that accepts zero or more
["extractors"](crate::extract) as arguments and returns something that
can be converted [into a response](crate::response).
Handlers are where your application logic lives and axum applications are built
by routing between handlers.
[`debug_handler`]: https://docs.rs/axum-macros/latest/axum_macros/attr.debug_handler.html
================================================
FILE: axum/src/docs/method_routing/fallback.md
================================================
Add a fallback service to the router.
This service will be called if no routes matches the incoming request.
```rust
use axum::{
Router,
routing::get,
handler::Handler,
response::IntoResponse,
http::{StatusCode, Method, Uri},
};
let handler = get(|| async {}).fallback(fallback);
let app = Router::new().route("/", handler);
async fn fallback(method: Method, uri: Uri) -> (StatusCode, String) {
(StatusCode::NOT_FOUND, format!("`{method}` not allowed for {uri}"))
}
# let _: Router = app;
```
## When used with `MethodRouter::merge`
Two routers that both have a fallback cannot be merged. Doing so results in a
panic:
```rust,should_panic
use axum::{
routing::{get, post},
handler::Handler,
response::IntoResponse,
http::{StatusCode, Uri},
};
let one = get(|| async {}).fallback(fallback_one);
let two = post(|| async {}).fallback(fallback_two);
let method_route = one.merge(two);
async fn fallback_one() -> impl IntoResponse { /* ... */ }
async fn fallback_two() -> impl IntoResponse { /* ... */ }
# let app: axum::Router = axum::Router::new().route("/", method_route);
```
## Setting the `Allow` header
By default `MethodRouter` will set the `Allow` header when returning `405 Method
Not Allowed`. This is also done when the fallback returns `405 Method Not Allowed`
unless the response generated by the fallback already sets the `Allow` header.
This means if you use `fallback` to accept additional methods, you should make
sure you set the `Allow` header correctly.
================================================
FILE: axum/src/docs/method_routing/layer.md
================================================
Apply a [`tower::Layer`] to all routes in the router.
This can be used to add additional processing to a request for a group
of routes.
Note that the middleware is only applied to existing routes. So you have to
first add your routes (and / or fallback) and then call `layer` afterwards. Additional
routes added after `layer` is called will not have the middleware added.
Works similarly to [`Router::layer`](super::Router::layer). See that method for
more details.
# Example
```rust
use axum::{routing::get, Router};
use tower::limit::ConcurrencyLimitLayer;
async fn handler() {}
let app = Router::new().route(
"/",
// All requests to `GET /` will be sent through `ConcurrencyLimitLayer`
get(handler).layer(ConcurrencyLimitLayer::new(64)),
);
# let _: Router = app;
```
================================================
FILE: axum/src/docs/method_routing/merge.md
================================================
Merge two routers into one.
This is useful for breaking routers into smaller pieces and combining them
into one.
```rust
use axum::{
routing::{get, post},
Router,
};
let get = get(|| async {});
let post = post(|| async {});
let merged = get.merge(post);
let app = Router
gitextract_tcp4if_v/
├── .clippy.toml
├── .github/
│ ├── DISCUSSION_TEMPLATE/
│ │ └── q-a.yml
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug_report.md
│ │ ├── config.yml
│ │ └── feature_request.md
│ ├── PULL_REQUEST_TEMPLATE.md
│ └── workflows/
│ └── CI.yml
├── .gitignore
├── CHANGELOG.md
├── CONTRIBUTING.md
├── Cargo.toml
├── ECOSYSTEM.md
├── LICENSE
├── axum/
│ ├── CHANGELOG.md
│ ├── Cargo.toml
│ ├── README.md
│ ├── benches/
│ │ └── benches.rs
│ ├── src/
│ │ ├── body/
│ │ │ └── mod.rs
│ │ ├── boxed.rs
│ │ ├── docs/
│ │ │ ├── debugging_handler_type_errors.md
│ │ │ ├── error_handling.md
│ │ │ ├── extract.md
│ │ │ ├── handlers_intro.md
│ │ │ ├── method_routing/
│ │ │ │ ├── fallback.md
│ │ │ │ ├── layer.md
│ │ │ │ ├── merge.md
│ │ │ │ └── route_layer.md
│ │ │ ├── middleware.md
│ │ │ ├── response.md
│ │ │ └── routing/
│ │ │ ├── fallback.md
│ │ │ ├── into_make_service_with_connect_info.md
│ │ │ ├── layer.md
│ │ │ ├── merge.md
│ │ │ ├── method_not_allowed_fallback.md
│ │ │ ├── nest.md
│ │ │ ├── route.md
│ │ │ ├── route_layer.md
│ │ │ ├── route_service.md
│ │ │ ├── with_state.md
│ │ │ └── without_v07_checks.md
│ │ ├── error_handling/
│ │ │ └── mod.rs
│ │ ├── extension.rs
│ │ ├── extract/
│ │ │ ├── connect_info.rs
│ │ │ ├── matched_path.rs
│ │ │ ├── mod.rs
│ │ │ ├── multipart.rs
│ │ │ ├── nested_path.rs
│ │ │ ├── original_uri.rs
│ │ │ ├── path/
│ │ │ │ ├── de.rs
│ │ │ │ └── mod.rs
│ │ │ ├── query.rs
│ │ │ ├── raw_form.rs
│ │ │ ├── raw_query.rs
│ │ │ ├── rejection.rs
│ │ │ ├── state.rs
│ │ │ └── ws.rs
│ │ ├── form.rs
│ │ ├── handler/
│ │ │ ├── future.rs
│ │ │ ├── mod.rs
│ │ │ └── service.rs
│ │ ├── json.rs
│ │ ├── lib.rs
│ │ ├── macros.rs
│ │ ├── middleware/
│ │ │ ├── from_extractor.rs
│ │ │ ├── from_fn.rs
│ │ │ ├── map_request.rs
│ │ │ ├── map_response.rs
│ │ │ ├── mod.rs
│ │ │ └── response_axum_body.rs
│ │ ├── response/
│ │ │ ├── mod.rs
│ │ │ ├── redirect.rs
│ │ │ └── sse.rs
│ │ ├── routing/
│ │ │ ├── future.rs
│ │ │ ├── into_make_service.rs
│ │ │ ├── method_filter.rs
│ │ │ ├── method_routing.rs
│ │ │ ├── mod.rs
│ │ │ ├── not_found.rs
│ │ │ ├── path_router.rs
│ │ │ ├── route.rs
│ │ │ ├── strip_prefix.rs
│ │ │ ├── tests/
│ │ │ │ ├── fallback.rs
│ │ │ │ ├── get_to_head.rs
│ │ │ │ ├── handle_error.rs
│ │ │ │ ├── merge.rs
│ │ │ │ ├── mod.rs
│ │ │ │ └── nest.rs
│ │ │ └── url_params.rs
│ │ ├── serve/
│ │ │ ├── listener.rs
│ │ │ └── mod.rs
│ │ ├── service_ext.rs
│ │ ├── test_helpers/
│ │ │ ├── counting_cloneable_state.rs
│ │ │ ├── mod.rs
│ │ │ ├── test_client.rs
│ │ │ └── tracing_helpers.rs
│ │ └── util.rs
│ └── tests/
│ └── panic_location.rs
├── axum-core/
│ ├── CHANGELOG.md
│ ├── Cargo.toml
│ ├── README.md
│ └── src/
│ ├── body.rs
│ ├── error.rs
│ ├── ext_traits/
│ │ ├── mod.rs
│ │ ├── request.rs
│ │ └── request_parts.rs
│ ├── extract/
│ │ ├── default_body_limit.rs
│ │ ├── from_ref.rs
│ │ ├── mod.rs
│ │ ├── option.rs
│ │ ├── rejection.rs
│ │ ├── request_parts.rs
│ │ └── tuple.rs
│ ├── lib.rs
│ ├── macros.rs
│ └── response/
│ ├── append_headers.rs
│ ├── into_response.rs
│ ├── into_response_parts.rs
│ └── mod.rs
├── axum-extra/
│ ├── CHANGELOG.md
│ ├── Cargo.toml
│ ├── README.md
│ ├── src/
│ │ ├── body/
│ │ │ ├── async_read_body.rs
│ │ │ └── mod.rs
│ │ ├── either.rs
│ │ ├── extract/
│ │ │ ├── cached.rs
│ │ │ ├── cookie/
│ │ │ │ ├── mod.rs
│ │ │ │ ├── private.rs
│ │ │ │ └── signed.rs
│ │ │ ├── form.rs
│ │ │ ├── json_deserializer.rs
│ │ │ ├── mod.rs
│ │ │ ├── multipart.rs
│ │ │ ├── query.rs
│ │ │ └── with_rejection.rs
│ │ ├── handler/
│ │ │ ├── mod.rs
│ │ │ └── or.rs
│ │ ├── json_lines.rs
│ │ ├── lib.rs
│ │ ├── middleware.rs
│ │ ├── protobuf.rs
│ │ ├── response/
│ │ │ ├── attachment.rs
│ │ │ ├── content_disposition.rs
│ │ │ ├── erased_json.rs
│ │ │ ├── error_response.rs
│ │ │ ├── file_stream.rs
│ │ │ ├── mod.rs
│ │ │ └── multiple.rs
│ │ ├── routing/
│ │ │ ├── mod.rs
│ │ │ ├── resource.rs
│ │ │ └── typed.rs
│ │ └── typed_header.rs
│ └── test_files/
│ ├── index.html
│ ├── index_2.html
│ └── script.js
├── axum-macros/
│ ├── CHANGELOG.md
│ ├── Cargo.toml
│ ├── README.md
│ ├── rust-toolchain
│ ├── src/
│ │ ├── attr_parsing.rs
│ │ ├── axum_test.rs
│ │ ├── debug_handler.rs
│ │ ├── from_ref.rs
│ │ ├── from_request/
│ │ │ ├── attr.rs
│ │ │ └── mod.rs
│ │ ├── lib.rs
│ │ ├── typed_path.rs
│ │ └── with_position.rs
│ └── tests/
│ ├── debug_handler/
│ │ ├── fail/
│ │ │ ├── .gitkeep
│ │ │ ├── argument_not_extractor.rs
│ │ │ ├── argument_not_extractor.stderr
│ │ │ ├── duplicate_args.rs
│ │ │ ├── duplicate_args.stderr
│ │ │ ├── extension_not_clone.rs
│ │ │ ├── extension_not_clone.stderr
│ │ │ ├── extract_self_mut.rs
│ │ │ ├── extract_self_mut.stderr
│ │ │ ├── extract_self_ref.rs
│ │ │ ├── extract_self_ref.stderr
│ │ │ ├── generics.rs
│ │ │ ├── generics.stderr
│ │ │ ├── invalid_attrs.rs
│ │ │ ├── invalid_attrs.stderr
│ │ │ ├── json_not_deserialize.rs
│ │ │ ├── json_not_deserialize.stderr
│ │ │ ├── multiple_paths.rs
│ │ │ ├── multiple_paths.stderr
│ │ │ ├── multiple_request_consumers.rs
│ │ │ ├── multiple_request_consumers.stderr
│ │ │ ├── not_a_function.rs
│ │ │ ├── not_a_function.stderr
│ │ │ ├── not_async.rs
│ │ │ ├── not_async.stderr
│ │ │ ├── not_send.rs
│ │ │ ├── not_send.stderr
│ │ │ ├── output_tuple_too_many.rs
│ │ │ ├── output_tuple_too_many.stderr
│ │ │ ├── returning_request_parts.rs
│ │ │ ├── returning_request_parts.stderr
│ │ │ ├── single_wrong_return_tuple.rs
│ │ │ ├── single_wrong_return_tuple.stderr
│ │ │ ├── too_many_extractors.rs
│ │ │ ├── too_many_extractors.stderr
│ │ │ ├── wrong_order.rs
│ │ │ ├── wrong_order.stderr
│ │ │ ├── wrong_return_tuple.rs
│ │ │ ├── wrong_return_tuple.stderr
│ │ │ ├── wrong_return_type.rs
│ │ │ └── wrong_return_type.stderr
│ │ └── pass/
│ │ ├── associated_fn_without_self.rs
│ │ ├── deny_unreachable_code.rs
│ │ ├── impl_future.rs
│ │ ├── impl_into_response.rs
│ │ ├── infer_state.rs
│ │ ├── multiple_extractors.rs
│ │ ├── mut_extractor.rs
│ │ ├── ready.rs
│ │ ├── request_last.rs
│ │ ├── result_impl_into_response.rs
│ │ ├── returns_self.rs
│ │ ├── self_receiver.rs
│ │ ├── set_state.rs
│ │ └── state_and_body.rs
│ ├── debug_middleware/
│ │ ├── fail/
│ │ │ ├── doesnt_take_next.rs
│ │ │ ├── doesnt_take_next.stderr
│ │ │ ├── next_not_last.rs
│ │ │ ├── next_not_last.stderr
│ │ │ ├── takes_next_twice.rs
│ │ │ └── takes_next_twice.stderr
│ │ └── pass/
│ │ └── basic.rs
│ ├── from_ref/
│ │ ├── fail/
│ │ │ ├── generics.rs
│ │ │ └── generics.stderr
│ │ └── pass/
│ │ ├── basic.rs
│ │ ├── reference-types.rs
│ │ └── skip.rs
│ ├── from_request/
│ │ ├── fail/
│ │ │ ├── double_via_attr.rs
│ │ │ ├── double_via_attr.stderr
│ │ │ ├── enum_from_request_ident_in_variant.rs
│ │ │ ├── enum_from_request_ident_in_variant.stderr
│ │ │ ├── enum_from_request_on_variant.rs
│ │ │ ├── enum_from_request_on_variant.stderr
│ │ │ ├── enum_no_via.rs
│ │ │ ├── enum_no_via.stderr
│ │ │ ├── generic.rs
│ │ │ ├── generic.stderr
│ │ │ ├── generic_without_via.rs
│ │ │ ├── generic_without_via.stderr
│ │ │ ├── generic_without_via_rejection.rs
│ │ │ ├── generic_without_via_rejection.stderr
│ │ │ ├── not_enum_or_struct.rs
│ │ │ ├── not_enum_or_struct.stderr
│ │ │ ├── override_rejection_on_enum_without_via.rs
│ │ │ ├── override_rejection_on_enum_without_via.stderr
│ │ │ ├── parts_extracting_body.rs
│ │ │ ├── parts_extracting_body.stderr
│ │ │ ├── state_infer_multiple_different_types.rs
│ │ │ ├── state_infer_multiple_different_types.stderr
│ │ │ ├── unknown_attr_container.rs
│ │ │ ├── unknown_attr_container.stderr
│ │ │ ├── unknown_attr_field.rs
│ │ │ ├── unknown_attr_field.stderr
│ │ │ ├── via_on_container_and_field.rs
│ │ │ └── via_on_container_and_field.stderr
│ │ └── pass/
│ │ ├── container.rs
│ │ ├── container_parts.rs
│ │ ├── empty_named.rs
│ │ ├── empty_named_parts.rs
│ │ ├── empty_tuple.rs
│ │ ├── empty_tuple_parts.rs
│ │ ├── enum_via.rs
│ │ ├── enum_via_parts.rs
│ │ ├── named.rs
│ │ ├── named_parts.rs
│ │ ├── named_via.rs
│ │ ├── named_via_parts.rs
│ │ ├── override_rejection.rs
│ │ ├── override_rejection_non_generic.rs
│ │ ├── override_rejection_non_generic_parts.rs
│ │ ├── override_rejection_parts.rs
│ │ ├── override_rejection_with_via_on_enum.rs
│ │ ├── override_rejection_with_via_on_enum_parts.rs
│ │ ├── override_rejection_with_via_on_struct.rs
│ │ ├── override_rejection_with_via_on_struct_parts.rs
│ │ ├── state_cookie.rs
│ │ ├── state_enum_via.rs
│ │ ├── state_enum_via_parts.rs
│ │ ├── state_explicit.rs
│ │ ├── state_explicit_parts.rs
│ │ ├── state_field_explicit.rs
│ │ ├── state_field_infer.rs
│ │ ├── state_infer.rs
│ │ ├── state_infer_multiple.rs
│ │ ├── state_infer_parts.rs
│ │ ├── state_via.rs
│ │ ├── state_via_infer.rs
│ │ ├── state_via_parts.rs
│ │ ├── state_with_rejection.rs
│ │ ├── tuple.rs
│ │ ├── tuple_parts.rs
│ │ ├── tuple_same_type_twice.rs
│ │ ├── tuple_same_type_twice_parts.rs
│ │ ├── tuple_same_type_twice_via.rs
│ │ ├── tuple_same_type_twice_via_parts.rs
│ │ ├── tuple_via.rs
│ │ ├── tuple_via_parts.rs
│ │ ├── unit.rs
│ │ └── unit_parts.rs
│ └── typed_path/
│ ├── fail/
│ │ ├── missing_capture.rs
│ │ ├── missing_capture.stderr
│ │ ├── missing_field.rs
│ │ ├── missing_field.stderr
│ │ ├── not_deserialize.rs
│ │ ├── not_deserialize.stderr
│ │ ├── route_not_starting_with_slash.rs
│ │ ├── route_not_starting_with_slash.stderr
│ │ ├── route_not_starting_with_slash_non_empty.rs
│ │ ├── route_not_starting_with_slash_non_empty.stderr
│ │ ├── unit_with_capture.rs
│ │ └── unit_with_capture.stderr
│ └── pass/
│ ├── customize_rejection.rs
│ ├── into_uri.rs
│ ├── named_fields_struct.rs
│ ├── result_handler.rs
│ ├── tuple_struct.rs
│ ├── unit_struct.rs
│ ├── url_encoding.rs
│ └── wildcards.rs
├── contrib/
│ └── ide/
│ └── vscode/
│ └── settings.json
├── deny.toml
└── examples/
├── Cargo.toml
├── README.md
├── anyhow-error-response/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── async-graphql/
│ └── README.md
├── auto-reload/
│ ├── Cargo.toml
│ ├── README.md
│ └── src/
│ └── main.rs
├── chat/
│ ├── Cargo.toml
│ ├── chat.html
│ └── src/
│ └── main.rs
├── compression/
│ ├── Cargo.toml
│ ├── README.md
│ ├── data/
│ │ └── products.json
│ └── src/
│ ├── main.rs
│ └── tests.rs
├── consume-body-in-extractor-or-middleware/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── cors/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── customize-extractor-error/
│ ├── Cargo.toml
│ ├── README.md
│ └── src/
│ ├── custom_extractor.rs
│ ├── derive_from_request.rs
│ ├── main.rs
│ └── with_rejection.rs
├── customize-path-rejection/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── dependency-injection/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── diesel-async-postgres/
│ ├── Cargo.toml
│ ├── migrations/
│ │ └── 2023-03-14-180127_add_users/
│ │ ├── down.sql
│ │ └── up.sql
│ └── src/
│ └── main.rs
├── diesel-postgres/
│ ├── Cargo.toml
│ ├── migrations/
│ │ └── 2023-03-14-180127_add_users/
│ │ ├── down.sql
│ │ └── up.sql
│ └── src/
│ └── main.rs
├── error-handling/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── form/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── global-404-handler/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── graceful-shutdown/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── handle-head-request/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── hello-world/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── http-proxy/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── jwt/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── key-value-store/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── low-level-native-tls/
│ ├── Cargo.toml
│ ├── self_signed_certs/
│ │ ├── cert.pem
│ │ └── key.pem
│ └── src/
│ └── main.rs
├── low-level-openssl/
│ ├── Cargo.toml
│ ├── self_signed_certs/
│ │ ├── cert.pem
│ │ └── key.pem
│ └── src/
│ └── main.rs
├── low-level-rustls/
│ ├── Cargo.toml
│ ├── self_signed_certs/
│ │ ├── cert.pem
│ │ └── key.pem
│ └── src/
│ └── main.rs
├── mongodb/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── multipart-form/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── oauth/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── parse-body-based-on-content-type/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── print-request-response/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── prometheus-metrics/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── readme/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── request-id/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── reqwest-response/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── reverse-proxy/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── routes-and-handlers-close-together/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── serve-with-hyper/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── simple-router-wasm/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── sqlx-postgres/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── sse/
│ ├── Cargo.toml
│ ├── assets/
│ │ ├── index.html
│ │ └── script.js
│ └── src/
│ └── main.rs
├── static-file-server/
│ ├── Cargo.toml
│ ├── assets/
│ │ ├── index.html
│ │ └── script.js
│ └── src/
│ └── main.rs
├── stream-to-file/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── templates/
│ ├── Cargo.toml
│ ├── src/
│ │ └── main.rs
│ └── templates/
│ └── hello.html
├── templates-minijinja/
│ ├── Cargo.toml
│ ├── src/
│ │ └── main.rs
│ └── templates/
│ ├── about.jinja
│ ├── content.jinja
│ ├── home.jinja
│ └── layout.jinja
├── testing/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── testing-websockets/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── tls-graceful-shutdown/
│ ├── Cargo.toml
│ ├── self_signed_certs/
│ │ ├── cert.pem
│ │ └── key.pem
│ └── src/
│ └── main.rs
├── tls-rustls/
│ ├── Cargo.toml
│ ├── self_signed_certs/
│ │ ├── cert.pem
│ │ └── key.pem
│ └── src/
│ └── main.rs
├── todos/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── tokio-postgres/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── tokio-redis/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── tracing-aka-logging/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── unix-domain-socket/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── validator/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── versioning/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── websockets/
│ ├── Cargo.toml
│ ├── assets/
│ │ ├── index.html
│ │ └── script.js
│ └── src/
│ ├── client.rs
│ └── main.rs
└── websockets-http2/
├── Cargo.toml
├── assets/
│ ├── index.html
│ └── script.js
├── self_signed_certs/
│ ├── cert.pem
│ └── key.pem
└── src/
└── main.rs
Showing preview only (217K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (2652 symbols across 285 files)
FILE: axum-core/src/body.rs
type BoxBody (line 13) | type BoxBody = http_body_util::combinators::UnsyncBoxBody<Bytes, Error>;
function boxed (line 15) | fn boxed<B>(body: B) -> BoxBody
function try_downcast (line 23) | pub(crate) fn try_downcast<T, K>(k: K) -> Result<T, K>
type Body (line 39) | pub struct Body(BoxBody);
method new (line 43) | pub fn new<B>(body: B) -> Self
method empty (line 52) | pub fn empty() -> Self {
method from_stream (line 59) | pub fn from_stream<S>(stream: S) -> Self
method into_data_stream (line 76) | pub fn into_data_stream(self) -> BodyDataStream {
method from (line 88) | fn from(_: ()) -> Self {
type Data (line 114) | type Data = Bytes;
type Error (line 115) | type Error = Error;
method poll_frame (line 118) | fn poll_frame(
method size_hint (line 126) | fn size_hint(&self) -> http_body::SizeHint {
method is_end_stream (line 131) | fn is_end_stream(&self) -> bool {
method default (line 82) | fn default() -> Self {
type BodyDataStream (line 141) | pub struct BodyDataStream {
type Data (line 171) | type Data = Bytes;
type Error (line 172) | type Error = Error;
method poll_frame (line 175) | fn poll_frame(
method is_end_stream (line 183) | fn is_end_stream(&self) -> bool {
method size_hint (line 188) | fn size_hint(&self) -> http_body::SizeHint {
type Item (line 146) | type Item = Result<Bytes, Error>;
method poll_next (line 149) | fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Opt...
method size_hint (line 162) | fn size_hint(&self) -> (usize, Option<usize>) {
type Data (line 206) | type Data = Bytes;
type Error (line 207) | type Error = Error;
function poll_frame (line 209) | fn poll_frame(
function test_try_downcast (line 223) | fn test_try_downcast() {
FILE: axum-core/src/error.rs
type Error (line 6) | pub struct Error {
method new (line 12) | pub fn new(error: impl Into<BoxError>) -> Self {
method into_inner (line 20) | pub fn into_inner(self) -> BoxError {
method fmt (line 26) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
method source (line 32) | fn source(&self) -> Option<&(dyn StdError + 'static)> {
FILE: axum-core/src/ext_traits/mod.rs
type State (line 12) | pub(crate) struct State<S>(pub(crate) S);
type Rejection (line 19) | type Rejection = Infallible;
function from_request_parts (line 21) | async fn from_request_parts(
type RequiresState (line 32) | pub(crate) struct RequiresState(pub(crate) String);
type Rejection (line 39) | type Rejection = Infallible;
method from_request_parts (line 41) | async fn from_request_parts(
FILE: axum-core/src/ext_traits/request.rs
type Sealed (line 6) | pub trait Sealed {}
type RequestExt (line 11) | pub trait RequestExt: sealed::Sealed + Sized {
method extract (line 68) | fn extract<E, M>(self) -> impl Future<Output = Result<E, E::Rejection>...
method extract_with_state (line 122) | fn extract_with_state<E, S, M>(
method extract_parts (line 178) | fn extract_parts<E>(&mut self) -> impl Future<Output = Result<E, E::Re...
method extract_parts_with_state (line 243) | fn extract_parts_with_state<'a, E, S>(
method with_limited_body (line 254) | fn with_limited_body(self) -> Request;
method into_limited_body (line 259) | fn into_limited_body(self) -> Body;
method extract (line 263) | fn extract<E, M>(self) -> impl Future<Output = Result<E, E::Rejection>...
method extract_with_state (line 271) | fn extract_with_state<E, S, M>(
method extract_parts (line 282) | fn extract_parts<E>(&mut self) -> impl Future<Output = Result<E, E::Re...
method extract_parts_with_state (line 289) | async fn extract_parts_with_state<'a, E, S>(
method with_limited_body (line 316) | fn with_limited_body(self) -> Request {
method into_limited_body (line 330) | fn into_limited_body(self) -> Body {
function extract_without_state (line 345) | async fn extract_without_state() {
function extract_body_without_state (line 354) | async fn extract_body_without_state() {
function extract_with_state (line 363) | async fn extract_with_state() {
function extract_parts_without_state (line 374) | async fn extract_parts_without_state() {
function extract_parts_with_state (line 387) | async fn extract_parts_with_state() {
type WorksForCustomExtractor (line 404) | struct WorksForCustomExtractor {
type Rejection (line 415) | type Rejection = <String as FromRequest<()>>::Rejection;
method from_request (line 417) | async fn from_request(mut req: Request, state: &S) -> Result<Self, Sel...
FILE: axum-core/src/ext_traits/request_parts.rs
type Sealed (line 6) | pub trait Sealed {}
type RequestPartsExt (line 11) | pub trait RequestPartsExt: sealed::Sealed + Sized {
method extract (line 55) | fn extract<E>(&mut self) -> impl Future<Output = Result<E, E::Rejectio...
method extract_with_state (line 108) | fn extract_with_state<'a, E, S>(
method extract (line 118) | fn extract<E>(&mut self) -> impl Future<Output = Result<E, E::Rejectio...
method extract_with_state (line 125) | fn extract_with_state<'a, E, S>(
function extract_without_state (line 149) | async fn extract_without_state() {
function extract_with_state (line 158) | async fn extract_with_state() {
type WorksForCustomExtractor (line 173) | struct WorksForCustomExtractor {
type Rejection (line 183) | type Rejection = Infallible;
method from_request_parts (line 185) | async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Se...
FILE: axum-core/src/extract/default_body_limit.rs
type DefaultBodyLimit (line 78) | pub struct DefaultBodyLimit {
method disable (line 119) | pub const fn disable() -> Self {
method max (line 150) | pub const fn max(limit: usize) -> Self {
method apply (line 182) | pub fn apply<B>(self, req: &mut Request<B>) {
type Service (line 188) | type Service = DefaultBodyLimitService<S>;
method layer (line 190) | fn layer(&self, inner: S) -> Self::Service {
type DefaultBodyLimitKind (line 83) | pub(crate) enum DefaultBodyLimitKind {
type DefaultBodyLimitService (line 205) | pub struct DefaultBodyLimitService<S> {
type Response (line 214) | type Response = S::Response;
type Error (line 215) | type Error = S::Error;
type Future (line 216) | type Future = S::Future;
function poll_ready (line 219) | fn poll_ready(&mut self, cx: &mut Context<'_>) -> std::task::Poll<Result...
function call (line 224) | fn call(&mut self, mut req: Request<B>) -> Self::Future {
FILE: axum-core/src/extract/from_ref.rs
type FromRef (line 13) | pub trait FromRef<T> {
method from_ref (line 15) | fn from_ref(input: &T) -> Self;
method from_ref (line 22) | fn from_ref(input: &T) -> Self {
FILE: axum-core/src/extract/mod.rs
type Request (line 29) | pub type Request<T = Body> = http::Request<T>;
type ViaParts (line 33) | pub enum ViaParts {}
type ViaRequest (line 36) | pub enum ViaRequest {}
type FromRequestParts (line 53) | pub trait FromRequestParts<S>: Sized {
method from_request_parts (line 59) | fn from_request_parts(
type FromRequest (line 79) | pub trait FromRequest<S, M = private::ViaRequest>: Sized {
method from_request (line 85) | fn from_request(
type Rejection (line 96) | type Rejection = <Self as FromRequestParts<S>>::Rejection;
method from_request (line 98) | fn from_request(
type Rejection (line 112) | type Rejection = Infallible;
function from_request_parts (line 114) | async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self...
type Rejection (line 124) | type Rejection = Infallible;
function from_request (line 126) | async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rej...
FILE: axum-core/src/extract/option.rs
type OptionalFromRequestParts (line 11) | pub trait OptionalFromRequestParts<S>: Sized {
method from_request_parts (line 18) | fn from_request_parts(
type OptionalFromRequest (line 25) | pub trait OptionalFromRequest<S, M = private::ViaRequest>: Sized {
method from_request (line 32) | fn from_request(
type Rejection (line 46) | type Rejection = T::Rejection;
function from_request_parts (line 49) | fn from_request_parts(
type Rejection (line 63) | type Rejection = T::Rejection;
function from_request (line 66) | async fn from_request(req: Request, state: &S) -> Result<Option<T>, Self...
FILE: axum-core/src/extract/rejection.rs
method from_err (line 18) | pub(crate) fn from_err<E>(err: E) -> Self
FILE: axum-core/src/extract/request_parts.rs
type Rejection (line 12) | type Rejection = Infallible;
method from_request (line 14) | async fn from_request(req: Request, _: &S) -> Result<Self, Self::Rejecti...
type Rejection (line 23) | type Rejection = Infallible;
method from_request_parts (line 25) | async fn from_request_parts(parts: &mut Parts, _: &S) -> Result<Self, Se...
type Rejection (line 34) | type Rejection = Infallible;
method from_request_parts (line 36) | async fn from_request_parts(parts: &mut Parts, _: &S) -> Result<Self, Se...
type Rejection (line 45) | type Rejection = Infallible;
method from_request_parts (line 47) | async fn from_request_parts(parts: &mut Parts, _: &S) -> Result<Self, Se...
type Rejection (line 61) | type Rejection = Infallible;
method from_request_parts (line 63) | async fn from_request_parts(parts: &mut Parts, _: &S) -> Result<Self, Se...
type Rejection (line 73) | type Rejection = BytesRejection;
method from_request (line 75) | async fn from_request(req: Request, _: &S) -> Result<Self, Self::Rejecti...
function body_to_bytes_mut (line 84) | async fn body_to_bytes_mut(body: &mut Body, bytes: &mut BytesMut) -> Res...
type Rejection (line 104) | type Rejection = BytesRejection;
method from_request (line 106) | async fn from_request(req: Request, _: &S) -> Result<Self, Self::Rejecti...
type Rejection (line 122) | type Rejection = StringRejection;
method from_request (line 124) | async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rej...
type Rejection (line 145) | type Rejection = Infallible;
method from_request_parts (line 147) | async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result<Sel...
type Rejection (line 157) | type Rejection = Infallible;
method from_request_parts (line 159) | async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result<Sel...
type Rejection (line 168) | type Rejection = Infallible;
method from_request (line 170) | async fn from_request(req: Request, _: &S) -> Result<Self, Self::Rejecti...
function extract_request_parts (line 181) | async fn extract_request_parts() {
FILE: axum-core/src/extract/tuple.rs
type Rejection (line 11) | type Rejection = Infallible;
function from_request_parts (line 13) | async fn from_request_parts(_: &mut Parts, _: &S) -> Result<(), Self::Re...
function assert_from_request (line 86) | fn assert_from_request<M, T>()
function assert_from_request_parts (line 92) | fn assert_from_request_parts<T: FromRequestParts<()>>() {}
function unit (line 95) | fn unit() {
function tuple_of_one (line 101) | fn tuple_of_one() {
function tuple_of_two (line 108) | fn tuple_of_two() {
function nested_tuple (line 115) | fn nested_tuple() {
FILE: axum-core/src/lib.rs
type BoxError (line 31) | pub type BoxError = Box<dyn std::error::Error + Send + Sync>;
FILE: axum-core/src/macros.rs
function source_gives_inner_source (line 346) | fn source_gives_inner_source() {
FILE: axum-core/src/response/append_headers.rs
type AppendHeaders (line 34) | pub struct AppendHeaders<I>(pub I);
method into_response (line 44) | fn into_response(self) -> Response {
type Error (line 57) | type Error = TryIntoHeaderError<K::Error, V::Error>;
method into_response_parts (line 59) | fn into_response_parts(self, mut res: ResponseParts) -> Result<ResponseP...
FILE: axum-core/src/response/into_response.rs
type IntoResponse (line 112) | pub trait IntoResponse {
method into_response (line 115) | fn into_response(self) -> Response;
method into_response (line 119) | fn into_response(self) -> Response {
method into_response (line 127) | fn into_response(self) -> Response {
method into_response (line 133) | fn into_response(self) -> Response {
method into_response (line 143) | fn into_response(self) -> Response {
method into_response (line 156) | fn into_response(self) -> Response {
method into_response (line 162) | fn into_response(self) -> Response {
method into_response (line 168) | fn into_response(self) -> Response {
method into_response (line 174) | fn into_response(self) -> Response {
method into_response (line 180) | fn into_response(self) -> Response {
method into_response (line 186) | fn into_response(self) -> Response {
method into_response (line 192) | fn into_response(self) -> Response {
method into_response (line 203) | fn into_response(self) -> Response {
method into_response (line 214) | fn into_response(self) -> Response {
method into_response (line 224) | fn into_response(self) -> Response {
method into_response (line 286) | fn into_response(self) -> Response {
method into_response (line 292) | fn into_response(self) -> Response {
method into_response (line 298) | fn into_response(self) -> Response {
method into_response (line 304) | fn into_response(self) -> Response {
method into_response (line 310) | fn into_response(self) -> Response {
method into_response (line 316) | fn into_response(self) -> Response {
method into_response (line 330) | fn into_response(self) -> Response {
method into_response (line 340) | fn into_response(self) -> Response {
method into_response (line 348) | fn into_response(self) -> Response {
method into_response (line 362) | fn into_response(self) -> Response {
method into_response (line 371) | fn into_response(self) -> Response {
method into_response (line 381) | fn into_response(self) -> Response {
method into_response (line 392) | fn into_response(self) -> Response {
type BytesChainBody (line 238) | struct BytesChainBody<T, U> {
type Data (line 248) | type Data = Bytes;
type Error (line 249) | type Error = Infallible;
function poll_frame (line 251) | fn poll_frame(
function is_end_stream (line 268) | fn is_end_stream(&self) -> bool {
function size_hint (line 272) | fn size_hint(&self) -> SizeHint {
FILE: axum-core/src/response/into_response_parts.rs
type IntoResponseParts (line 73) | pub trait IntoResponseParts {
method into_response_parts (line 80) | fn into_response_parts(self, res: ResponseParts) -> Result<ResponsePar...
type Error (line 87) | type Error = T::Error;
method into_response_parts (line 89) | fn into_response_parts(self, res: ResponseParts) -> Result<ResponsePar...
type Error (line 133) | type Error = Infallible;
method into_response_parts (line 135) | fn into_response_parts(self, mut res: ResponseParts) -> Result<Respons...
type Error (line 148) | type Error = TryIntoHeaderError<K::Error, V::Error>;
method into_response_parts (line 150) | fn into_response_parts(self, mut res: ResponseParts) -> Result<Respons...
type Error (line 260) | type Error = Infallible;
method into_response_parts (line 262) | fn into_response_parts(self, mut res: ResponseParts) -> Result<Respons...
type Error (line 269) | type Error = Infallible;
method into_response_parts (line 271) | fn into_response_parts(self, res: ResponseParts) -> Result<ResponsePar...
type ResponseParts (line 102) | pub struct ResponseParts {
method headers (line 109) | pub fn headers(&self) -> &HeaderMap {
method headers_mut (line 115) | pub fn headers_mut(&mut self) -> &mut HeaderMap {
method extensions (line 121) | pub fn extensions(&self) -> &Extensions {
method extensions_mut (line 127) | pub fn extensions_mut(&mut self) -> &mut Extensions {
type TryIntoHeaderError (line 163) | pub struct TryIntoHeaderError<K, V> {
function key (line 168) | pub(super) fn key(err: K) -> Self {
function value (line 174) | pub(super) fn value(err: V) -> Self {
type TryIntoHeaderErrorKind (line 182) | enum TryIntoHeaderErrorKind<K, V> {
method into_response (line 192) | fn into_response(self) -> Response {
function fmt (line 205) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
function source (line 220) | fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
function failed_into_response_parts (line 283) | fn failed_into_response_parts() {
FILE: axum-core/src/response/mod.rs
type Response (line 25) | pub type Response<T = Body> = http::Response<T>;
type Result (line 106) | pub type Result<T, E = ErrorResponse> = std::result::Result<T, E>;
method into_response (line 112) | fn into_response(self) -> Response {
type ErrorResponse (line 125) | pub struct ErrorResponse(Response);
method from (line 131) | fn from(value: T) -> Self {
type IntoResponseFailed (line 171) | pub struct IntoResponseFailed;
type Error (line 174) | type Error = Infallible;
method into_response_parts (line 176) | fn into_response_parts(self, mut res: ResponseParts) -> Result<ResponseP...
function into_response_failed_doesnt_impl_into_response (line 192) | fn into_response_failed_doesnt_impl_into_response() {}
type ForceStatusCode (line 198) | pub struct ForceStatusCode(pub StatusCode);
method into_response (line 201) | fn into_response(self) -> Response {
method into_response (line 212) | fn into_response(self) -> Response {
FILE: axum-extra/src/body/async_read_body.rs
method new (line 59) | pub fn new<R>(read: R) -> Self
type Data (line 70) | type Data = Bytes;
type Error (line 71) | type Error = Error;
method poll_frame (line 74) | fn poll_frame(
method is_end_stream (line 82) | fn is_end_stream(&self) -> bool {
method size_hint (line 87) | fn size_hint(&self) -> http_body::SizeHint {
method into_response (line 93) | fn into_response(self) -> Response {
FILE: axum-extra/src/either.rs
type Either (line 108) | pub enum Either<E1, E2> {
type Either3 (line 120) | pub enum Either3<E1, E2, E3> {
type Either4 (line 134) | pub enum Either4<E1, E2, E3, E4> {
type Either5 (line 150) | pub enum Either5<E1, E2, E3, E4, E5> {
type Either6 (line 168) | pub enum Either6<E1, E2, E3, E4, E5, E6> {
type Either7 (line 188) | pub enum Either7<E1, E2, E3, E4, E5, E6, E7> {
type Either8 (line 210) | pub enum Either8<E1, E2, E3, E4, E5, E6, E7, E8> {
type Service (line 282) | type Service = Either<E1::Service, E2::Service>;
function layer (line 284) | fn layer(&self, inner: S) -> Self::Service {
type Response (line 297) | type Response = E1::Response;
type Error (line 298) | type Error = E1::Error;
type Future (line 299) | type Future = futures_util::future::Either<E1::Future, E2::Future>;
function poll_ready (line 301) | fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::...
function call (line 308) | fn call(&mut self, req: R) -> Self::Future {
FILE: axum-extra/src/extract/cached.rs
type Cached (line 78) | pub struct Cached<T>(pub T);
type CachedEntry (line 81) | struct CachedEntry<T>(T);
type Rejection (line 88) | type Rejection = T::Rejection;
function from_request_parts (line 90) | async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self...
function works (line 114) | async fn works() {
function _last_handler_argument (line 153) | async fn _last_handler_argument() {
FILE: axum-extra/src/extract/cookie/mod.rs
type CookieJar (line 89) | pub struct CookieJar {
type Rejection (line 97) | type Rejection = Infallible;
method from_request_parts (line 99) | async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result<S...
method from_headers (line 122) | pub fn from_headers(headers: &HeaderMap) -> Self {
method new (line 139) | pub fn new() -> Self {
method get (line 158) | pub fn get(&self, name: &str) -> Option<&Cookie<'static>> {
method remove (line 174) | pub fn remove<C: Into<Cookie<'static>>>(mut self, cookie: C) -> Self {
method add (line 194) | pub fn add<C: Into<Cookie<'static>>>(mut self, cookie: C) -> Self {
method iter (line 200) | pub fn iter(&self) -> impl Iterator<Item = &'_ Cookie<'static>> {
function cookies_from_request (line 104) | fn cookies_from_request(headers: &HeaderMap) -> impl Iterator<Item = Coo...
type Error (line 206) | type Error = Infallible;
method into_response_parts (line 208) | fn into_response_parts(self, mut res: ResponseParts) -> Result<ResponseP...
method into_response (line 215) | fn into_response(self) -> Response {
function set_cookies (line 220) | fn set_cookies(jar: &cookie::CookieJar, headers: &mut HeaderMap) {
type AppState (line 318) | struct AppState {
method from_ref (line 324) | fn from_ref(state: &AppState) -> Self {
type CustomKey (line 336) | struct CustomKey(Key);
method from_ref (line 330) | fn from_ref(state: &AppState) -> Self {
method from (line 339) | fn from(custom: CustomKey) -> Self {
function signed_cannot_access_invalid_cookies (line 346) | async fn signed_cannot_access_invalid_cookies() {
function body_text (line 375) | async fn body_text<B>(body: B) -> String
FILE: axum-extra/src/extract/cookie/private.rs
type PrivateCookieJar (line 108) | pub struct PrivateCookieJar<K = Key> {
method from_headers (line 157) | pub fn from_headers(headers: &HeaderMap, key: Key) -> Self {
method new (line 179) | pub fn new(key: Key) -> Self {
function fmt (line 117) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
type Rejection (line 130) | type Rejection = Infallible;
function from_request_parts (line 132) | async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self...
function get (line 206) | pub fn get(&self, name: &str) -> Option<Cookie<'static>> {
function remove (line 222) | pub fn remove<C: Into<Cookie<'static>>>(mut self, cookie: C) -> Self {
function add (line 242) | pub fn add<C: Into<Cookie<'static>>>(mut self, cookie: C) -> Self {
function decrypt (line 250) | pub fn decrypt(&self, cookie: Cookie<'static>) -> Option<Cookie<'static>> {
function iter (line 257) | pub fn iter(&self) -> impl Iterator<Item = Cookie<'static>> + '_ {
function private_jar (line 264) | fn private_jar(&self) -> PrivateJar<&'_ cookie::CookieJar> {
function private_jar_mut (line 268) | fn private_jar_mut(&mut self) -> PrivateJar<&'_ mut cookie::CookieJar> {
type Error (line 274) | type Error = Infallible;
method into_response_parts (line 276) | fn into_response_parts(self, mut res: ResponseParts) -> Result<ResponseP...
method into_response (line 283) | fn into_response(self) -> Response {
type PrivateCookieJarIter (line 289) | struct PrivateCookieJarIter<'a, K> {
type Item (line 295) | type Item = Cookie<'static>;
method next (line 297) | fn next(&mut self) -> Option<Self::Item> {
method clone (line 309) | fn clone(&self) -> Self {
FILE: axum-extra/src/extract/cookie/signed.rs
type SignedCookieJar (line 125) | pub struct SignedCookieJar<K = Key> {
method from_headers (line 174) | pub fn from_headers(headers: &HeaderMap, key: Key) -> Self {
method new (line 196) | pub fn new(key: Key) -> Self {
function fmt (line 134) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
type Rejection (line 147) | type Rejection = Infallible;
function from_request_parts (line 149) | async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self...
function get (line 224) | pub fn get(&self, name: &str) -> Option<Cookie<'static>> {
function remove (line 240) | pub fn remove<C: Into<Cookie<'static>>>(mut self, cookie: C) -> Self {
function add (line 260) | pub fn add<C: Into<Cookie<'static>>>(mut self, cookie: C) -> Self {
function verify (line 268) | pub fn verify(&self, cookie: Cookie<'static>) -> Option<Cookie<'static>> {
function iter (line 275) | pub fn iter(&self) -> impl Iterator<Item = Cookie<'static>> + '_ {
function signed_jar (line 282) | fn signed_jar(&self) -> SignedJar<&'_ cookie::CookieJar> {
function signed_jar_mut (line 286) | fn signed_jar_mut(&mut self) -> SignedJar<&'_ mut cookie::CookieJar> {
type Error (line 292) | type Error = Infallible;
method into_response_parts (line 294) | fn into_response_parts(self, mut res: ResponseParts) -> Result<ResponseP...
method into_response (line 301) | fn into_response(self) -> Response {
type SignedCookieJarIter (line 307) | struct SignedCookieJarIter<'a, K> {
type Item (line 313) | type Item = Cookie<'static>;
method next (line 315) | fn next(&mut self) -> Option<Self::Item> {
method clone (line 327) | fn clone(&self) -> Self {
FILE: axum-extra/src/extract/form.rs
type Form (line 29) | pub struct Form<T>(pub T);
type Rejection (line 38) | type Rejection = FormRejection;
function from_request (line 40) | async fn from_request(req: Request, _state: &S) -> Result<Self, Self::Re...
function supports_multiple_values (line 100) | async fn supports_multiple_values() {
function deserialize_error_status_codes (line 125) | async fn deserialize_error_status_codes() {
FILE: axum-extra/src/extract/json_deserializer.rs
type JsonDeserializer (line 81) | pub struct JsonDeserializer<T> {
type Rejection (line 91) | type Rejection = JsonDeserializerRejection;
function from_request (line 93) | async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rej...
function deserialize (line 112) | pub fn deserialize(&'a self) -> Result<T, JsonDeserializerRejection> {
function json_content_type (line 185) | fn json_content_type(headers: &HeaderMap) -> bool {
function deserialize_body (line 219) | async fn deserialize_body() {
function deserialize_body_escaped_to_cow (line 246) | async fn deserialize_body_escaped_to_cow() {
function deserialize_body_escaped_to_str (line 279) | async fn deserialize_body_escaped_to_str() {
function consume_body_to_json_requires_json_content_type (line 312) | async fn consume_body_to_json_requires_json_content_type() {
function json_content_types (line 334) | async fn json_content_types() {
function invalid_json_syntax (line 361) | async fn invalid_json_syntax() {
type Foo (line 382) | struct Foo {
type Bar (line 390) | struct Bar {
function invalid_json_data (line 398) | async fn invalid_json_data() {
FILE: axum-extra/src/extract/multipart.rs
type Multipart (line 90) | pub struct Multipart {
type Rejection (line 98) | type Rejection = MultipartRejection;
method from_request (line 100) | async fn from_request(req: Request<Body>, _state: &S) -> Result<Self, ...
method next_field (line 110) | pub async fn next_field(&mut self) -> Result<Option<Field>, MultipartE...
method into_stream (line 125) | pub fn into_stream(self) -> impl Stream<Item = Result<Field, Multipart...
type Field (line 135) | pub struct Field {
method name (line 154) | pub fn name(&self) -> Option<&str> {
method file_name (line 162) | pub fn file_name(&self) -> Option<&str> {
method content_type (line 168) | pub fn content_type(&self) -> Option<&str> {
method headers (line 174) | pub fn headers(&self) -> &HeaderMap {
method bytes (line 179) | pub async fn bytes(self) -> Result<Bytes, MultipartError> {
method text (line 187) | pub async fn text(self) -> Result<String, MultipartError> {
method chunk (line 229) | pub async fn chunk(&mut self) -> Result<Option<Bytes>, MultipartError> {
type Item (line 140) | type Item = Result<Bytes, MultipartError>;
method poll_next (line 142) | fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Opt...
type MultipartError (line 239) | pub struct MultipartError {
method from_multer (line 244) | fn from_multer(multer: multer::Error) -> Self {
method body_text (line 249) | pub fn body_text(&self) -> String {
method status (line 265) | pub fn status(&self) -> http::StatusCode {
method fmt (line 328) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
method source (line 334) | fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
function status_code_from_multer_error (line 270) | fn status_code_from_multer_error(err: &multer::Error) -> StatusCode {
function is_body_limit_error (line 305) | fn is_body_limit_error(err: &multer::Error) -> bool {
method into_response (line 322) | fn into_response(self) -> Response {
function parse_boundary (line 339) | fn parse_boundary(headers: &HeaderMap) -> Option<String> {
function content_type_with_encoding (line 368) | async fn content_type_with_encoding() {
function _multipart_from_request_limited (line 399) | fn _multipart_from_request_limited() {
function body_too_large (line 405) | async fn body_too_large() {
function body_too_large_with_tracing (line 431) | async fn body_too_large_with_tracing() {
FILE: axum-extra/src/extract/query.rs
type Query (line 25) | pub struct Query<T>(pub T);
type Rejection (line 32) | type Rejection = QueryRejection;
function from_request_parts (line 34) | async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result<Sel...
function try_from_uri (line 67) | pub fn try_from_uri(value: &Uri) -> Result<Self, QueryRejection> {
type OptionalQuery (line 131) | pub struct OptionalQuery<T>(pub Option<T>);
type Rejection (line 138) | type Rejection = OptionalQueryRejection;
function from_request_parts (line 140) | async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result<Sel...
type Target (line 154) | type Target = Option<T>;
function deref (line 157) | fn deref(&self) -> &Self::Target {
function deref_mut (line 164) | fn deref_mut(&mut self) -> &mut Self::Target {
function query_supports_multiple_values (line 189) | async fn query_supports_multiple_values() {
function correct_rejection_status_code (line 214) | async fn correct_rejection_status_code() {
function optional_query_supports_multiple_values (line 235) | async fn optional_query_supports_multiple_values() {
function optional_query_deserializes_no_parameters_into_none (line 263) | async fn optional_query_deserializes_no_parameters_into_none() {
function optional_query_preserves_parsing_errors (line 288) | async fn optional_query_preserves_parsing_errors() {
function test_try_from_uri (line 316) | fn test_try_from_uri() {
function test_try_from_uri_with_invalid_query (line 331) | fn test_try_from_uri_with_invalid_query() {
FILE: axum-extra/src/extract/with_rejection.rs
type WithRejection (line 60) | pub struct WithRejection<E, R>(pub E, pub PhantomData<R>);
function into_inner (line 64) | pub fn into_inner(self) -> E {
method fmt (line 73) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
method clone (line 85) | fn clone(&self) -> Self {
method default (line 93) | fn default() -> Self {
type Target (line 99) | type Target = E;
method deref (line 101) | fn deref(&self) -> &Self::Target {
method deref_mut (line 107) | fn deref_mut(&mut self) -> &mut Self::Target {
type Rejection (line 118) | type Rejection = R;
function from_request (line 120) | async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rej...
type Rejection (line 132) | type Rejection = R;
function from_request_parts (line 134) | async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self...
constant PATH (line 145) | const PATH: &'static str = E::PATH;
method fmt (line 152) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
function extractor_rejection_is_transformed (line 165) | async fn extractor_rejection_is_transformed() {
FILE: axum-extra/src/handler/mod.rs
type HandlerCallWithExtractors (line 25) | pub trait HandlerCallWithExtractors<T, S>: Sized {
method call (line 30) | fn call(self, extractors: T, state: S) -> <Self as HandlerCallWithExtr...
method into_handler (line 33) | fn into_handler(self) -> IntoHandler<Self, T, S> {
method or (line 105) | fn or<R, Rt>(self, rhs: R) -> Or<Self, R, T, Rt, S>
type IntoHandler (line 162) | pub struct IntoHandler<H, T, S> {
type Future (line 174) | type Future = BoxFuture<'static, Response>;
function call (line 176) | fn call(self, req: Request, state: S) -> Self::Future {
method clone (line 193) | fn clone(&self) -> Self {
FILE: axum-extra/src/handler/or.rs
type Or (line 17) | pub struct Or<L, R, Lt, Rt, S> {
type Future (line 31) | type Future = EitherFuture<
function call (line 36) | fn call(
type Future (line 67) | type Future = BoxFuture<'static, Response>;
function call (line 69) | fn call(self, req: Request, state: S) -> Self::Future {
method clone (line 99) | fn clone(&self) -> Self {
function works (line 120) | async fn works() {
FILE: axum-extra/src/json_lines.rs
type AsExtractor (line 85) | pub struct AsExtractor;
type AsResponse (line 90) | pub struct AsResponse;
function new (line 94) | pub fn new(stream: S) -> Self {
type Rejection (line 107) | type Rejection = Infallible;
function from_request (line 109) | async fn from_request(req: Request, _state: &S) -> Result<Self, Self::Re...
type Item (line 135) | type Item = Result<T, axum_core::Error>;
method poll_next (line 137) | fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<...
method into_response (line 153) | fn into_response(self) -> Response {
type User (line 189) | struct User {
function extractor (line 194) | async fn extractor() {
function response (line 231) | async fn response() {
FILE: axum-extra/src/lib.rs
constant FRAGMENT (line 85) | const FRAGMENT: &AsciiSet = &CONTROLS.add(b' ').add(b'"').add(b'<').add(...
constant PATH (line 86) | const PATH: &AsciiSet = &FRAGMENT.add(b'#').add(b'?').add(b'{').add(b'}');
constant PATH_SEGMENT (line 87) | pub const PATH_SEGMENT: &AsciiSet = &PATH.add(b'/').add(b'%');
FILE: axum-extra/src/middleware.rs
function option_layer (line 33) | pub fn option_layer<L>(layer: Option<L>) -> Either<(ResponseAxumBodyLaye...
function remap_response_body (line 55) | fn remap_response_body() {
FILE: axum-extra/src/protobuf.rs
type Protobuf (line 94) | pub struct Protobuf<T>(pub T);
type Rejection (line 101) | type Rejection = ProtobufRejection;
function from_request (line 103) | async fn from_request(req: Request, _: &S) -> Result<Self, Self::Rejecti...
function from (line 121) | fn from(inner: T) -> Self {
method into_response (line 130) | fn into_response(self) -> Response {
function decode_body (line 173) | async fn decode_body() {
function prost_decode_error (line 200) | async fn prost_decode_error() {
function encode_body (line 227) | async fn encode_body() {
FILE: axum-extra/src/response/attachment.rs
type Attachment (line 39) | pub struct Attachment<T> {
function new (line 47) | pub fn new(inner: T) -> Self {
function filename (line 58) | pub fn filename<H: TryInto<HeaderValue>>(mut self, value: H) -> Self {
function content_type (line 69) | pub fn content_type<H: TryInto<HeaderValue>>(mut self, value: H) -> Self {
method into_response (line 83) | fn into_response(self) -> axum_core::response::Response {
function attachment_without_filename (line 113) | fn attachment_without_filename() {
function attachment_with_normal_filename (line 120) | fn attachment_with_normal_filename() {
function attachment_filename_escapes_quotes (line 129) | fn attachment_filename_escapes_quotes() {
function attachment_filename_escapes_backslashes (line 143) | fn attachment_filename_escapes_backslashes() {
FILE: axum-extra/src/response/content_disposition.rs
type EscapedFilename (line 8) | pub(crate) struct EscapedFilename<'a>(pub &'a str);
function fmt (line 11) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
function no_special_characters (line 27) | fn no_special_characters() {
function escapes_double_quotes (line 32) | fn escapes_double_quotes() {
function escapes_backslashes (line 40) | fn escapes_backslashes() {
FILE: axum-extra/src/response/erased_json.rs
type ErasedJson (line 43) | pub struct ErasedJson(Result<Bytes, Arc<serde_json::Error>>);
method new (line 47) | pub fn new<T: Serialize>(val: T) -> Self {
method pretty (line 57) | pub fn pretty<T: Serialize>(val: T) -> Self {
method into_response (line 71) | fn into_response(self) -> Response {
FILE: axum-extra/src/response/error_response.rs
type InternalServerError (line 28) | pub struct InternalServerError<T>(pub T);
method into_response (line 31) | fn into_response(self) -> Response {
function internal_server_error (line 47) | fn internal_server_error() {
FILE: axum-extra/src/response/file_stream.rs
type FileStream (line 49) | pub struct FileStream<S> {
function new (line 65) | pub fn new(stream: S) -> Self {
function file_name (line 76) | pub fn file_name(mut self, file_name: impl Into<String>) -> Self {
function content_size (line 82) | pub fn content_size(mut self, len: u64) -> Self {
function into_range_response (line 126) | pub fn into_range_response(self, start: u64, end: u64, total_size: u64) ...
function try_range_response (line 184) | pub async fn try_range_response(
function from_path (line 244) | pub async fn from_path(path: impl AsRef<Path>) -> io::Result<Self> {
method into_response (line 273) | fn into_response(self) -> Response {
function response (line 313) | async fn response() -> Result<(), Box<dyn std::error::Error>> {
function response_not_set_filename (line 352) | async fn response_not_set_filename() -> Result<(), Box<dyn std::error::E...
function response_not_set_content_size (line 392) | async fn response_not_set_content_size() -> Result<(), Box<dyn std::erro...
function response_with_content_size_and_filename (line 434) | async fn response_with_content_size_and_filename() -> Result<(), Box<dyn...
function response_from_path (line 481) | async fn response_from_path() -> Result<(), Box<dyn std::error::Error>> {
function response_range_file (line 533) | async fn response_range_file() -> Result<(), Box<dyn std::error::Error>> {
function range_stream (line 573) | async fn range_stream(headers: HeaderMap) -> Response {
function parse_range_header (line 593) | fn parse_range_header(range: &str) -> Option<(u64, u64)> {
function filename_escapes_quotes (line 608) | async fn filename_escapes_quotes() -> Result<(), Box<dyn std::error::Err...
function filename_escapes_backslashes (line 635) | async fn filename_escapes_backslashes() -> Result<(), Box<dyn std::error...
function response_range_empty_file (line 661) | async fn response_range_empty_file() -> Result<(), Box<dyn std::error::E...
FILE: axum-extra/src/response/multiple.rs
type MultipartForm (line 13) | pub struct MultipartForm {
method with_parts (line 28) | pub fn with_parts(parts: Vec<Part>) -> Self {
method from_iter (line 205) | fn from_iter<T: IntoIterator<Item = Part>>(iter: T) -> Self {
method into_response (line 34) | fn into_response(self) -> Response {
type Part (line 68) | pub struct Part {
method text (line 108) | pub fn text(name: String, contents: &str) -> Self {
method file (line 133) | pub fn file(field_name: &str, file_name: &str, contents: Vec<u8>) -> S...
method raw_part (line 160) | pub fn raw_part(
method serialize (line 176) | pub(super) fn serialize(&self) -> Vec<u8> {
function generate_boundary (line 217) | fn generate_boundary() -> String {
function process_form (line 236) | async fn process_form() -> Result<(), Box<dyn std::error::Error>> {
function valid_boundary_generation (line 286) | fn valid_boundary_generation() {
FILE: axum-extra/src/routing/mod.rs
function __private_validate_static_path (line 32) | pub const fn __private_validate_static_path(path: &'static str) -> &'sta...
type RouterExt (line 119) | pub trait RouterExt<S>: sealed::Sealed {
method typed_get (line 127) | fn typed_get<H, T, P>(self, handler: H) -> Self
method typed_delete (line 140) | fn typed_delete<H, T, P>(self, handler: H) -> Self
method typed_head (line 153) | fn typed_head<H, T, P>(self, handler: H) -> Self
method typed_options (line 166) | fn typed_options<H, T, P>(self, handler: H) -> Self
method typed_patch (line 179) | fn typed_patch<H, T, P>(self, handler: H) -> Self
method typed_post (line 192) | fn typed_post<H, T, P>(self, handler: H) -> Self
method typed_put (line 205) | fn typed_put<H, T, P>(self, handler: H) -> Self
method typed_trace (line 218) | fn typed_trace<H, T, P>(self, handler: H) -> Self
method typed_connect (line 231) | fn typed_connect<H, T, P>(self, handler: H) -> Self
method route_with_tsr (line 262) | fn route_with_tsr(self, path: &str, method_router: MethodRouter<S>) ->...
method route_service_with_tsr (line 269) | fn route_service_with_tsr<T>(self, path: &str, service: T) -> Self
function typed_get (line 282) | fn typed_get<H, T, P>(self, handler: H) -> Self
function typed_delete (line 292) | fn typed_delete<H, T, P>(self, handler: H) -> Self
function typed_head (line 302) | fn typed_head<H, T, P>(self, handler: H) -> Self
function typed_options (line 312) | fn typed_options<H, T, P>(self, handler: H) -> Self
function typed_patch (line 322) | fn typed_patch<H, T, P>(self, handler: H) -> Self
function typed_post (line 332) | fn typed_post<H, T, P>(self, handler: H) -> Self
function typed_put (line 342) | fn typed_put<H, T, P>(self, handler: H) -> Self
function typed_trace (line 352) | fn typed_trace<H, T, P>(self, handler: H) -> Self
function typed_connect (line 362) | fn typed_connect<H, T, P>(self, handler: H) -> Self
function route_with_tsr (line 372) | fn route_with_tsr(mut self, path: &str, method_router: MethodRouter<S>) ...
function route_service_with_tsr (line 383) | fn route_service_with_tsr<T>(mut self, path: &str, service: T) -> Self
function validate_tsr_path (line 397) | fn validate_tsr_path(path: &str) {
function add_tsr_redirect_route (line 403) | fn add_tsr_redirect_route<S>(
function map_path (line 445) | fn map_path<F>(original_uri: Uri, f: F) -> Option<Uri>
type Sealed (line 465) | pub trait Sealed {}
function test_tsr (line 479) | async fn test_tsr() {
function tsr_with_params (line 502) | async fn tsr_with_params() {
function tsr_maintains_query_params (line 533) | async fn tsr_maintains_query_params() {
function tsr_works_in_nested_router (line 544) | async fn tsr_works_in_nested_router() {
function tsr_independent_route_registration (line 560) | fn tsr_independent_route_registration() {
function tsr_at_root (line 568) | fn tsr_at_root() {
FILE: axum-extra/src/routing/resource.rs
type Resource (line 36) | pub struct Resource<S = ()> {
function named (line 48) | pub fn named(resource_name: &str) -> Self {
function index (line 56) | pub fn index<H, T>(self, handler: H) -> Self
function create (line 66) | pub fn create<H, T>(self, handler: H) -> Self
function new (line 76) | pub fn new<H, T>(self, handler: H) -> Self
function show (line 88) | pub fn show<H, T>(self, handler: H) -> Self
function edit (line 100) | pub fn edit<H, T>(self, handler: H) -> Self
function update (line 112) | pub fn update<H, T>(self, handler: H) -> Self
function destroy (line 127) | pub fn destroy<H, T>(self, handler: H) -> Self
function index_create_path (line 136) | fn index_create_path(&self) -> String {
function show_update_destroy_path (line 140) | fn show_update_destroy_path(&self) -> String {
function route (line 144) | fn route(mut self, path: &str, method_router: MethodRouter<S>) -> Self {
function from (line 151) | fn from(resource: Resource<S>) -> Self {
function works (line 166) | async fn works() {
function call_route (line 216) | async fn call_route(app: &Router, method: Method, uri: &str) -> String {
FILE: axum-extra/src/routing/typed.rs
type TypedPath (line 217) | pub trait TypedPath: std::fmt::Display {
constant PATH (line 219) | const PATH: &'static str;
method to_uri (line 232) | fn to_uri(&self) -> Uri {
method with_query_params (line 269) | fn with_query_params<T>(self, params: T) -> WithQueryParams<Self, T>
constant PATH (line 317) | const PATH: &'static str = P::PATH;
type WithQueryParams (line 282) | pub struct WithQueryParams<P, T> {
function fmt (line 292) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
type SecondElementIs (line 331) | pub trait SecondElementIs<P>: Sealed {}
type UsersShow (line 392) | struct UsersShow {
type Params (line 397) | struct Params {
function with_params (line 404) | fn with_params() {
function with_params_called_multiple_times (line 422) | fn with_params_called_multiple_times() {
function supports_with_rejection (line 438) | fn supports_with_rejection() {
FILE: axum-extra/src/typed_header.rs
type TypedHeader (line 55) | pub struct TypedHeader<T>(pub T);
type Rejection (line 62) | type Rejection = TypedHeaderRejection;
function from_request_parts (line 64) | async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result<Sel...
type Rejection (line 86) | type Rejection = TypedHeaderRejection;
function from_request_parts (line 88) | async fn from_request_parts(
type Error (line 111) | type Error = Infallible;
method into_response_parts (line 113) | fn into_response_parts(self, mut res: ResponseParts) -> Result<ResponseP...
method into_response (line 123) | fn into_response(self) -> Response {
type TypedHeaderRejection (line 133) | pub struct TypedHeaderRejection {
method name (line 141) | pub fn name(&self) -> &http::header::HeaderName {
method reason (line 147) | pub fn reason(&self) -> &TypedHeaderRejectionReason {
method is_missing (line 155) | pub fn is_missing(&self) -> bool {
method fmt (line 191) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
method source (line 204) | fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
type TypedHeaderRejectionReason (line 164) | pub enum TypedHeaderRejectionReason {
method is_missing (line 176) | pub fn is_missing(&self) -> bool {
method into_response (line 182) | fn into_response(self) -> Response {
function typed_header (line 219) | async fn typed_header() {
FILE: axum-macros/src/attr_parsing.rs
function parse_parenthesized_attribute (line 7) | pub(crate) fn parse_parenthesized_attribute<K, T>(
function parse_assignment_attribute (line 32) | pub(crate) fn parse_assignment_attribute<K, T>(
type Combine (line 55) | pub(crate) trait Combine: Sized {
method combine (line 56) | fn combine(self, other: Self) -> syn::Result<Self>;
function parse_attrs (line 59) | pub(crate) fn parse_attrs<T>(ident: &str, attrs: &[syn::Attribute]) -> s...
function combine_attribute (line 70) | pub(crate) fn combine_attribute<K, T>(a: &mut Option<(K, T)>, b: Option<...
function combine_unary_attribute (line 85) | pub(crate) fn combine_unary_attribute<K>(a: &mut Option<K>, b: Option<K>...
function second (line 100) | pub(crate) fn second<T, K>(tuple: (T, K)) -> K {
FILE: axum-macros/src/axum_test.rs
function expand (line 5) | pub(crate) fn expand(_attr: Attrs, mut item_fn: ItemFn) -> TokenStream {
type Attrs (line 16) | pub(crate) struct Attrs;
method parse (line 19) | fn parse(_input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
function replace_nest_with_nest_service (line 24) | fn replace_nest_with_nest_service(mut item_fn: ItemFn) -> Option<ItemFn> {
type NestToNestService (line 34) | struct NestToNestService {
method visit_expr_method_call_mut (line 39) | fn visit_expr_method_call_mut(&mut self, i: &mut syn::ExprMethodCall) {
FILE: axum-macros/src/debug_handler.rs
function expand (line 11) | pub(crate) fn expand(attr: Attrs, item_fn: &ItemFn, kind: FunctionKind) ...
type FunctionKind (line 92) | pub(crate) enum FunctionKind {
method fmt (line 98) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
method name_uppercase_plural (line 107) | fn name_uppercase_plural(self) -> &'static str {
type Attrs (line 120) | pub(crate) struct Attrs {
method parse (line 125) | fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
function check_extractor_count (line 143) | fn check_extractor_count(item_fn: &ItemFn, kind: FunctionKind) -> Option...
function extractor_idents (line 164) | fn extractor_idents(
function check_path_extractor (line 190) | fn check_path_extractor(item_fn: &ItemFn, kind: FunctionKind) -> TokenSt...
function is_self_pat_type (line 213) | fn is_self_pat_type(typed: &syn::PatType) -> bool {
function check_inputs_impls_from_request (line 223) | fn check_inputs_impls_from_request(
function check_output_tuples (line 341) | fn check_output_tuples(item_fn: &ItemFn) -> TokenStream {
function check_into_response (line 397) | fn check_into_response(handler: &Ident, ty: &Type) -> TokenStream {
function check_is_response_parts (line 437) | fn check_is_response_parts(ty: &Type, ident: &Ident, index: usize) -> To...
function check_into_response_parts (line 456) | fn check_into_response_parts(ty: &Type, ident: &Ident, index: usize) -> ...
function check_input_order (line 498) | fn check_input_order(item_fn: &ItemFn, kind: FunctionKind) -> Option<Tok...
function extract_clean_typename (line 577) | fn extract_clean_typename(ty: &Type) -> Option<String> {
function request_consuming_type_name (line 585) | fn request_consuming_type_name(ty: &Type) -> Option<&'static str> {
function well_known_last_response_type (line 606) | fn well_known_last_response_type(ty: &Type) -> Option<&'static str> {
function check_output_impls_into_response (line 622) | fn check_output_impls_into_response(item_fn: &ItemFn) -> TokenStream {
function check_future_send (line 711) | fn check_future_send(item_fn: &ItemFn, kind: FunctionKind) -> TokenStream {
function self_receiver (line 771) | fn self_receiver(item_fn: &ItemFn) -> Option<TokenStream> {
function state_types_from_args (line 813) | fn state_types_from_args(item_fn: &ItemFn) -> HashSet<Type> {
function next_is_last_input (line 826) | fn next_is_last_input(item_fn: &ItemFn) -> TokenStream {
function skip_next_arg (line 863) | fn skip_next_arg(arg: &FnArg, kind: FunctionKind) -> bool {
function ui_debug_handler (line 884) | fn ui_debug_handler() {
function ui_debug_middleware (line 889) | fn ui_debug_middleware() {
FILE: axum-macros/src/from_ref.rs
function expand (line 11) | pub(crate) fn expand(item: ItemStruct) -> syn::Result<TokenStream> {
function expand_field (line 29) | fn expand_field(state: &Ident, idx: usize, field: &Field) -> TokenStream {
type FieldAttrs (line 71) | pub(super) struct FieldAttrs {
method parse (line 76) | fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
method combine (line 95) | fn combine(mut self, other: Self) -> syn::Result<Self> {
function ui (line 103) | fn ui() {
FILE: axum-macros/src/from_request/attr.rs
type FromRequestContainerAttrs (line 14) | pub(super) struct FromRequestContainerAttrs {
method parse (line 21) | fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
method combine (line 50) | fn combine(mut self, other: Self) -> syn::Result<Self> {
type FromRequestFieldAttrs (line 64) | pub(super) struct FromRequestFieldAttrs {
method parse (line 69) | fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
method combine (line 88) | fn combine(mut self, other: Self) -> syn::Result<Self> {
FILE: axum-macros/src/from_request/mod.rs
type Trait (line 16) | pub(crate) enum Trait {
method via_marker_type (line 22) | fn via_marker_type(self) -> Option<Type> {
method fmt (line 31) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
type State (line 40) | enum State {
method impl_generics (line 51) | fn impl_generics(&self) -> impl Iterator<Item = Type> {
method trait_generics (line 64) | fn trait_generics(&self) -> impl Iterator<Item = Type> {
method bounds (line 71) | fn bounds(&self) -> TokenStream {
method to_tokens (line 85) | fn to_tokens(&self, tokens: &mut TokenStream) {
function expand (line 93) | pub(crate) fn expand(item: syn::Item, tr: Trait) -> syn::Result<TokenStr...
function parse_single_generic_type_on_struct (line 230) | fn parse_single_generic_type_on_struct(
function error_on_generic_ident (line 317) | fn error_on_generic_ident(generic_ident: Option<Ident>, tr: Trait) -> sy...
function impl_struct_by_extracting_each_field (line 330) | fn impl_struct_by_extracting_each_field(
function has_no_fields (line 404) | fn has_no_fields(fields: &syn::Fields) -> bool {
function extract_fields (line 412) | fn extract_fields(
function peel_option (line 641) | fn peel_option(ty: &syn::Type) -> Option<&syn::Type> {
function peel_result_ok (line 670) | fn peel_result_ok(ty: &syn::Type) -> Option<&syn::Type> {
function impl_struct_by_extracting_all_at_once (line 699) | fn impl_struct_by_extracting_all_at_once(
function impl_enum_by_extracting_all_at_once (line 871) | fn impl_enum_by_extracting_all_at_once(
function infer_state_type_from_field_types (line 987) | fn infer_state_type_from_field_types(fields: &Fields) -> impl Iterator<I...
function infer_state_type_from_field_attributes (line 1010) | fn infer_state_type_from_field_attributes(fields: &Fields) -> impl Itera...
function path_ident_is_state (line 1036) | fn path_ident_is_state(path: &Path) -> bool {
function state_from_via (line 1044) | fn state_from_via(ident: &Ident, via: &Path) -> Option<Type> {
function ui (line 1049) | fn ui() {
function test_field_doesnt_impl_from_request (line 1063) | fn test_field_doesnt_impl_from_request() {}
FILE: axum-macros/src/lib.rs
function derive_from_request (line 376) | pub fn derive_from_request(item: TokenStream) -> TokenStream {
function derive_from_request_parts (line 425) | pub fn derive_from_request_parts(item: TokenStream) -> TokenStream {
function debug_handler (line 576) | pub fn debug_handler(_attr: TokenStream, input: TokenStream) -> TokenStr...
function debug_middleware (line 632) | pub fn debug_middleware(_attr: TokenStream, input: TokenStream) -> Token...
function __private_axum_test (line 654) | pub fn __private_axum_test(_attr: TokenStream, input: TokenStream) -> To...
function derive_typed_path (line 664) | pub fn derive_typed_path(input: TokenStream) -> TokenStream {
function derive_from_ref (line 714) | pub fn derive_from_ref(item: TokenStream) -> TokenStream {
function expand_with (line 718) | fn expand_with<F, I, K>(input: TokenStream, f: F) -> TokenStream
function expand_attr_with (line 727) | fn expand_attr_with<F, A, I, K>(attr: TokenStream, input: TokenStream, f...
function expand (line 742) | fn expand<T>(result: syn::Result<T>) -> TokenStream
function infer_state_types (line 758) | fn infer_state_types<'a, I>(types: I) -> impl Iterator<Item = Type> + 'a
function run_ui_tests (line 797) | fn run_ui_tests(directory: &str) {
FILE: axum-macros/src/typed_path.rs
function expand (line 7) | pub(crate) fn expand(item_struct: &ItemStruct) -> syn::Result<TokenStrea...
type Attrs (line 57) | struct Attrs {
method parse (line 63) | fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
method combine (line 85) | fn combine(mut self, other: Self) -> syn::Result<Self> {
function expand_named_fields (line 101) | fn expand_named_fields(
function expand_unnamed_fields (line 169) | fn expand_unnamed_fields(
function simple_pluralize (line 274) | fn simple_pluralize(count: usize, word: &str) -> String {
function expand_unit_fields (line 282) | fn expand_unit_fields(
function format_str_from_path (line 358) | fn format_str_from_path(segments: &[Segment]) -> String {
function captures_from_path (line 369) | fn captures_from_path(segments: &[Segment]) -> Vec<syn::Ident> {
function parse_path (line 379) | fn parse_path(path: &LitStr) -> syn::Result<Vec<Segment>> {
type Segment (line 409) | enum Segment {
function path_rejection (line 414) | fn path_rejection() -> TokenStream {
function rejection_assoc_type (line 420) | fn rejection_assoc_type(rejection: Option<&syn::Path>) -> TokenStream {
function map_err_rejection (line 427) | fn map_err_rejection(rejection: Option<&syn::Path>) -> TokenStream {
function ui (line 442) | fn ui() {
FILE: axum-macros/src/with_position.rs
type WithPosition (line 31) | pub(crate) struct WithPosition<I>
function new (line 43) | pub(crate) fn new(iter: impl IntoIterator<IntoIter = I>) -> Self {
method clone (line 56) | fn clone(&self) -> Self {
type Position (line 65) | pub(crate) enum Position<T> {
function into_inner (line 73) | pub(crate) fn into_inner(self) -> T {
type Item (line 81) | type Item = Position<I::Item>;
method next (line 83) | fn next(&mut self) -> Option<Self::Item> {
method size_hint (line 109) | fn size_hint(&self) -> (usize, Option<usize>) {
FILE: axum-macros/tests/debug_handler/fail/argument_not_extractor.rs
function handler (line 4) | async fn handler(_foo: bool) {}
function main (line 6) | fn main() {}
FILE: axum-macros/tests/debug_handler/fail/duplicate_args.rs
function handler (line 4) | async fn handler() {}
function main (line 6) | fn main() {}
FILE: axum-macros/tests/debug_handler/fail/extension_not_clone.rs
type NonCloneType (line 4) | struct NonCloneType;
function test_extension_non_clone (line 7) | async fn test_extension_non_clone(_: Extension<NonCloneType>) {}
function main (line 9) | fn main() {}
FILE: axum-macros/tests/debug_handler/fail/extract_self_mut.rs
type A (line 4) | struct A;
type Rejection (line 10) | type Rejection = ();
method from_request (line 12) | async fn from_request(_req: Request, _state: &S) -> Result<Self, Self:...
method handler (line 19) | async fn handler(&mut self) {}
function main (line 22) | fn main() {}
FILE: axum-macros/tests/debug_handler/fail/extract_self_ref.rs
type A (line 4) | struct A;
type Rejection (line 10) | type Rejection = ();
method from_request (line 12) | async fn from_request(_req: Request, _state: &S) -> Result<Self, Self:...
method handler (line 19) | async fn handler(&self) {}
function main (line 22) | fn main() {}
FILE: axum-macros/tests/debug_handler/fail/generics.rs
function handler (line 4) | async fn handler<T>(_extract: T) {}
function main (line 6) | fn main() {}
FILE: axum-macros/tests/debug_handler/fail/invalid_attrs.rs
function handler (line 4) | async fn handler() {}
function main (line 6) | fn main() {}
FILE: axum-macros/tests/debug_handler/fail/json_not_deserialize.rs
type Struct (line 4) | struct Struct {}
function handler (line 7) | async fn handler(_foo: Json<Struct>) {}
function main (line 9) | fn main() {}
FILE: axum-macros/tests/debug_handler/fail/multiple_paths.rs
function handler (line 5) | async fn handler(_: Path<String>, _: Path<String>) {}
function main (line 7) | fn main() {}
FILE: axum-macros/tests/debug_handler/fail/multiple_request_consumers.rs
function one (line 9) | async fn one(_: Json<()>, _: String, _: Uri) {}
function two (line 12) | async fn two(_: Json<()>, _: Method, _: Bytes, _: Uri, _: String) {}
function main (line 14) | fn main() {}
FILE: axum-macros/tests/debug_handler/fail/not_a_function.rs
type A (line 4) | struct A;
function main (line 6) | fn main() {}
FILE: axum-macros/tests/debug_handler/fail/not_async.rs
function handler (line 4) | fn handler() {}
function main (line 6) | fn main() {}
FILE: axum-macros/tests/debug_handler/fail/not_send.rs
function handler (line 4) | async fn handler() {
function main (line 9) | fn main() {}
FILE: axum-macros/tests/debug_handler/fail/output_tuple_too_many.rs
function handler (line 4) | async fn handler() -> (
function main (line 28) | fn main() {}
FILE: axum-macros/tests/debug_handler/fail/returning_request_parts.rs
function handler (line 2) | async fn handler() -> (
function main (line 9) | fn main() {}
FILE: axum-macros/tests/debug_handler/fail/single_wrong_return_tuple.rs
type NotIntoResponse (line 3) | struct NotIntoResponse;
function handler (line 6) | async fn handler() -> (NotIntoResponse) {
function main (line 10) | fn main() {}
FILE: axum-macros/tests/debug_handler/fail/too_many_extractors.rs
function handler (line 5) | async fn handler(
function main (line 26) | fn main() {}
FILE: axum-macros/tests/debug_handler/fail/wrong_order.rs
function one (line 5) | async fn one(_: Json<()>, _: Uri) {}
function two (line 8) | async fn two(_: String, _: Uri) {}
function main (line 10) | fn main() {}
FILE: axum-macros/tests/debug_handler/fail/wrong_return_tuple.rs
function named_type (line 4) | async fn named_type() -> (
type CustomIntoResponse (line 12) | struct CustomIntoResponse {}
method into_response (line 14) | fn into_response(self) -> axum::response::Response {
function custom_type (line 19) | async fn custom_type() -> (
function main (line 27) | fn main() {}
FILE: axum-macros/tests/debug_handler/fail/wrong_return_type.rs
function handler (line 4) | async fn handler() -> bool {
function main (line 8) | fn main() {}
FILE: axum-macros/tests/debug_handler/pass/associated_fn_without_self.rs
type A (line 3) | struct A;
method handler (line 7) | async fn handler() {}
function main (line 10) | fn main() {}
FILE: axum-macros/tests/debug_handler/pass/deny_unreachable_code.rs
function handler (line 6) | async fn handler(Path(_): Path<String>) {}
function main (line 8) | fn main() {}
FILE: axum-macros/tests/debug_handler/pass/impl_future.rs
function handler (line 5) | fn handler() -> impl Future<Output = ()> {
function main (line 9) | fn main() {}
FILE: axum-macros/tests/debug_handler/pass/impl_into_response.rs
function handler (line 5) | async fn handler() -> impl IntoResponse {
function main (line 9) | fn main() {}
FILE: axum-macros/tests/debug_handler/pass/infer_state.rs
function handler (line 5) | async fn handler(_: State<AppState>) {}
function handler_2 (line 8) | async fn handler_2(_: axum::extract::State<AppState>) {}
function handler_3 (line 11) | async fn handler_3(_: axum::extract::State<AppState>, _: axum::extract::...
function handler_4 (line 14) | async fn handler_4(_: State<AppState>, _: State<AppState>) {}
function handler_5 (line 17) | async fn handler_5(_: axum::extract::State<AppState>, _: State<AppState>...
type AppState (line 20) | struct AppState;
function main (line 22) | fn main() {}
FILE: axum-macros/tests/debug_handler/pass/multiple_extractors.rs
function handler (line 5) | async fn handler(_one: Method, _two: Uri, _three: String) {}
function main (line 7) | fn main() {}
FILE: axum-macros/tests/debug_handler/pass/mut_extractor.rs
function handler (line 4) | async fn handler(mut foo: String) -> String {
function main (line 9) | fn main() {}
FILE: axum-macros/tests/debug_handler/pass/ready.rs
function handler (line 5) | fn handler() -> Ready<()> {
function main (line 9) | fn main() {}
FILE: axum-macros/tests/debug_handler/pass/request_last.rs
function handler (line 5) | async fn handler(_: Extension<String>, _: Request) {}
function main (line 7) | fn main() {}
FILE: axum-macros/tests/debug_handler/pass/result_impl_into_response.rs
function main (line 4) | fn main() {}
function concrete_future (line 7) | fn concrete_future() -> std::future::Ready<Result<impl IntoResponse, ()>> {
function impl_future (line 12) | fn impl_future() -> impl std::future::Future<Output = Result<impl IntoRe...
function handler_no_arg_one (line 19) | async fn handler_no_arg_one() -> Result<impl IntoResponse, ()> {
function handler_no_arg_two (line 24) | async fn handler_no_arg_two() -> Result<(), impl IntoResponse> {
function handler_no_arg_three (line 29) | async fn handler_no_arg_three() -> Result<impl IntoResponse, impl IntoRe...
function handler_no_arg_four (line 34) | async fn handler_no_arg_four() -> Result<impl IntoResponse, impl IntoRes...
function handler_one (line 41) | async fn handler_one(foo: String) -> Result<impl IntoResponse, ()> {
function handler_two (line 47) | async fn handler_two(foo: String) -> Result<(), impl IntoResponse> {
function handler_three (line 53) | async fn handler_three(foo: String) -> Result<impl IntoResponse, impl In...
function handler_four (line 59) | async fn handler_four(foo: String) -> Result<impl IntoResponse, impl Int...
type A (line 66) | struct A;
method handler_no_arg_one (line 70) | async fn handler_no_arg_one(self) -> Result<impl IntoResponse, ()> {
method handler_no_arg_two (line 75) | async fn handler_no_arg_two(self) -> Result<(), impl IntoResponse> {
method handler_no_arg_three (line 80) | async fn handler_no_arg_three(self) -> Result<impl IntoResponse, impl ...
method handler_no_arg_four (line 85) | async fn handler_no_arg_four(self) -> Result<impl IntoResponse, impl I...
method handler_one (line 94) | async fn handler_one(self, foo: String) -> Result<impl IntoResponse, (...
method handler_two (line 100) | async fn handler_two(self, foo: String) -> Result<(), impl IntoRespons...
method handler_three (line 106) | async fn handler_three(self, foo: String) -> Result<impl IntoResponse,...
method handler_four (line 112) | async fn handler_four(self, foo: String) -> Result<impl IntoResponse, ...
type Rejection (line 122) | type Rejection = ();
method from_request_parts (line 124) | async fn from_request_parts(_parts: &mut Parts, _state: &S) -> Result<...
FILE: axum-macros/tests/debug_handler/pass/returns_self.rs
type A (line 4) | struct A;
method handler (line 8) | async fn handler() -> Self {
method into_response (line 14) | fn into_response(self) -> Response {
function main (line 19) | fn main() {}
FILE: axum-macros/tests/debug_handler/pass/self_receiver.rs
type A (line 4) | struct A;
type Rejection (line 10) | type Rejection = ();
method from_request (line 12) | async fn from_request(_req: Request, _state: &S) -> Result<Self, Self:...
method handler (line 30) | async fn handler(self) {}
method handler_with_qualified_self (line 33) | async fn handler_with_qualified_self(self: Box<Self>) {}
type Rejection (line 21) | type Rejection = ();
function from_request (line 23) | async fn from_request(_req: Request, _state: &S) -> Result<Self, Self::R...
function main (line 36) | fn main() {}
FILE: axum-macros/tests/debug_handler/pass/set_state.rs
function handler (line 5) | async fn handler(_: A) {}
type AppState (line 8) | struct AppState;
type A (line 10) | struct A;
type Rejection (line 17) | type Rejection = ();
method from_request (line 19) | async fn from_request(_req: Request, _state: &S) -> Result<Self, Self:...
function main (line 24) | fn main() {}
FILE: axum-macros/tests/debug_handler/pass/state_and_body.rs
function handler (line 5) | async fn handler(_: State<AppState>, _: Request) {}
type AppState (line 8) | struct AppState;
function main (line 10) | fn main() {}
FILE: axum-macros/tests/debug_middleware/fail/doesnt_take_next.rs
function my_middleware (line 8) | async fn my_middleware(request: Request) -> Response {
function main (line 13) | fn main() {}
FILE: axum-macros/tests/debug_middleware/fail/next_not_last.rs
function my_middleware (line 4) | async fn my_middleware(next: Next, request: Request) -> Response {
function main (line 8) | fn main() {}
FILE: axum-macros/tests/debug_middleware/fail/takes_next_twice.rs
function my_middleware (line 4) | async fn my_middleware(request: Request, next: Next, next2: Next) -> Res...
function main (line 9) | fn main() {}
FILE: axum-macros/tests/debug_middleware/pass/basic.rs
function my_middleware (line 4) | async fn my_middleware(request: Request, next: Next) -> Response {
function main (line 8) | fn main() {}
FILE: axum-macros/tests/from_ref/fail/generics.rs
type AppState (line 4) | struct AppState<T> {
function main (line 8) | fn main() {}
FILE: axum-macros/tests/from_ref/pass/basic.rs
type AppState (line 9) | struct AppState {
function handler (line 14) | async fn handler(_: State<String>) {}
function main (line 16) | fn main() {
FILE: axum-macros/tests/from_ref/pass/reference-types.rs
type State (line 6) | struct State {
function main (line 10) | fn main() {}
FILE: axum-macros/tests/from_ref/pass/skip.rs
type AppState (line 4) | struct AppState {
function main (line 10) | fn main() {}
FILE: axum-macros/tests/from_request/fail/double_via_attr.rs
type Extractor (line 4) | struct Extractor(#[from_request(via(axum::Extension), via(axum::Extensio...
type State (line 7) | struct State;
function main (line 9) | fn main() {}
FILE: axum-macros/tests/from_request/fail/enum_from_request_ident_in_variant.rs
type Extractor (line 5) | enum Extractor {
function main (line 12) | fn main() {}
FILE: axum-macros/tests/from_request/fail/enum_from_request_on_variant.rs
type Extractor (line 5) | enum Extractor {
function main (line 10) | fn main() {}
FILE: axum-macros/tests/from_request/fail/enum_no_via.rs
type Extractor (line 4) | enum Extractor {}
function main (line 6) | fn main() {}
FILE: axum-macros/tests/from_request/fail/generic.rs
type Extractor (line 4) | struct Extractor<T>(Option<T>);
function main (line 6) | fn main() {}
FILE: axum-macros/tests/from_request/fail/generic_without_via.rs
type Extractor (line 5) | struct Extractor<T>(T);
function foo (line 7) | async fn foo(_: Extractor<()>) {}
function main (line 9) | fn main() {
FILE: axum-macros/tests/from_request/fail/generic_without_via_rejection.rs
type Extractor (line 6) | struct Extractor<T>(T);
function foo (line 8) | async fn foo(_: Extractor<()>) {}
function main (line 10) | fn main() {
FILE: axum-macros/tests/from_request/fail/not_enum_or_struct.rs
function main (line 6) | fn main() {}
FILE: axum-macros/tests/from_request/fail/override_rejection_on_enum_without_via.rs
function main (line 9) | fn main() {
function handler (line 13) | async fn handler(_: MyExtractor) {}
function handler_result (line 15) | async fn handler_result(_: Result<MyExtractor, MyRejection>) {}
type MyExtractor (line 19) | enum MyExtractor {}
type MyRejection (line 21) | struct MyRejection {}
method from (line 24) | fn from(_: ExtensionRejection) -> Self {
method into_response (line 30) | fn into_response(self) -> Response {
FILE: axum-macros/tests/from_request/fail/parts_extracting_body.rs
type Extractor (line 4) | struct Extractor {
function assert_from_request (line 8) | fn assert_from_request()
function main (line 14) | fn main() {}
FILE: axum-macros/tests/from_request/fail/state_infer_multiple_different_types.rs
type Extractor (line 5) | struct Extractor {
type AppState (line 11) | struct AppState {}
type OtherState (line 14) | struct OtherState {}
function assert_from_request (line 16) | fn assert_from_request()
function main (line 22) | fn main() {}
FILE: axum-macros/tests/from_request/fail/unknown_attr_container.rs
type Extractor (line 5) | struct Extractor;
function main (line 7) | fn main() {}
FILE: axum-macros/tests/from_request/fail/unknown_attr_field.rs
type Extractor (line 4) | struct Extractor(#[from_request(foo)] String);
function main (line 6) | fn main() {}
FILE: axum-macros/tests/from_request/fail/via_on_container_and_field.rs
type Extractor (line 5) | struct Extractor(#[from_request(via(axum::Extension))] State);
type State (line 8) | struct State;
function main (line 10) | fn main() {}
FILE: axum-macros/tests/from_request/pass/container.rs
type Extractor (line 10) | struct Extractor {
function assert_from_request (line 16) | fn assert_from_request()
function main (line 22) | fn main() {}
FILE: axum-macros/tests/from_request/pass/container_parts.rs
type Extractor (line 9) | struct Extractor {
function assert_from_request (line 15) | fn assert_from_request()
function main (line 21) | fn main() {}
FILE: axum-macros/tests/from_request/pass/empty_named.rs
type Extractor (line 4) | struct Extractor {}
function assert_from_request (line 6) | fn assert_from_request()
function main (line 12) | fn main() {}
FILE: axum-macros/tests/from_request/pass/empty_named_parts.rs
type Extractor (line 4) | struct Extractor {}
function assert_from_request (line 6) | fn assert_from_request()
function main (line 12) | fn main() {}
FILE: axum-macros/tests/from_request/pass/empty_tuple.rs
type Extractor (line 4) | struct Extractor();
function assert_from_request (line 6) | fn assert_from_request()
function main (line 12) | fn main() {}
FILE: axum-macros/tests/from_request/pass/empty_tuple_parts.rs
type Extractor (line 4) | struct Extractor();
function assert_from_request (line 6) | fn assert_from_request()
function main (line 12) | fn main() {}
FILE: axum-macros/tests/from_request/pass/enum_via.rs
type Extractor (line 6) | enum Extractor {}
function foo (line 8) | async fn foo(_: Extractor) {}
function main (line 10) | fn main() {
FILE: axum-macros/tests/from_request/pass/enum_via_parts.rs
type Extractor (line 6) | enum Extractor {}
function foo (line 8) | async fn foo(_: Extractor) {}
function main (line 10) | fn main() {
FILE: axum-macros/tests/from_request/pass/named.rs
type Extractor (line 9) | struct Extractor {
function assert_from_request (line 18) | fn assert_from_request()
function main (line 24) | fn main() {}
FILE: axum-macros/tests/from_request/pass/named_parts.rs
type Extractor (line 9) | struct Extractor {
function assert_from_request (line 17) | fn assert_from_request()
function main (line 23) | fn main() {}
FILE: axum-macros/tests/from_request/pass/named_via.rs
type Extractor (line 12) | struct Extractor {
function assert_from_request (line 25) | fn assert_from_request()
type State (line 32) | struct State;
function main (line 34) | fn main() {}
FILE: axum-macros/tests/from_request/pass/named_via_parts.rs
type Extractor (line 12) | struct Extractor {
function assert_from_request (line 25) | fn assert_from_request()
type State (line 32) | struct State;
function main (line 34) | fn main() {}
FILE: axum-macros/tests/from_request/pass/override_rejection.rs
function main (line 9) | fn main() {
function handler (line 13) | async fn handler(_: MyExtractor) {}
function handler_result (line 15) | async fn handler_result(_: Result<MyExtractor, MyRejection>) {}
type MyExtractor (line 19) | struct MyExtractor {
type OtherExtractor (line 26) | struct OtherExtractor;
type Rejection (line 33) | type Rejection = (StatusCode, String);
method from_request (line 35) | async fn from_request(_req: Request, _state: &S) -> Result<Self, Self:...
type MyRejection (line 40) | struct MyRejection {}
method from (line 43) | fn from(_: ExtensionRejection) -> Self {
method from (line 49) | fn from(_: (StatusCode, String)) -> Self {
method into_response (line 55) | fn into_response(self) -> Response {
FILE: axum-macros/tests/from_request/pass/override_rejection_non_generic.rs
function main (line 11) | fn main() {
function handler (line 15) | async fn handler(_: MyJson) {}
function handler_result (line 17) | async fn handler_result(_: Result<MyJson, MyJsonRejection>) {}
type MyJson (line 22) | struct MyJson(HashMap<String, String>);
type MyJsonRejection (line 24) | struct MyJsonRejection {}
method from (line 27) | fn from(_: JsonRejection) -> Self {
method into_response (line 33) | fn into_response(self) -> Response {
FILE: axum-macros/tests/from_request/pass/override_rejection_non_generic_parts.rs
function main (line 11) | fn main() {
function handler (line 15) | async fn handler(_: MyQuery) {}
function handler_result (line 17) | async fn handler_result(_: Result<MyQuery, MyQueryRejection>) {}
type MyQuery (line 22) | struct MyQuery(HashMap<String, String>);
type MyQueryRejection (line 24) | struct MyQueryRejection {}
method from (line 27) | fn from(_: QueryRejection) -> Self {
method into_response (line 33) | fn into_response(self) -> Response {
FILE: axum-macros/tests/from_request/pass/override_rejection_parts.rs
function main (line 9) | fn main() {
function handler (line 13) | async fn handler(_: MyExtractor) {}
function handler_result (line 15) | async fn handler_result(_: Result<MyExtractor, MyRejection>) {}
type MyExtractor (line 19) | struct MyExtractor {
type OtherExtractor (line 26) | struct OtherExtractor;
type Rejection (line 33) | type Rejection = (StatusCode, String);
method from_request_parts (line 35) | async fn from_request_parts(_parts: &mut Parts, _state: &S) -> Result<...
type MyRejection (line 40) | struct MyRejection {}
method from (line 43) | fn from(_: ExtensionRejection) -> Self {
method from (line 49) | fn from(_: (StatusCode, String)) -> Self {
method into_response (line 55) | fn into_response(self) -> Response {
FILE: axum-macros/tests/from_request/pass/override_rejection_with_via_on_enum.rs
function main (line 9) | fn main() {
function handler (line 13) | async fn handler(_: MyExtractor) {}
function handler_result (line 15) | async fn handler_result(_: Result<MyExtractor, MyRejection>) {}
type MyExtractor (line 19) | enum MyExtractor {}
type MyRejection (line 21) | struct MyRejection {}
method from (line 24) | fn from(_: ExtensionRejection) -> Self {
method into_response (line 30) | fn into_response(self) -> Response {
FILE: axum-macros/tests/from_request/pass/override_rejection_with_via_on_enum_parts.rs
function main (line 9) | fn main() {
function handler (line 13) | async fn handler(_: MyExtractor) {}
function handler_result (line 15) | async fn handler_result(_: Result<MyExtractor, MyRejection>) {}
type MyExtractor (line 19) | enum MyExtractor {}
type MyRejection (line 21) | struct MyRejection {}
method from (line 24) | fn from(_: ExtensionRejection) -> Self {
method into_response (line 30) | fn into_response(self) -> Response {
FILE: axum-macros/tests/from_request/pass/override_rejection_with_via_on_struct.rs
function main (line 10) | fn main() {
type Payload (line 15) | struct Payload {}
function handler (line 17) | async fn handler(_: MyJson<Payload>) {}
function handler_result (line 19) | async fn handler_result(_: Result<MyJson<Payload>, MyJsonRejection>) {}
type MyJson (line 23) | struct MyJson<T>(T);
type MyJsonRejection (line 25) | struct MyJsonRejection {}
method from (line 28) | fn from(_: JsonRejection) -> Self {
method into_response (line 34) | fn into_response(self) -> Response {
FILE: axum-macros/tests/from_request/pass/override_rejection_with_via_on_struct_parts.rs
function main (line 10) | fn main() {
type Payload (line 15) | struct Payload {}
function handler (line 17) | async fn handler(_: MyQuery<Payload>) {}
function handler_result (line 19) | async fn handler_result(_: Result<MyQuery<Payload>, MyQueryRejection>) {}
type MyQuery (line 23) | struct MyQuery<T>(T);
type MyQueryRejection (line 25) | struct MyQueryRejection {}
method from (line 28) | fn from(_: QueryRejection) -> Self {
method into_response (line 34) | fn into_response(self) -> Response {
FILE: axum-macros/tests/from_request/pass/state_cookie.rs
type Extractor (line 7) | struct Extractor {
type AppState (line 11) | struct AppState {
method from_ref (line 16) | fn from_ref(input: &AppState) -> Self {
function assert_from_request (line 21) | fn assert_from_request()
function main (line 27) | fn main() {}
FILE: axum-macros/tests/from_request/pass/state_enum_via.rs
function main (line 8) | fn main() {
type AppState (line 17) | enum AppState {
method default (line 22) | fn default() -> AppState {
type InnerState (line 29) | enum InnerState {}
method from_ref (line 32) | fn from_ref(_: &AppState) -> Self {
FILE: axum-macros/tests/from_request/pass/state_enum_via_parts.rs
function main (line 8) | fn main() {
type AppState (line 18) | enum AppState {
method default (line 23) | fn default() -> AppState {
type InnerState (line 30) | enum InnerState {}
method from_ref (line 33) | fn from_ref(_: &AppState) -> Self {
FILE: axum-macros/tests/from_request/pass/state_explicit.rs
function main (line 8) | fn main() {
type Extractor (line 16) | struct Extractor {
type AppState (line 24) | struct AppState {
type One (line 30) | struct One {}
method from_ref (line 33) | fn from_ref(input: &AppState) -> Self {
type Two (line 39) | struct Two {}
method from_ref (line 42) | fn from_ref(input: &AppState) -> Self {
FILE: axum-macros/tests/from_request/pass/state_explicit_parts.rs
function main (line 9) | fn main() {
type Extractor (line 17) | struct Extractor {
type AppState (line 23) | struct AppState {
type InnerState (line 28) | struct InnerState {}
method from_ref (line 31) | fn from_ref(input: &AppState) -> Self {
FILE: axum-macros/tests/from_request/pass/state_field_explicit.rs
function main (line 8) | fn main() {
type Extractor (line 16) | struct Extractor {
type AppState (line 24) | struct AppState {
type InnerState (line 29) | struct InnerState {}
method from_ref (line 32) | fn from_ref(input: &AppState) -> Self {
FILE: axum-macros/tests/from_request/pass/state_field_infer.rs
function main (line 4) | fn main() {
type Extractor (line 11) | struct Extractor {
type AppState (line 17) | struct AppState {}
FILE: axum-macros/tests/from_request/pass/state_infer.rs
type Extractor (line 5) | struct Extractor {
type AppState (line 10) | struct AppState {}
function assert_from_request (line 12) | fn assert_from_request()
function main (line 18) | fn main() {}
FILE: axum-macros/tests/from_request/pass/state_infer_multiple.rs
type Extractor (line 5) | struct Extractor {
type AppState (line 11) | struct AppState {}
function assert_from_request (line 13) | fn assert_from_request()
function main (line 19) | fn main() {}
FILE: axum-macros/tests/from_request/pass/state_infer_parts.rs
type Extractor (line 5) | struct Extractor {
type AppState (line 10) | struct AppState {}
function assert_from_request (line 12) | fn assert_from_request()
function main (line 18) | fn main() {}
FILE: axum-macros/tests/from_request/pass/state_via.rs
function main (line 8) | fn main() {
type AppState (line 17) | struct AppState {
type InnerState (line 23) | struct InnerState {}
method from_ref (line 26) | fn from_ref(input: &AppState) -> Self {
FILE: axum-macros/tests/from_request/pass/state_via_infer.rs
function main (line 4) | fn main() {
type AppState (line 14) | struct AppState {}
FILE: axum-macros/tests/from_request/pass/state_via_parts.rs
function main (line 8) | fn main() {
type AppState (line 18) | struct AppState {
type InnerState (line 24) | struct InnerState {}
method from_ref (line 27) | fn from_ref(input: &AppState) -> Self {
FILE: axum-macros/tests/from_request/pass/state_with_rejection.rs
function main (line 10) | fn main() {
type Extractor (line 18) | struct Extractor {
type AppState (line 23) | struct AppState {}
type MyRejection (line 25) | struct MyRejection {}
method from (line 28) | fn from(err: Infallible) -> Self {
method into_response (line 34) | fn into_response(self) -> Response {
FILE: axum-macros/tests/from_request/pass/tuple.rs
type Extractor (line 4) | struct Extractor(axum::http::HeaderMap, String);
function assert_from_request (line 6) | fn assert_from_request()
function main (line 12) | fn main() {}
FILE: axum-macros/tests/from_request/pass/tuple_parts.rs
type Extractor (line 4) | struct Extractor(axum::http::HeaderMap, axum::http::Method);
function assert_from_request (line 6) | fn assert_from_request()
function main (line 12) | fn main() {}
FILE: axum-macros/tests/from_request/pass/tuple_same_type_twice.rs
type Extractor (line 6) | struct Extractor(Query<Payload>, axum::extract::Json<Payload>);
type Payload (line 9) | struct Payload {}
function assert_from_request (line 11) | fn assert_from_request()
function main (line 17) | fn main() {}
FILE: axum-macros/tests/from_request/pass/tuple_same_type_twice_parts.rs
type Extractor (line 6) | struct Extractor(Query<Payload>, axum::extract::Path<Payload>);
type Payload (line 9) | struct Payload {}
function assert_from_request (line 11) | fn assert_from_request()
function main (line 17) | fn main() {}
FILE: axum-macros/tests/from_request/pass/tuple_same_type_twice_via.rs
type Extractor (line 7) | struct Extractor(
type Payload (line 13) | struct Payload {}
function assert_from_request (line 15) | fn assert_from_request()
function main (line 21) | fn main() {}
FILE: axum-macros/tests/from_request/pass/tuple_same_type_twice_via_parts.rs
type Extractor (line 7) | struct Extractor(
type Payload (line 13) | struct Payload {}
function assert_from_request (line 15) | fn assert_from_request()
function main (line 21) | fn main() {}
FILE: axum-macros/tests/from_request/pass/tuple_via.rs
type Extractor (line 5) | struct Extractor(#[from_request(via(Extension))] State);
type State (line 8) | struct State;
function assert_from_request (line 10) | fn assert_from_request()
function main (line 16) | fn main() {}
FILE: axum-macros/tests/from_request/pass/tuple_via_parts.rs
type Extractor (line 5) | struct Extractor(#[from_request(via(Extension))] State);
type State (line 8) | struct State;
function assert_from_request (line 10) | fn assert_from_request()
function main (line 16) | fn main() {}
FILE: axum-macros/tests/from_request/pass/unit.rs
type Extractor (line 4) | struct Extractor;
function assert_from_request (line 6) | fn assert_from_request()
function main (line 12) | fn main() {}
FILE: axum-macros/tests/from_request/pass/unit_parts.rs
type Extractor (line 4) | struct Extractor;
function assert_from_request (line 6) | fn assert_from_request()
function main (line 12) | fn main() {}
FILE: axum-macros/tests/typed_path/fail/missing_capture.rs
type MyPath (line 6) | struct MyPath {
function main (line 10) | fn main() {}
FILE: axum-macros/tests/typed_path/fail/missing_field.rs
type MyPath (line 6) | struct MyPath {}
function main (line 8) | fn main() {}
FILE: axum-macros/tests/typed_path/fail/not_deserialize.rs
type MyPath (line 5) | struct MyPath {
function main (line 9) | fn main() {}
FILE: axum-macros/tests/typed_path/fail/route_not_starting_with_slash.rs
type MyPath (line 5) | struct MyPath;
function main (line 7) | fn main() {}
FILE: axum-macros/tests/typed_path/fail/route_not_starting_with_slash_non_empty.rs
type MyPath (line 5) | struct MyPath;
function main (line 7) | fn main() {}
FILE: axum-macros/tests/typed_path/fail/unit_with_capture.rs
type MyPath (line 6) | struct MyPath;
function main (line 8) | fn main() {}
FILE: axum-macros/tests/typed_path/pass/customize_rejection.rs
type MyPathNamed (line 10) | struct MyPathNamed {
type MyPathUnit (line 16) | struct MyPathUnit;
type MyPathUnnamed (line 20) | struct MyPathUnnamed(String);
type MyRejection (line 22) | struct MyRejection;
method from (line 31) | fn from(_: PathRejection) -> Self {
method into_response (line 25) | fn into_response(self) -> Response {
method default (line 37) | fn default() -> Self {
function main (line 42) | fn main() {
FILE: axum-macros/tests/typed_path/pass/into_uri.rs
type Named (line 7) | struct Named {
type Unnamed (line 13) | struct Unnamed(u32);
type Unit (line 17) | struct Unit;
function main (line 19) | fn main() {
FILE: axum-macros/tests/typed_path/pass/named_fields_struct.rs
type MyPath (line 6) | struct MyPath {
function main (line 11) | fn main() {
FILE: axum-macros/tests/typed_path/pass/result_handler.rs
type UsersShow (line 7) | struct UsersShow {
function result_handler (line 11) | async fn result_handler(_: Result<UsersShow, PathRejection>) {}
type UsersIndex (line 15) | struct UsersIndex;
function result_handler_unit_struct (line 17) | async fn result_handler_unit_struct(_: Result<UsersIndex, StatusCode>) {}
function main (line 19) | fn main() {
FILE: axum-macros/tests/typed_path/pass/tuple_struct.rs
type Result (line 4) | pub type Result<T> = std::result::Result<T, ()>;
type MyPath (line 8) | struct MyPath(u32, u32);
function main (line 10) | fn main() {
FILE: axum-macros/tests/typed_path/pass/unit_struct.rs
type MyPath (line 5) | struct MyPath;
function main (line 7) | fn main() {
FILE: axum-macros/tests/typed_path/pass/url_encoding.rs
type Named (line 6) | struct Named {
type Unnamed (line 12) | struct Unnamed(String);
function main (line 14) | fn main() {
FILE: axum-macros/tests/typed_path/pass/wildcards.rs
type MyPath (line 6) | struct MyPath {
function main (line 10) | fn main() {
FILE: axum/benches/benches.rs
function main (line 15) | fn main() {
type AppState (line 93) | struct AppState {
type Payload (line 99) | struct Payload {
function benchmark (line 105) | fn benchmark(name: &'static str) -> BenchmarkBuilder {
type BenchmarkBuilder (line 115) | struct BenchmarkBuilder {
method run (line 138) | fn run<F>(self, f: F)
function install_rewrk (line 221) | fn install_rewrk() {
function ensure_rewrk_is_installed (line 238) | fn ensure_rewrk_is_installed() {
function on_ci (line 248) | fn on_ci() -> bool {
FILE: axum/src/body/mod.rs
function to_bytes (line 48) | pub async fn to_bytes(body: Body, limit: usize) -> Result<Bytes, axum_co...
FILE: axum/src/boxed.rs
type BoxedIntoRoute (line 12) | pub(crate) struct BoxedIntoRoute<S, E>(Box<dyn ErasedIntoRoute<S, E>>);
function from_handler (line 18) | pub(crate) fn from_handler<H, T>(handler: H) -> Self
function map (line 31) | pub(crate) fn map<F, E2>(self, f: F) -> BoxedIntoRoute<S, E2>
function into_route (line 44) | pub(crate) fn into_route(self, state: S) -> Route<E> {
method clone (line 50) | fn clone(&self) -> Self {
function fmt (line 56) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
type ErasedIntoRoute (line 61) | pub(crate) trait ErasedIntoRoute<S, E>: Send + Sync {
method clone_box (line 62) | fn clone_box(&self) -> Box<dyn ErasedIntoRoute<S, E>>;
method into_route (line 64) | fn into_route(self: Box<Self>, state: S) -> Route<E>;
method call_with_state (line 67) | fn call_with_state(self: Box<Self>, request: Request, state: S) -> Rou...
type MakeErasedHandler (line 70) | pub(crate) struct MakeErasedHandler<H, S> {
function clone_box (line 80) | fn clone_box(&self) -> Box<dyn ErasedIntoRoute<S, Infallible>> {
function into_route (line 84) | fn into_route(self: Box<Self>, state: S) -> Route {
function call_with_state (line 88) | fn call_with_state(self: Box<Self>, request: Request, state: S) -> Route...
method clone (line 97) | fn clone(&self) -> Self {
type MakeErasedRouter (line 106) | pub(crate) struct MakeErasedRouter<S> {
function clone_box (line 115) | fn clone_box(&self) -> Box<dyn ErasedIntoRoute<S, Infallible>> {
function into_route (line 119) | fn into_route(self: Box<Self>, state: S) -> Route {
function call_with_state (line 123) | fn call_with_state(self: Box<Self>, request: Request, state: S) -> Route...
method clone (line 132) | fn clone(&self) -> Self {
type Map (line 140) | pub(crate) struct Map<S, E, E2> {
function clone_box (line 151) | fn clone_box(&self) -> Box<dyn ErasedIntoRoute<S, E2>> {
function into_route (line 158) | fn into_route(self: Box<Self>, state: S) -> Route<E2> {
function call_with_state (line 162) | fn call_with_state(self: Box<Self>, request: Request, state: S) -> Route...
type LayerFn (line 167) | pub(crate) trait LayerFn<E, E2>: FnOnce(Route<E>) -> Route<E2> + Send + ...
method clone_box (line 168) | fn clone_box(&self) -> Box<dyn LayerFn<E, E2>>;
method clone_box (line 175) | fn clone_box(&self) -> Box<dyn LayerFn<E, E2>> {
FILE: axum/src/error_handling/mod.rs
type HandleErrorLayer (line 23) | pub struct HandleErrorLayer<F, T> {
function new (line 30) | pub fn new(f: F) -> Self {
method clone (line 42) | fn clone(&self) -> Self {
function fmt (line 51) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
type Service (line 62) | type Service = HandleError<S, F, T>;
function layer (line 64) | fn layer(&self, inner: S) -> Self::Service {
type HandleError (line 72) | pub struct HandleError<S, F, T> {
function new (line 80) | pub fn new(inner: S, f: F) -> Self {
method clone (line 94) | fn clone(&self) -> Self {
function fmt (line 107) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
type Response (line 126) | type Response = Response;
type Error (line 127) | type Error = Infallible;
type Future (line 128) | type Future = future::HandleErrorFuture;
type Output (line 248) | type Output = Result<Response, Infallible>;
method poll (line 250) | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Outp...
function poll_ready (line 130) | fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<(), Self::E...
function call (line 134) | fn call(&mut self, req: Request<B>) -> Self::Future {
function traits (line 257) | fn traits() {
FILE: axum/src/extension.rs
type Extension (line 72) | pub struct Extension<T>(pub T);
function from_extensions (line 78) | fn from_extensions(extensions: &Extensions) -> Option<Self> {
type Rejection (line 88) | type Rejection = ExtensionRejection;
function from_request_parts (line 90) | async fn from_request_parts(req: &mut Parts, _state: &S) -> Result<Self,...
type Rejection (line 105) | type Rejection = Infallible;
function from_request_parts (line 107) | async fn from_request_parts(
type Error (line 121) | type Error = Infallible;
method into_response_parts (line 123) | fn into_response_parts(self, mut res: ResponseParts) -> Result<ResponseP...
method into_response (line 133) | fn into_response(self) -> Response {
type Service (line 144) | type Service = AddExtension<S, T>;
function layer (line 146) | fn layer(&self, inner: S) -> Self::Service {
type AddExtension (line 164) | pub struct AddExtension<S, T> {
type Response (line 174) | type Response = S::Response;
type Error (line 175) | type Error = S::Error;
type Future (line 176) | type Future = S::Future;
function poll_ready (line 179) | fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::...
function call (line 183) | fn call(&mut self, mut req: Request<ResBody>) -> Self::Future {
type Foo (line 198) | struct Foo(String);
type Bar (line 201) | struct Bar(String);
function extension_extractor (line 204) | async fn extension_extractor() {
FILE: axum/src/extract/connect_info.rs
type IntoMakeServiceWithConnectInfo (line 28) | pub struct IntoMakeServiceWithConnectInfo<S, C> {
function new (line 34) | pub(crate) fn new(svc: S) -> Self {
function fmt (line 46) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
method clone (line 57) | fn clone(&self) -> Self {
type Connected (line 74) | pub trait Connected<T>: Clone + Send + Sync + 'static {
method connect_info (line 76) | fn connect_info(stream: T) -> Self;
constant _ (line 80) | const _: () = {
method connect_info (line 94) | fn connect_info(remote_addr: Self) -> Self {
type Response (line 104) | type Response = AddExtension<S, ConnectInfo<C>>;
type Error (line 105) | type Error = Infallible;
type Future (line 106) | type Future = ResponseFuture<S, C>;
function poll_ready (line 109) | fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self:...
function call (line 113) | fn call(&mut self, target: T) -> Self::Future {
type ConnectInfo (line 136) | pub struct ConnectInfo<T>(pub T);
type Rejection (line 143) | type Rejection = <Extension<Self> as FromRequestParts<S>>::Rejection;
function from_request_parts (line 145) | async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self...
type MockConnectInfo (line 206) | pub struct MockConnectInfo<T>(pub T);
type Service (line 212) | type Service = <Extension<Self> as Layer<S>>::Service;
function layer (line 214) | fn layer(&self, inner: S) -> Self::Service {
function into_make_service_traits (line 229) | fn into_make_service_traits() {
function connected_traits (line 236) | fn connected_traits() {
function socket_addr (line 308) | async fn socket_addr() {
function custom (line 336) | async fn custom() {
function mock_connect_info (line 377) | async fn mock_connect_info() {
function both_mock_and_real_connect_info (line 394) | async fn both_mock_and_real_connect_info() {
FILE: axum/src/extract/matched_path.rs
type MatchedPath (line 57) | pub struct MatchedPath(pub(crate) Arc<str>);
method as_str (line 62) | pub fn as_str(&self) -> &str {
type Rejection (line 71) | type Rejection = MatchedPathRejection;
method from_request_parts (line 73) | async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result<S...
type Rejection (line 88) | type Rejection = Infallible;
method from_request_parts (line 90) | async fn from_request_parts(
type MatchedNestedPath (line 99) | struct MatchedNestedPath(Arc<str>);
function set_matched_path_for_request (line 101) | pub(crate) fn set_matched_path_for_request(
function append_nested_matched_path (line 125) | fn append_nested_matched_path(matched_path: &Arc<str>, extensions: &http...
function extracting_on_handler (line 156) | async fn extracting_on_handler() {
function extracting_on_handler_in_nested_router (line 169) | async fn extracting_on_handler_in_nested_router() {
function extracting_on_handler_in_deeply_nested_router (line 185) | async fn extracting_on_handler_in_deeply_nested_router() {
function cannot_extract_nested_matched_path_in_middleware (line 204) | async fn cannot_extract_nested_matched_path_in_middleware() {
function can_extract_nested_matched_path_in_middleware_using_nest (line 224) | async fn can_extract_nested_matched_path_in_middleware_using_nest() {
function cannot_extract_nested_matched_path_in_middleware_via_extension (line 244) | async fn cannot_extract_nested_matched_path_in_middleware_via_extension() {
function can_extract_nested_matched_path_in_middleware_via_extension_using_nest (line 261) | async fn can_extract_nested_matched_path_in_middleware_via_extension_usi...
function can_extract_nested_matched_path_in_middleware_on_nested_router (line 278) | async fn can_extract_nested_matched_path_in_middleware_on_nested_router() {
function can_extract_nested_matched_path_in_middleware_on_nested_router_via_extension (line 298) | async fn can_extract_nested_matched_path_in_middleware_on_nested_router_...
function extracting_on_nested_handler (line 319) | async fn extracting_on_nested_handler() {
function doesnt_panic_if_router_called_from_wildcard_route (line 334) | async fn doesnt_panic_if_router_called_from_wildcard_route() {
function cant_extract_in_fallback (line 353) | async fn cant_extract_in_fallback() {
function matching_colon (line 368) | async fn matching_colon() {
function matching_asterisk (line 388) | async fn matching_asterisk() {
FILE: axum/src/extract/mod.rs
function has_content_type (line 83) | pub(super) fn has_content_type(headers: &HeaderMap, expected_content_typ...
function consume_body (line 100) | async fn consume_body() {
FILE: axum/src/extract/multipart.rs
type Multipart (line 64) | pub struct Multipart {
type Rejection (line 72) | type Rejection = MultipartRejection;
method from_request (line 74) | async fn from_request(req: Request, _state: &S) -> Result<Self, Self::...
type Rejection (line 88) | type Rejection = MultipartRejection;
method from_request (line 90) | async fn from_request(req: Request, _state: &S) -> Result<Option<Self>...
method next_field (line 108) | pub async fn next_field(&mut self) -> Result<Option<Field<'_>>, Multip...
type Field (line 128) | pub struct Field<'a> {
type Item (line 136) | type Item = Result<Bytes, MultipartError>;
method poll_next (line 138) | fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Opt...
function name (line 150) | pub fn name(&self) -> Option<&str> {
function file_name (line 158) | pub fn file_name(&self) -> Option<&str> {
function content_type (line 164) | pub fn content_type(&self) -> Option<&str> {
function headers (line 170) | pub fn headers(&self) -> &HeaderMap {
function bytes (line 175) | pub async fn bytes(self) -> Result<Bytes, MultipartError> {
function text (line 183) | pub async fn text(self) -> Result<String, MultipartError> {
function chunk (line 225) | pub async fn chunk(&mut self) -> Result<Option<Bytes>, MultipartError> {
type MultipartError (line 235) | pub struct MultipartError {
method from_multer (line 240) | fn from_multer(multer: multer::Error) -> Self {
method body_text (line 246) | pub fn body_text(&self) -> String {
method status (line 256) | pub fn status(&self) -> http::StatusCode {
method fmt (line 313) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
method source (line 319) | fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
function status_code_from_multer_error (line 261) | fn status_code_from_multer_error(err: &multer::Error) -> StatusCode {
function is_body_limit_error (line 296) | fn is_body_limit_error(err: &multer::Error) -> bool {
method into_response (line 325) | fn into_response(self) -> Response {
function content_type_str (line 336) | fn content_type_str(headers: &HeaderMap) -> Option<&str> {
function content_type_with_encoding (line 365) | async fn content_type_with_encoding() {
function _multipart_from_request_limited (line 401) | fn _multipart_from_request_limited() {
function body_too_large (line 409) | async fn body_too_large() {
function optional_multipart (line 434) | async fn optional_multipart() {
FILE: axum/src/extract/nested_path.rs
type NestedPath (line 40) | pub struct NestedPath(Arc<str>);
method as_str (line 45) | pub fn as_str(&self) -> &str {
type Rejection (line 55) | type Rejection = NestedPathRejection;
method from_request_parts (line 57) | async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result<S...
type SetNestedPath (line 66) | pub(crate) struct SetNestedPath<S> {
function layer (line 72) | pub(crate) fn layer(path: &str) -> impl Layer<S, Service = Self> + Clone {
type Response (line 85) | type Response = S::Response;
type Error (line 86) | type Error = S::Error;
type Future (line 87) | type Future = S::Future;
function poll_ready (line 90) | fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::...
function call (line 94) | fn call(&mut self, mut req: Request<B>) -> Self::Future {
function one_level_of_nesting (line 125) | async fn one_level_of_nesting() {
function one_level_of_nesting_with_trailing_slash (line 143) | async fn one_level_of_nesting_with_trailing_slash() {
function two_levels_of_nesting (line 161) | async fn two_levels_of_nesting() {
function two_levels_of_nesting_with_trailing_slash (line 179) | async fn two_levels_of_nesting_with_trailing_slash() {
function in_fallbacks (line 197) | async fn in_fallbacks() {
function in_middleware (line 212) | async fn in_middleware() {
FILE: axum/src/extract/original_uri.rs
type OriginalUri (line 68) | pub struct OriginalUri(pub Uri);
type Rejection (line 74) | type Rejection = Infallible;
method from_request_parts (line 76) | async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Se...
FILE: axum/src/extract/path/de.rs
type PathDeserializer (line 45) | pub(crate) struct PathDeserializer<'de> {
function new (line 51) | pub(crate) fn new(url_params: &'de [(Arc<str>, PercentDecodedStr)]) -> S...
type Error (line 57) | type Error = PathDeserializationError;
function deserialize_any (line 81) | fn deserialize_any<V>(self, v: V) -> Result<V::Value, Self::Error>
function deserialize_str (line 88) | fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error>
function deserialize_unit (line 114) | fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error>
function deserialize_unit_struct (line 121) | fn deserialize_unit_struct<V>(
function deserialize_newtype_struct (line 132) | fn deserialize_newtype_struct<V>(
function deserialize_seq (line 143) | fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
function deserialize_tuple (line 153) | fn deserialize_tuple<V>(self, len: usize, visitor: V) -> Result<V::Value...
function deserialize_tuple_struct (line 168) | fn deserialize_tuple_struct<V>(
function deserialize_map (line 188) | fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error>
function deserialize_struct (line 199) | fn deserialize_struct<V>(
function deserialize_enum (line 211) | fn deserialize_enum<V>(
type MapDeserializer (line 232) | struct MapDeserializer<'de> {
type Error (line 239) | type Error = PathDeserializationError;
function next_key_seed (line 241) | fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self...
function next_value_seed (line 256) | fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error>
type KeyDeserializer (line 270) | struct KeyDeserializer<'de> {
type Error (line 286) | type Error = PathDeserializationError;
function deserialize_any (line 292) | fn deserialize_any<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
type ValueDeserializer (line 340) | struct ValueDeserializer<'de> {
type Error (line 346) | type Error = PathDeserializationError;
function deserialize_any (line 368) | fn deserialize_any<V>(self, v: V) -> Result<V::Value, Self::Error>
function deserialize_str (line 375) | fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error>
function deserialize_bytes (line 394) | fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value, Self::Error>
function deserialize_option (line 401) | fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
function deserialize_unit (line 408) | fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error>
function deserialize_unit_struct (line 415) | fn deserialize_unit_struct<V>(
function deserialize_newtype_struct (line 426) | fn deserialize_newtype_struct<V>(
function deserialize_tuple (line 437) | fn deserialize_tuple<V>(self, len: usize, visitor: V) -> Result<V::Value...
function deserialize_seq (line 489) | fn deserialize_seq<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
function deserialize_tuple_struct (line 498) | fn deserialize_tuple_struct<V>(
function deserialize_struct (line 512) | fn deserialize_struct<V>(
function deserialize_enum (line 526) | fn deserialize_enum<V>(
function deserialize_ignored_any (line 538) | fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value, Self...
type EnumDeserializer (line 546) | struct EnumDeserializer<'de> {
type Error (line 551) | type Error = PathDeserializationError;
type Variant (line 552) | type Variant = UnitVariant;
function variant_seed (line 554) | fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant), S...
type UnitVariant (line 565) | struct UnitVariant;
type Error (line 568) | type Error = PathDeserializationError;
method unit_variant (line 570) | fn unit_variant(self) -> Result<(), Self::Error> {
method newtype_variant_seed (line 574) | fn newtype_variant_seed<T>(self, _seed: T) -> Result<T::Value, Self::E...
method tuple_variant (line 583) | fn tuple_variant<V>(self, _len: usize, _visitor: V) -> Result<V::Value...
method struct_variant (line 592) | fn struct_variant<V>(
type SeqDeserializer (line 606) | struct SeqDeserializer<'de> {
type Error (line 612) | type Error = PathDeserializationError;
function next_element_seed (line 614) | fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, ...
type KeyOrIdx (line 634) | enum KeyOrIdx<'de> {
function key (line 640) | fn key(&self) -> &'de str {
type MyEnum (line 654) | enum MyEnum {
type Struct (line 662) | struct Struct {
function create_url_params (line 668) | fn create_url_params<I, K, V>(values: I) -> Vec<(Arc<str>, PercentDecode...
function test_parse_single_value (line 692) | fn test_parse_single_value() {
function test_parse_seq (line 733) | fn test_parse_seq() {
function test_parse_seq_tuple_string_string (line 761) | fn test_parse_seq_tuple_string_string() {
function test_parse_seq_tuple_string_parse (line 773) | fn test_parse_seq_tuple_string_parse() {
function test_parse_struct (line 782) | fn test_parse_struct() {
function test_parse_struct_ignoring_additional_fields (line 795) | fn test_parse_struct_ignoring_additional_fields() {
function test_parse_map (line 813) | fn test_parse_map() {
function test_parse_tuple_too_many_fields (line 839) | fn test_parse_tuple_too_many_fields() {
function test_wrong_number_of_parameters_error (line 851) | fn test_wrong_number_of_parameters_error() {
function test_parse_error_at_key_error (line 863) | fn test_parse_error_at_key_error() {
function test_parse_error_at_key_error_multiple (line 881) | fn test_parse_error_at_key_error_multiple() {
function test_parse_error_at_index_error (line 900) | fn test_parse_error_at_index_error() {
function test_parse_error_error (line 913) | fn test_parse_error_error() {
function test_unsupported_type_error_nested_data_structure (line 925) | fn test_unsupported_type_error_nested_data_structure() {
function test_parse_seq_tuple_unsupported_key_type (line 936) | fn test_parse_seq_tuple_unsupported_key_type() {
function test_parse_seq_wrong_tuple_length (line 945) | fn test_parse_seq_wrong_tuple_length() {
function test_parse_seq_seq (line 956) | fn test_parse_seq_seq() {
function test_deserialize_key_value (line 967) | fn test_deserialize_key_value() {
FILE: axum/src/extract/path/mod.rs
type Path (line 153) | pub struct Path<T>(pub T);
type Rejection (line 162) | type Rejection = PathRejection;
function from_request_parts (line 164) | async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result<Sel...
type Rejection (line 197) | type Rejection = PathRejection;
function from_request_parts (line 199) | async fn from_request_parts(
type PathDeserializationError (line 218) | pub(crate) struct PathDeserializationError {
method new (line 223) | pub(super) fn new(kind: ErrorKind) -> Self {
method wrong_number_of_parameters (line 227) | pub(super) fn wrong_number_of_parameters() -> WrongNumberOfParameters<...
method unsupported_type (line 232) | pub(super) fn unsupported_type(name: &'static str) -> Self {
method custom (line 259) | fn custom<T>(msg: T) -> Self
method fmt (line 270) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
type WrongNumberOfParameters (line 237) | pub(super) struct WrongNumberOfParameters<G> {
function got (line 243) | pub(super) fn got<G2>(self, got: G2) -> WrongNumberOfParameters<G2> {
function expected (line 249) | pub(super) fn expected(self, expected: usize) -> PathDeserializationError {
type ErrorKind (line 285) | pub enum ErrorKind {
method fmt (line 358) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
type FailedToDeserializePathParams (line 407) | pub struct FailedToDeserializePathParams(PathDeserializationError);
method kind (line 411) | pub fn kind(&self) -> &ErrorKind {
method into_kind (line 416) | pub fn into_kind(self) -> ErrorKind {
method body_text (line 422) | pub fn body_text(&self) -> String {
method status (line 438) | pub fn status(&self) -> StatusCode {
method fmt (line 466) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
method into_response (line 454) | fn into_response(self) -> Response {
type RawPathParams (line 501) | pub struct RawPathParams(Vec<(Arc<str>, PercentDecodedStr)>);
type Rejection (line 507) | type Rejection = RawPathParamsRejection;
method from_request_parts (line 509) | async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result<S...
method iter (line 530) | pub fn iter(&self) -> RawPathParamsIter<'_> {
type Item (line 536) | type Item = (&'a str, &'a str);
type IntoIter (line 537) | type IntoIter = RawPathParamsIter<'a>;
method into_iter (line 539) | fn into_iter(self) -> Self::IntoIter {
type RawPathParamsIter (line 548) | pub struct RawPathParamsIter<'a>(std::slice::Iter<'a, (Arc<str>, Percent...
type Item (line 551) | type Item = (&'a str, &'a str);
method next (line 553) | fn next(&mut self) -> Option<Self::Item> {
type InvalidUtf8InPathParam (line 562) | pub struct InvalidUtf8InPathParam {
method body_text (line 569) | pub fn body_text(&self) -> String {
method status (line 575) | pub fn status(&self) -> StatusCode {
method fmt (line 581) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
method into_response (line 589) | fn into_response(self) -> Response {
function extracting_url_params (line 608) | async fn extracting_url_params() {
function extracting_url_params_multiple_times (line 629) | async fn extracting_url_params_multiple_times() {
function percent_decoding (line 639) | async fn percent_decoding() {
function supports_128_bit_numbers (line 653) | async fn supports_128_bit_numbers() {
function wildcard (line 674) | async fn wildcard() {
function captures_dont_match_empty_path (line 697) | async fn captures_dont_match_empty_path() {
function captures_match_empty_inner_segments (line 710) | async fn captures_match_empty_inner_segments() {
function captures_match_empty_inner_segments_near_end (line 726) | async fn captures_match_empty_inner_segments_near_end() {
function captures_match_empty_trailing_segment (line 745) | async fn captures_match_empty_trailing_segment() {
function str_reference_deserialize (line 767) | async fn str_reference_deserialize() {
function two_path_extractors (line 795) | async fn two_path_extractors() {
function tuple_param_matches_exactly (line 810) | async fn tuple_param_matches_exactly() {
function deserialize_into_vec_of_tuples (line 840) | async fn deserialize_into_vec_of_tuples() {
function type_that_uses_deserialize_any (line 861) | async fn type_that_uses_deserialize_any() {
function wrong_number_of_parameters_json (line 939) | async fn wrong_number_of_parameters_json() {
function raw_path_params (line 962) | async fn raw_path_params() {
function deserialize_error_single_value (line 981) | async fn deserialize_error_single_value() {
function deserialize_error_multi_value (line 999) | async fn deserialize_error_multi_value() {
function regression_3038 (line 1020) | async fn regression_3038() {
FILE: axum/src/extract/query.rs
type Query (line 41) | pub struct Query<T>(pub T);
type Rejection (line 48) | type Rejection = QueryRejection;
function from_request_parts (line 50) | async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result<Sel...
function try_from_uri (line 78) | pub fn try_from_uri(value: &Uri) -> Result<Self, QueryRejection> {
function check (line 100) | async fn check<T>(uri: impl AsRef<str>, value: T)
function test_query (line 112) | async fn test_query() {
function correct_rejection_status_code (line 148) | async fn correct_rejection_status_code() {
function test_try_from_uri (line 169) | fn test_try_from_uri() {
function test_try_from_uri_with_invalid_query (line 182) | fn test_try_from_uri_with_invalid_query() {
FILE: axum/src/extract/raw_form.rs
type RawForm (line 30) | pub struct RawForm(pub Bytes);
type Rejection (line 36) | type Rejection = RawFormRejection;
method from_request (line 38) | async fn from_request(req: Request, state: &S) -> Result<Self, Self::R...
function check_query (line 64) | async fn check_query(uri: &str, value: &[u8]) {
function check_body (line 70) | async fn check_body(body: &'static [u8]) {
function test_from_query (line 80) | async fn test_from_query() {
function test_from_body (line 87) | async fn test_from_body() {
function test_incorrect_content_type (line 94) | async fn test_incorrect_content_type() {
FILE: axum/src/extract/raw_query.rs
type RawQuery (line 25) | pub struct RawQuery(pub Option<String>);
type Rejection (line 31) | type Rejection = Infallible;
method from_request_parts (line 33) | async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result<S...
FILE: axum/src/extract/state.rs
type State (line 296) | pub struct State<S>(pub S);
type Rejection (line 303) | type Rejection = Infallible;
function from_request_parts (line 305) | async fn from_request_parts(
type Target (line 315) | type Target = S;
method deref (line 317) | fn deref(&self) -> &Self::Target {
method deref_mut (line 323) | fn deref_mut(&mut self) -> &mut Self::Target {
FILE: axum/src/extract/ws.rs
type WebSocketUpgrade (line 134) | pub struct WebSocketUpgrade<F = DefaultOnFailedUpgrade> {
function fmt (line 146) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
function read_buffer_size (line 158) | pub fn read_buffer_size(mut self, size: usize) -> Self {
function write_buffer_size (line 172) | pub fn write_buffer_size(mut self, size: usize) -> Self {
function max_write_buffer_size (line 188) | pub fn max_write_buffer_size(mut self, max: usize) -> Self {
function max_message_size (line 194) | pub fn max_message_size(mut self, max: usize) -> Self {
function max_frame_size (line 200) | pub fn max_frame_size(mut self, max: usize) -> Self {
function accept_unmasked_frames (line 206) | pub fn accept_unmasked_frames(mut self, accept: bool) -> Self {
function protocols (line 241) | pub fn protocols<I>(mut self, protocols: I) -> Self
function requested_protocols (line 278) | pub fn requested_protocols(&self) -> impl Iterator<Item = &HeaderValue> {
function set_selected_protocol (line 292) | pub fn set_selected_protocol(&mut self, protocol: HeaderValue) {
function selected_protocol (line 301) | pub fn selected_protocol(&self) -> Option<&HeaderValue> {
function on_failed_upgrade (line 329) | pub fn on_failed_upgrade<C>(self, callback: C) -> WebSocketUpgrade<C>
function on_upgrade (line 346) | pub fn on_upgrade<C, Fut>(self, callback: C) -> Response
type OnFailedUpgrade (line 416) | pub trait OnFailedUpgrade: Send + 'static {
method call (line 418) | fn call(self, error: Error);
method call (line 425) | fn call(self, error: Error) {
method call (line 439) | fn call(self, _error: Error) {}
type DefaultOnFailedUpgrade (line 435) | pub struct DefaultOnFailedUpgrade;
type Rejection (line 446) | type Rejection = WebSocketUpgradeRejection;
function from_request_parts (line 448) | async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result<Sel...
function header_eq (line 519) | fn header_eq(headers: &HeaderMap, key: &HeaderName, value: &'static str)...
function header_contains (line 527) | fn header_contains(headers: &HeaderMap, key: &HeaderName, value: &'stati...
type WebSocket (line 543) | pub struct WebSocket {
method recv (line 552) | pub async fn recv(&mut self) -> Option<Result<Message, Error>> {
method send (line 557) | pub async fn send(&mut self, msg: Message) -> Result<(), Error> {
method protocol (line 565) | pub fn protocol(&self) -> Option<&HeaderValue> {
type Error (line 596) | type Error = Error;
method poll_ready (line 598) | fn poll_ready(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<...
method start_send (line 602) | fn start_send(mut self: Pin<&mut Self>, item: Message) -> Result<(), S...
method poll_flush (line 608) | fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<...
method poll_close (line 612) | fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<...
method is_terminated (line 572) | fn is_terminated(&self) -> bool {
type Item (line 578) | type Item = Result<Message, Error>;
method poll_next (line 580) | fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Opt...
type Utf8Bytes (line 621) | pub struct Utf8Bytes(ts::Utf8Bytes);
method from_static (line 627) | pub const fn from_static(str: &'static str) -> Self {
method as_str (line 633) | pub fn as_str(&self) -> &str {
method into_tungstenite (line 637) | fn into_tungstenite(self) -> ts::Utf8Bytes {
type Target (line 643) | type Target = str;
method deref (line 658) | fn deref(&self) -> &Self::Target {
method fmt (line 665) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
type Error (line 671) | type Error = std::str::Utf8Error;
method try_from (line 674) | fn try_from(bytes: Bytes) -> Result<Self, Self::Error> {
type Error (line 680) | type Error = std::str::Utf8Error;
method try_from (line 683) | fn try_from(v: Vec<u8>) -> Result<Self, Self::Error> {
method from (line 690) | fn from(s: String) -> Self {
method from (line 697) | fn from(s: &str) -> Self {
method from (line 704) | fn from(s: &String) -> Self {
method eq (line 728) | fn eq(&self, other: &T) -> bool {
method from (line 711) | fn from(Utf8Bytes(bytes): Utf8Bytes) -> Self {
type CloseCode (line 734) | pub type CloseCode = u16;
type CloseFrame (line 738) | pub struct CloseFrame {
type Message (line 769) | pub enum Message {
method into_tungstenite (line 812) | fn into_tungstenite(self) -> ts::Message {
method from_tungstenite (line 826) | fn from_tungstenite(message: ts::Message) -> Option<Self> {
method into_data (line 844) | pub fn into_data(self) -> Bytes {
method into_text (line 854) | pub fn into_text(self) -> Result<Utf8Bytes, Error> {
method to_text (line 867) | pub fn to_text(&self) -> Result<&str, Error> {
method text (line 879) | pub fn text<S>(string: S) -> Self
method binary (line 887) | pub fn binary<B>(bin: B) -> Self
method from (line 896) | fn from(string: String) -> Self {
method from (line 902) | fn from(string: &'s str) -> Self {
method from (line 908) | fn from(data: &'b [u8]) -> Self {
method from (line 914) | fn from(data: Bytes) -> Self {
method from (line 920) | fn from(data: Vec<u8>) -> Self {
function from (line 926) | fn from(msg: Message) -> Self {
function sign (line 931) | fn sign(key: &[u8]) -> HeaderValue {
constant NORMAL (line 1035) | pub const NORMAL: u16 = 1000;
constant AWAY (line 1039) | pub const AWAY: u16 = 1001;
constant PROTOCOL (line 1042) | pub const PROTOCOL: u16 = 1002;
constant UNSUPPORTED (line 1048) | pub const UNSUPPORTED: u16 = 1003;
constant STATUS (line 1051) | pub const STATUS: u16 = 1005;
constant ABNORMAL (line 1054) | pub const ABNORMAL: u16 = 1006;
constant INVALID (line 1060) | pub const INVALID: u16 = 1007;
constant POLICY (line 1068) | pub const POLICY: u16 = 1008;
constant SIZE (line 1072) | pub const SIZE: u16 = 1009;
constant EXTENSION (line 1082) | pub const EXTENSION: u16 = 1010;
constant ERROR (line 1086) | pub const ERROR: u16 = 1011;
constant RESTART (line 1089) | pub const RESTART: u16 = 1012;
constant AGAIN (line 1094) | pub const AGAIN: u16 = 1013;
function rejects_http_1_0_requests (line 1112) | async fn rejects_http_1_0_requests() {
function default_on_failed_upgrade (line 1138) | fn default_on_failed_upgrade() {
function on_failed_upgrade (line 1146) | fn on_failed_upgrade() {
function integration_test (line 1155) | async fn integration_test() {
function http2 (line 1166) | async fn http2() {
function echo_app (line 1207) | fn echo_app() -> Router {
constant TEST_ECHO_APP_REQ_SUBPROTO (line 1234) | const TEST_ECHO_APP_REQ_SUBPROTO: &str = "echo3, echo";
function test_echo_app (line 1235) | async fn test_echo_app<S: AsyncRead + AsyncWrite + Unpin>(
FILE: axum/src/form.rs
type Form (line 71) | pub struct Form<T>(pub T);
type Rejection (line 78) | type Rejection = FormRejection;
function from_request (line 80) | async fn from_request(req: Request, _state: &S) -> Result<Self, Self::Re...
method into_response (line 111) | fn into_response(self) -> Response {
type Pagination (line 150) | struct Pagination {
function check_query (line 155) | async fn check_query<T: DeserializeOwned + PartialEq + Debug>(uri: impl ...
function check_body (line 163) | async fn check_body<T: Serialize + DeserializeOwned + PartialEq + Debug>...
function test_form_query (line 174) | async fn test_form_query() {
function test_form_body (line 204) | async fn test_form_body() {
function test_incorrect_content_type (line 225) | async fn test_incorrect_content_type() {
function deserialize_error_status_codes (line 247) | async fn deserialize_error_status_codes() {
FILE: axum/src/handler/future.rs
function new (line 35) | pub(super) fn new(
type Output (line 46) | type Output = Response;
method poll (line 49) | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> std::task::Poll<S...
FILE: axum/src/handler/mod.rs
type Handler (line 148) | pub trait Handler<T, S>: Clone + Send + Sync + Sized + 'static {
method call (line 153) | fn call(self, req: Request, state: S) -> Self::Future;
method layer (line 189) | fn layer<L>(self, layer: L) -> Layered<L, Self, T, S>
method with_state (line 202) | fn with_state(self, state: S) -> HandlerService<Self, T, S> {
type Future (line 214) | type Future = Pin<Box<dyn Future<Output = Response> + Send>>;
method call (line 216) | fn call(self, _req: Request, _state: S) -> Self::Future {
type IntoResponseHandler (line 267) | pub enum IntoResponseHandler {}
type Future (line 275) | type Future = std::future::Ready<Response>;
method call (line 277) | fn call(self, _req: Request, _state: S) -> Self::Future {
type Layered (line 285) | pub struct Layered<L, H, T, S> {
function fmt (line 295) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
method clone (line 307) | fn clone(&self) -> Self {
type Future (line 327) | type Future = future::LayeredFuture<L::Service>;
function call (line 329) | fn call(self, req: Request, state: S) -> Self::Future {
type HandlerWithoutStateExt (line 357) | pub trait HandlerWithoutStateExt<T>: Handler<T, ()> {
method into_service (line 359) | fn into_service(self) -> HandlerService<Self, T, ()>;
method into_make_service (line 366) | fn into_make_service(self) -> IntoMakeService<HandlerService<Self, T, ...
method into_make_service_with_connect_info (line 375) | fn into_make_service_with_connect_info<C>(
method into_service (line 384) | fn into_service(self) -> HandlerService<Self, T, ()> {
method into_make_service (line 388) | fn into_make_service(self) -> IntoMakeService<HandlerService<Self, T, ()...
method into_make_service_with_connect_info (line 393) | fn into_make_service_with_connect_info<C>(
function handler_into_service (line 413) | async fn handler_into_service() {
function with_layer_that_changes_request_body_and_state (line 426) | async fn with_layer_that_changes_request_body_and_state() {
FILE: axum/src/handler/service.rs
type HandlerService (line 22) | pub struct HandlerService<H, T, S> {
function state (line 30) | pub fn state(&self) -> &S {
function into_make_service (line 63) | pub fn into_make_service(self) -> IntoMakeService<Self> {
function into_make_service_with_connect_info (line 104) | pub fn into_make_service_with_connect_info<C>(self) -> IntoMakeServiceWi...
function traits (line 110) | fn traits() {
function new (line 117) | pub(super) fn new(handler: H, state: S) -> Self {
function fmt (line 127) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
method clone (line 137) | fn clone(&self) -> Self {
type Response (line 153) | type Response = Response;
type Error (line 154) | type Error = Infallible;
type Future (line 155) | type Future = super::future::IntoServiceFuture<H::Future>;
function poll_ready (line 158) | fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self:...
function call (line 165) | fn call(&mut self, req: Request<B>) -> Self::Future {
constant _ (line 180) | const _: () = {
FILE: axum/src/json.rs
type Json (line 97) | pub struct Json<T>(pub T);
type Rejection (line 104) | type Rejection = JsonRejection;
function from_request (line 106) | async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rej...
type Rejection (line 121) | type Rejection = JsonRejection;
function from_request (line 123) | async fn from_request(req: Request, state: &S) -> Result<Option<Self>, S...
function json_content_type (line 138) | fn json_content_type(headers: &HeaderMap) -> bool {
function from (line 152) | fn from(inner: T) -> Self {
function from_bytes (line 164) | pub fn from_bytes(bytes: &[u8]) -> Result<Self, JsonRejection> {
method into_response (line 201) | fn into_response(self) -> Response {
function deserialize_body (line 242) | async fn deserialize_body() {
function consume_body_to_json_requires_json_content_type (line 258) | async fn consume_body_to_json_requires_json_content_type() {
function json_content_types (line 275) | async fn json_content_types() {
function invalid_json_syntax (line 298) | async fn invalid_json_syntax() {
function extra_chars_after_valid_json_syntax (line 312) | async fn extra_chars_after_valid_json_syntax() {
type Foo (line 336) | struct Foo {
type Bar (line 344) | struct Bar {
function invalid_json_data (line 352) | async fn invalid_json_data() {
FILE: axum/src/middleware/from_extractor.rs
function from_extractor (line 89) | pub fn from_extractor<E>() -> FromExtractorLayer<E, ()> {
function from_extractor_with_state (line 96) | pub fn from_extractor_with_state<E, S>(state: S) -> FromExtractorLayer<E...
type FromExtractorLayer (line 110) | pub struct FromExtractorLayer<E, S> {
method clone (line 119) | fn clone(&self) -> Self {
function fmt (line 131) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
type Service (line 143) | type Service = FromExtractor<T, E, S>;
function layer (line 145) | fn layer(&self, inner: T) -> Self::Service {
type FromExtractor (line 157) | pub struct FromExtractor<T, E, S> {
function traits (line 164) | fn traits() {
method clone (line 175) | fn clone(&self) -> Self {
function fmt (line 189) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
type Response (line 206) | type Response = Response;
type Error (line 207) | type Error = T::Error;
type Future (line 208) | type Future = ResponseFuture<B, T, E, S>;
type Output (line 268) | type Output = Result<Response, T::Error>;
method poll (line 270) | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::...
function poll_ready (line 211) | fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::...
function call (line 215) | fn call(&mut self, req: Request<B>) -> Self::Future {
function test_from_extractor (line 311) | async fn test_from_extractor() {
function works_with_request_body_limit (line 365) | fn works_with_request_body_limit() {
FILE: axum/src/middleware/from_fn.rs
function from_fn (line 114) | pub fn from_fn<F, T>(f: F) -> FromFnLayer<F, (), T> {
function from_fn_with_state (line 164) | pub fn from_fn_with_state<F, S, T>(state: S, f: F) -> FromFnLayer<F, S, ...
type FromFnLayer (line 178) | pub struct FromFnLayer<F, S, T> {
method clone (line 189) | fn clone(&self) -> Self {
type Service (line 203) | type Service = FromFn<F, S, I, T>;
function layer (line 205) | fn layer(&self, inner: I) -> Self::Service {
function fmt (line 219) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
type FromFn (line 231) | pub struct FromFn<F, S, I, T> {
method clone (line 244) | fn clone(&self) -> Self {
function fmt (line 327) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
type Next (line 338) | pub struct Next {
method run (line 344) | pub async fn run(mut self, req: Request) -> Response {
type Response (line 353) | type Response = Response;
type Error (line 354) | type Error = Infallible;
type Future (line 355) | type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self:...
method poll_ready (line 357) | fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self...
method call (line 361) | fn call(&mut self, req: Request) -> Self::Future {
type ResponseFuture (line 367) | pub struct ResponseFuture {
method fmt (line 380) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
type Output (line 372) | type Output = Result<Response, Infallible>;
method poll (line 374) | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Ou...
function basic (line 394) | async fn basic() {
FILE: axum/src/middleware/map_request.rs
function map_request (line 117) | pub fn map_request<F, T>(f: F) -> MapRequestLayer<F, (), T> {
function map_request_with_state (line 159) | pub fn map_request_with_state<F, S, T>(state: S, f: F) -> MapRequestLaye...
type MapRequestLayer (line 171) | pub struct MapRequestLayer<F, S, T> {
method clone (line 182) | fn clone(&self) -> Self {
type Service (line 196) | type Service = MapRequest<F, S, I, T>;
function layer (line 198) | fn layer(&self, inner: I) -> Self::Service {
function fmt (line 212) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
type MapRequest (line 224) | pub struct MapRequest<F, S, I, T> {
method clone (line 237) | fn clone(&self) -> Self {
function fmt (line 327) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
type ResponseFuture (line 337) | pub struct ResponseFuture {
method fmt (line 350) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
type Output (line 342) | type Output = Result<Response, Infallible>;
method poll (line 344) | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Ou...
type Sealed (line 358) | pub trait Sealed<B> {}
type IntoMapRequestResult (line 367) | pub trait IntoMapRequestResult<B>: private::Sealed<B> {
method into_map_request_result (line 370) | fn into_map_request_result(self) -> Result<Request<B>, Response>;
function into_map_request_result (line 377) | fn into_map_request_result(self) -> Result<Request<B>, Response> {
function into_map_request_result (line 383) | fn into_map_request_result(self) -> Result<Self, Response> {
function works (line 395) | async fn works() {
function works_for_short_circutting (line 420) | async fn works_for_short_circutting() {
FILE: axum/src/middleware/map_response.rs
function map_response (line 99) | pub fn map_response<F, T>(f: F) -> MapResponseLayer<F, (), T> {
function map_response_with_state (line 141) | pub fn map_response_with_state<F, S, T>(state: S, f: F) -> MapResponseLa...
type MapResponseLayer (line 153) | pub struct MapResponseLayer<F, S, T> {
method clone (line 164) | fn clone(&self) -> Self {
type Service (line 178) | type Service = MapResponse<F, S, I, T>;
function layer (line 180) | fn layer(&self, inner: I) -> Self::Service {
function fmt (line 194) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
type MapResponse (line 206) | pub struct MapResponse<F, S, I, T> {
method clone (line 219) | fn clone(&self) -> Self {
function fmt (line 315) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
type ResponseFuture (line 325) | pub struct ResponseFuture {
method fmt (line 338) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
type Output (line 330) | type Output = Result<Response, Infallible>;
method poll (line 332) | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Ou...
function works (line 350) | async fn works() {
FILE: axum/src/middleware/response_axum_body.rs
type ResponseAxumBodyLayer (line 18) | pub struct ResponseAxumBodyLayer;
type Service (line 21) | type Service = ResponseAxumBody<S>;
method layer (line 23) | fn layer(&self, inner: S) -> Self::Service {
type ResponseAxumBody (line 30) | pub struct ResponseAxumBody<S>(S);
type Response (line 38) | type Response = Response;
type Error (line 40) | type Error = S::Error;
type Future (line 42) | type Future = ResponseAxumBodyFuture<S::Future>;
type Output (line 69) | type Output = Result<Response<Body>, E>;
method poll (line 71) | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Outp...
function poll_ready (line 44) | fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::...
function call (line 48) | fn call(&mut self, req: Request) -> Self::Future {
FILE: axum/src/response/mod.rs
type Html (line 37) | pub struct Html<T>(pub T);
method into_response (line 43) | fn into_response(self) -> Response {
function from (line 56) | fn from(inner: T) -> Self {
type NoContent (line 78) | pub struct NoContent;
method into_response (line 81) | fn into_response(self) -> Response {
function impl_trait_result_works (line 102) | fn impl_trait_result_works() {
function tuple_responses (line 136) | fn tuple_responses() {
function status_code_tuple_doesnt_override_error (line 258) | fn status_code_tuple_doesnt_override_error() {
function into_response_parts_failing_sets_extension (line 392) | fn into_response_parts_failing_sets_extension() {
function doenst_override_status_code_when_using_into_response_failed_at_same_level (line 438) | fn doenst_override_status_code_when_using_into_response_failed_at_same_l...
function force_overriding_status_code (line 474) | fn force_overriding_status_code() {
function status_code_tuple_doesnt_override_error_json (line 509) | async fn status_code_tuple_doesnt_override_error_json() {
function no_content (line 539) | fn no_content() {
FILE: axum/src/response/redirect.rs
type Redirect (line 22) | pub struct Redirect {
method to (line 37) | pub fn to(uri: impl Into<String>) -> Self {
method temporary (line 47) | pub fn temporary(uri: impl Into<String>) -> Self {
method permanent (line 54) | pub fn permanent(uri: impl Into<String>) -> Self {
method status_code (line 60) | pub fn status_code(&self) -> StatusCode {
method location (line 66) | pub fn location(&self) -> &str {
method with_status_code (line 74) | fn with_status_code(status_code: StatusCode, uri: String) -> Self {
method into_response (line 88) | fn into_response(self) -> Response {
constant EXAMPLE_URL (line 102) | const EXAMPLE_URL: &str = "https://example.com";
function correct_status (line 107) | fn correct_status() {
function correct_location (line 125) | fn correct_location() {
function test_internal_error (line 132) | fn test_internal_error() {
FILE: axum/src/response/sse.rs
type Sse (line 54) | pub struct Sse<S> {
function new (line 63) | pub fn new(stream: S) -> Self
function keep_alive (line 75) | pub fn keep_alive(self, keep_alive: KeepAlive) -> Sse<KeepAliveStream<S>> {
function fmt (line 83) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
method into_response (line 95) | fn into_response(self) -> Response {
type Data (line 120) | type Data = Bytes;
type Error (line 121) | type Error = E;
method poll_frame (line 123) | fn poll_frame(
type Buffer (line 147) | enum Buffer {
method as_mut (line 157) | fn as_mut(&mut self) -> &mut BytesMut {
type Event (line 174) | pub struct Event {
constant DEFAULT_KEEP_ALIVE (line 202) | pub const DEFAULT_KEEP_ALIVE: Self = Self::finalized(Bytes::from_stati...
method finalized (line 204) | const fn finalized(bytes: Bytes) -> Self {
method into_data_writer (line 217) | pub fn into_data_writer(self) -> EventDataWriter {
method data (line 237) | pub fn data<T>(self, data: T) -> Self
method json_data (line 256) | pub fn json_data<T>(self, data: T) -> Result<Self, axum_core::Error>
method comment (line 289) | pub fn comment<T>(mut self, comment: T) -> Self
method event (line 311) | pub fn event<T>(mut self, event: T) -> Self
method retry (line 334) | pub fn retry(mut self, duration: Duration) -> Self {
method id (line 378) | pub fn id<T>(mut self, id: T) -> Self
method field (line 398) | fn field(&mut self, name: &str, value: impl AsRef<[u8]>) {
method finalize (line 414) | fn finalize(self) -> Bytes {
type EventDataWriter (line 191) | pub struct EventDataWriter {
method into_event (line 430) | pub fn into_event(self) -> Event {
method write_buf (line 442) | fn write_buf(&mut self, buf: &[u8]) -> usize {
method write_str (line 473) | fn write_str(&mut self, s: &str) -> fmt::Result {
method default (line 480) | fn default() -> Self {
type EventFlags (line 489) | struct EventFlags(u8);
constant HAS_DATA (line 492) | const HAS_DATA: Self = Self::from_bits(0b0001);
constant HAS_EVENT (line 493) | const HAS_EVENT: Self = Self::from_bits(0b0010);
constant HAS_RETRY (line 494) | const HAS_RETRY: Self = Self::from_bits(0b0100);
constant HAS_ID (line 495) | const HAS_ID: Self = Self::from_bits(0b1000);
method bits (line 497) | const fn bits(self) -> u8 {
method from_bits (line 501) | const fn from_bits(bits: u8) -> Self {
method contains (line 505) | const fn contains(self, other: Self) -> bool {
method insert (line 509) | fn insert(&mut self, other: Self) {
type KeepAlive (line 518) | pub struct KeepAlive {
method new (line 525) | pub fn new() -> Self {
method interval (line 535) | pub fn interval(mut self, time: Duration) -> Self {
method text (line 548) | pub fn text<I>(self, text: I) -> Self
method event (line 563) | pub fn event(mut self, event: Event) -> Self {
method default (line 570) | fn default() -> Self {
function new (line 590) | fn new(keep_alive: KeepAlive, inner: S) -> Self {
function reset (line 598) | fn reset(self: Pin<&mut Self>) {
type Item (line 610) | type Item = Result<Event, E>;
method poll_next (line 612) | fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Opt...
function leading_space_is_not_stripped (line 648) | fn leading_space_is_not_stripped() {
function write_data_writer_str (line 657) | fn write_data_writer_str() {
function valid_json_raw_value_chars_handled (line 683) | fn valid_json_raw_value_chars_handled() {
function basic (line 695) | async fn basic() {
function keep_alive (line 738) | async fn keep_alive() {
function keep_alive_ends_when_the_stream_ends (line 774) | async fn keep_alive_ends_when_the_stream_ends() {
function parse_event (line 815) | fn parse_event(payload: &str) -> HashMap<String, String> {
FILE: axum/src/routing/into_make_service.rs
type IntoMakeService (line 12) | pub struct IntoMakeService<S> {
function new (line 17) | pub(crate) fn new(svc: S) -> Self {
type Response (line 26) | type Response = S;
type Error (line 27) | type Error = Infallible;
type Future (line 28) | type Future = IntoMakeServiceFuture<S>;
function poll_ready (line 31) | fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self:...
function call (line 35) | fn call(&mut self, _target: T) -> Self::Future {
function traits (line 51) | fn traits() {
FILE: axum/src/routing/method_filter.rs
type MethodFilter (line 9) | pub struct MethodFilter(u16);
constant CONNECT (line 29) | pub const CONNECT: Self = Self::from_bits(0b0_0000_0001);
constant DELETE (line 31) | pub const DELETE: Self = Self::from_bits(0b0_0000_0010);
constant GET (line 33) | pub const GET: Self = Self::from_bits(0b0_0000_0100);
constant HEAD (line 35) | pub const HEAD: Self = Self::from_bits(0b0_0000_1000);
constant OPTIONS (line 37) | pub const OPTIONS: Self = Self::from_bits(0b0_0001_0000);
constant PATCH (line 39) | pub const PATCH: Self = Self::from_bits(0b0_0010_0000);
constant POST (line 41) | pub const POST: Self = Self::from_bits(0b0_0100_0000);
constant PUT (line 43) | pub const PUT: Self = Self::from_bits(0b0_1000_0000);
constant TRACE (line 45) | pub const TRACE: Self = Self::from_bits(0b1_0000_0000);
method bits (line 47) | const fn bits(self) -> u16 {
method from_bits (line 52) | const fn from_bits(bits: u16) -> Self {
method contains (line 56) | pub(crate) const fn contains(self, other: Self) -> bool {
method or (line 62) | pub const fn or(self, other: Self) -> Self {
type Error (line 89) | type Error = NoMatchingMethodFilter;
method try_from (line 91) | fn try_from(m: Method) -> Result<Self, NoMatchingMethodFilter> {
type NoMatchingMethodFilter (line 69) | pub struct NoMatchingMethodFilter {
method method (line 75) | pub fn method(&self) -> &Method {
method fmt (line 81) | fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
function from_http_method (line 112) | fn from_http_method() {
FILE: axum/src/routing/method_routing.rs
function on_service (line 368) | pub fn on_service<T, S>(filter: MethodFilter, svc: T) -> MethodRouter<S,...
function any_service (line 427) | pub fn any_service<T, S>(svc: T) -> MethodRouter<S, T::Error>
function on (line 466) | pub fn on<H, T, S>(filter: MethodFilter, handler: H) -> MethodRouter<S, ...
function any (line 508) | pub fn any<H, T, S>(handler: H) -> MethodRouter<S, Infallible>
type MethodRouter (line 547) | pub struct MethodRouter<S = (), E = Infallible> {
type AllowHeader (line 562) | enum AllowHeader {
method merge (line 572) | fn merge(self, other: Self) -> Self {
function fmt (line 587) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
function on (line 630) | pub fn on<H, T>(self, filter: MethodFilter, handler: H) -> Self
function fallback (line 653) | pub fn fallback<H, T>(mut self, handler: H) -> Self
function method_filter (line 673) | pub fn method_filter(&self) -> Option<MethodFilter> {
function default_fallback (line 712) | pub(crate) fn default_fallback<H, T>(self, handler: H) -> Self
function into_make_service (line 754) | pub fn into_make_service(self) -> IntoMakeService<Self> {
function into_make_service_with_connect_info (line 788) | pub fn into_make_service_with_connect_info<C>(self) -> IntoMakeServiceWi...
function new (line 799) | pub fn new() -> Self {
function with_state (line 820) | pub fn with_state<S2>(self, state: S) -> MethodRouter<S2, E> {
function on_service (line 860) | pub fn on_service<T>(self, filter: MethodFilter, svc: T) -> Self
function on_endpoint (line 870) | fn on_endpoint(mut self, filter: MethodFilter, endpoint: &MethodEndpoint...
function fallback_service (line 1003) | pub fn fallback_service<T>(mut self, svc: T) -> Self
function layer (line 1014) | pub fn layer<L, NewError>(self, layer: L) -> MethodRouter<S, NewError>
function route_layer (line 1044) | pub fn route_layer<L>(mut self, layer: L) -> Self
function merge_for_path (line 1084) | pub(crate) fn merge_for_path(
function merge (line 1138) | pub fn merge(self, other: Self) -> Self {
function handle_error (line 1149) | pub fn handle_error<F, T>(self, f: F) -> MethodRouter<S, Infallible>
function skip_allow_header (line 1162) | fn skip_allow_header(mut self) -> Self {
function call_with_state (line 1167) | pub(crate) fn call_with_state(&self, req: Request, state: S) -> RouteFut...
function append_allow_header (line 1225) | fn append_allow_header(allow_header: &mut AllowHeader, method: &'static ...
method clone (line 1246) | fn clone(&self) -> Self {
method default (line 1267) | fn default() -> Self {
type MethodEndpoint (line 1272) | enum MethodEndpoint<S, E> {
function is_some (line 1282) | fn is_some(&self) -> bool {
function is_none (line 1286) | fn is_none(&self) -> bool {
function map (line 1290) | fn map<F, E2>(self, f: F) -> MethodEndpoint<S, E2>
function with_state (line 1304) | fn with_state<S2>(self, state: &S) -> MethodEndpoint<S2, E> {
method clone (line 1314) | fn clone(&self) -> Self {
function fmt (line 1324) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
type Response (line 1338) | type Response = Response;
type Error (line 1339) | type Error = E;
type Future (line 1340) | type Future = RouteFuture<E>;
function poll_ready (line 1343) | fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self:...
function call (line 1348) | fn call(&mut self, req: Request<B>) -> Self::Future {
type Future (line 1359) | type Future = InfallibleRouteFuture;
function call (line 1361) | fn call(self, req: Request, state: S) -> Self::Future {
constant _ (line 1368) | const _: () = {
function method_not_allowed_by_default (line 1402) | async fn method_not_allowed_by_default() {
function get_service_fn (line 1410) | async fn get_service_fn() {
function get_handler (line 1423) | async fn get_handler() {
function get_accepts_head (line 1431) | async fn get_accepts_head() {
function head_takes_precedence_over_get (line 1439) | async fn head_takes_precedence_over_get() {
function merge (line 1447) | async fn merge() {
function layer (line 1462) | async fn layer() {
function route_layer (line 1478) | async fn route_layer() {
function building_complex_router (line 1493) | async fn building_complex_router() {
function sets_allow_header (line 1514) | async fn sets_allow_header() {
function sets_allow_header_get_head (line 1522) | async fn sets_allow_header_get_head() {
function empty_allow_header_by_default (line 1530) | async fn empty_allow_header_by_default() {
function allow_header_when_merging (line 1538) | async fn allow_header_when_merging() {
function allow_header_any (line 1549) | async fn allow_header_any() {
function allow_header_with_fallback (line 1558) | async fn allow_header_with_fallback() {
function allow_header_with_fallback_that_sets_allow (line 1569) | async fn allow_header_with_fallback_that_sets_allow() {
function allow_header_noop_middleware (line 1597) | async fn allow_header_noop_middleware() {
function handler_overlaps (line 1611) | async fn handler_overlaps() {
function service_overlaps (line 1619) | async fn service_overlaps() {
function get_head_does_not_overlap (line 1624) | async fn get_head_does_not_overlap() {
function head_get_does_not_overlap (line 1629) | async fn head_get_does_not_overlap() {
function accessing_state (line 1634) | async fn accessing_state() {
function fallback_accessing_state (line 1646) | async fn fallback_accessing_state() {
function merge_accessing_state (line 1658) | async fn merge_accessing_state() {
function method_filter (line 1674) | fn method_filter() {
function call (line 1692) | async fn call<S>(method: Method, svc: &mut S) -> (StatusCode, HeaderMap,...
function ok (line 1716) | async fn ok() -> (StatusCode, &'static str) {
function created (line 1720) | async fn created() -> (StatusCode, &'static str) {
FILE: axum/src/routing/mod.rs
constant TAKE_ONCE_ROUTE_PANIC_MSG (line 60) | const TAKE_ONCE_ROUTE_PANIC_MSG: &str =
function take_route_or_internal_error (line 63) | fn take_route_or_internal_error(service: &mut Option<Route>) -> Route {
type RouteId (line 76) | pub(crate) struct RouteId(usize);
type Router (line 86) | pub struct Router<S = ()> {
method into_make_service (line 558) | pub fn into_make_service(self) -> IntoMakeService<Self> {
method into_make_service_with_connect_info (line 567) | pub fn into_make_service_with_connect_info<C>(self) -> IntoMakeService...
method clone (line 91) | fn clone(&self) -> Self {
type RouterInner (line 98) | struct RouterInner<S> {
method default (line 108) | fn default() -> Self {
function fmt (line 114) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
constant NEST_TAIL_PARAM (line 123) | pub(crate) const NEST_TAIL_PARAM: &str = "__private__axum_nest_tail_param";
constant NEST_TAIL_PARAM_CAPTURE (line 125) | pub(crate) const NEST_TAIL_PARAM_CAPTURE: &str = "/{*__private__axum_nes...
constant FALLBACK_PARAM (line 126) | pub(crate) const FALLBACK_PARAM: &str = "__private__axum_fallback";
constant FALLBACK_PARAM_PATH (line 127) | pub(crate) const FALLBACK_PARAM_PATH: &str = "/{*__private__axum_fallbac...
function new (line 162) | pub fn new() -> Self {
function into_inner (line 172) | fn into_inner(self) -> RouterInner<S> {
function without_v07_checks (line 184) | pub fn without_v07_checks(self) -> Self {
function route (line 192) | pub fn route(self, path: &str, method_router: MethodRouter<S>) -> Self {
function route_service (line 199) | pub fn route_service<T>(self, path: &str, service: T) -> Self
function nest (line 220) | pub fn nest(self, path: &str, router: Self) -> Self {
function nest_service (line 241) | pub fn nest_service<T>(self, path: &str, service: T) -> Self
function merge (line 258) | pub fn merge<R>(self, other: R) -> Self
function layer (line 296) | pub fn layer<L>(self, layer: L) -> Self
function route_layer (line 313) | pub fn route_layer<L>(self, layer: L) -> Self
function has_routes (line 330) | pub fn has_routes(&self) -> bool {
function fallback (line 336) | pub fn fallback<H, T>(self, handler: H) -> Self
function fallback_service (line 351) | pub fn fallback_service<T>(self, service: T) -> Self
function method_not_allowed_fallback (line 366) | pub fn method_not_allowed_fallback<H, T>(self, handler: H) -> Self
function reset_fallback (line 384) | pub fn reset_fallback(self) -> Self {
function fallback_endpoint (line 391) | fn fallback_endpoint(self, endpoint: Endpoint<S>) -> Self {
function with_state (line 444) | pub fn with_state<S2>(self, state: S) -> Router<S2> {
function call_with_state (line 452) | pub(crate) fn call_with_state(&self, req: Request, state: S) -> RouteFut...
function as_service (line 517) | pub fn as_service<B>(&mut self) -> RouterAsService<'_, B, S> {
function into_service (line 530) | pub fn into_service<B>(self) -> RouterIntoService<B, S> {
constant _ (line 576) | const _: () = {
type Response (line 604) | type Response = Response;
type Error (line 605) | type Error = Infallible;
type Future (line 606) | type Future = RouteFuture<Infallible>;
function poll_ready (line 609) | fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<(), Self::E...
function call (line 614) | fn call(&mut self, req: Request<B>) -> Self::Future {
type RouterAsService (line 623) | pub struct RouterAsService<'a, B, S = ()> {
type Response (line 633) | type Response = Response;
type Error (line 634) | type Error = Infallible;
type Future (line 635) | type Future = RouteFuture<Infallible>;
function poll_ready (line 638) | fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::...
function call (line 643) | fn call(&mut self, req: Request<B>) -> Self::Future {
function fmt (line 652) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
type RouterIntoService (line 662) | pub struct RouterIntoService<B, S = ()> {
method clone (line 671) | fn clone(&self) -> Self {
type Response (line 684) | type Response = Response;
type Error (line 685) | type Error = Infallible;
type Future (line 686) | type Future = RouteFuture<Infallible>;
function poll_ready (line 689) | fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::...
function call (line 694) | fn call(&mut self, req: Request<B>) -> Self::Future {
function fmt (line 703) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
type Fallback (line 710) | enum Fallback<S, E = Infallible> {
function merge (line 720) | fn merge(self, other: Self) -> Option<Self> {
function map (line 729) | fn map<F, E2>(self, f: F) -> Fallback<S, E2>
function with_state (line 743) | fn with_state<S2>(self, state: S) -> Fallback<S2, E> {
function call_with_state (line 751) | fn call_with_state(self, req: Request, state: S) -> RouteFuture<E> {
function is_default (line 761) | fn is_default(&self) -> bool {
method clone (line 767) | fn clone(&self) -> Self {
function fmt (line 777) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
type Endpoint (line 787) | enum Endpoint<S> {
function layer (line 796) | fn layer<L>(self, layer: L) -> Self
method clone (line 812) | fn clone(&self) -> Self {
function fmt (line 821) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
function traits (line 832) | fn traits() {
FILE: axum/src/routing/not_found.rs
type NotFound (line 16) | pub(super) struct NotFound;
type Response (line 22) | type Response = Response;
type Error (line 23) | type Error = Infallible;
type Future (line 24) | type Future = std::future::Ready<Result<Response, Self::Error>>;
method poll_ready (line 27) | fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Sel...
method call (line 31) | fn call(&mut self, _req: Request<B>) -> Self::Future {
FILE: axum/src/routing/path_router.rs
type PathRouter (line 16) | pub(super) struct PathRouter<S> {
function validate_path (line 22) | fn validate_path(v7_checks: bool, path: &str) -> Result<(), &'static str> {
function validate_v07_paths (line 36) | fn validate_v07_paths(path: &str) -> Result<(), &'static str> {
function without_v07_checks (line 62) | pub(super) fn without_v07_checks(&mut self) {
function route (line 66) | pub(super) fn route(
function method_not_allowed_fallback (line 95) | pub(super) fn method_not_allowed_fallback<H, T>(&mut self, handler: &H)
function route_service (line 107) | pub(super) fn route_service<T>(
function route_endpoint (line 120) | pub(super) fn route_endpoint(
function set_node (line 132) | fn set_node(&mut self, path: &str, id: RouteId) -> Result<(), String> {
function new_route (line 139) | fn new_route(&mut self, path: &str, endpoint: Endpoint<S>) -> Result<(),...
function merge (line 146) | pub(super) fn merge(&mut self, other: Self) -> Result<(), Cow<'static, s...
function nest (line 172) | pub(super) fn nest(
function nest_service (line 212) | pub(super) fn nest_service<T>(
function layer (line 251) | pub(super) fn layer<L>(self, layer: L) -> Self
function route_layer (line 273) | pub(super) fn route_layer<L>(self, layer: L) -> Self
function has_routes (line 301) | pub(super) fn has_routes(&self) -> bool {
function with_state (line 305) | pub(super) fn with_state<S2>(self, state: S) -> PathRouter<S2> {
function call_with_state (line 325) | pub(super) fn call_with_state(
method default (line 376) | fn default() -> Self {
function fmt (line 386) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
method clone (line 395) | fn clone(&self) -> Self {
type Node (line 406) | struct Node {
method insert (line 413) | fn insert(
method at (line 429) | fn at<'n, 'p>(
method fmt (line 438) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
function validate_nest_path (line 445) | fn validate_nest_path(v7_checks: bool, path: &str) -> Result<&str, &'sta...
function path_for_nested_route (line 466) | pub(crate) fn path_for_nested_route<'a>(prefix: &'a str, path: &'a str) ...
FILE: axum/src/routing/route.rs
type Route (line 31) | pub struct Route<E = Infallible>(BoxCloneSyncService<Request, Response, ...
function new (line 34) | pub(crate) fn new<T>(svc: T) -> Self
function call_owned (line 44) | pub(crate) fn call_owned(self, req: Request<Body>) -> RouteFuture<E> {
function oneshot_inner (line 49) | pub(crate) fn oneshot_inner(&self, req: Request) -> RouteFuture<E> {
function oneshot_inner_owned (line 55) | pub(crate) fn oneshot_inner_owned(self, req: Request) -> RouteFuture<E> {
function layer (line 60) | pub(crate) fn layer<L, NewError>(self, layer: L) -> Route<NewError>
method clone (line 77) | fn clone(&self) -> Self {
function fmt (line 83) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
type Response (line 93) | type Response = Response;
type Error (line 94) | type Error = E;
type Future (line 95) | type Future = RouteFuture<E>;
type Output (line 144) | type Output = Result<Response, E>;
method poll (line 147) | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Outp...
type Output (line 229) | type Output = Response;
method poll (line 231) | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Outp...
function poll_ready (line 98) | fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self:...
function call (line 103) | fn call(&mut self, req: Request<B>) -> Self::Future {
function new (line 120) | fn new(
function allow_header (line 132) | pub(crate) fn allow_header(mut self, allow_header: Bytes) -> Self {
function not_top_level (line 137) | pub(crate) fn not_top_level(mut self) -> Self {
function set_allow_header (line 182) | fn set_allow_header(headers: &mut HeaderMap, allow_header: &mut Option<B...
function set_content_length (line 194) | fn set_content_length(size_hint: &http_body::SizeHint, headers: &mut Hea...
method new (line 223) | pub(crate) fn new(future: RouteFuture<Infallible>) -> Self {
function traits (line 244) | fn traits() {
FILE: axum/src/routing/strip_prefix.rs
type StripPrefix (line 11) | pub(super) struct StripPrefix<S> {
function layer (line 17) | pub(super) fn layer(prefix: &str) -> impl Layer<S, Service = Self> + Clo...
type Response (line 30) | type Response = S::Response;
type Error (line 31) | type Error = S::Error;
type Future (line 32) | type Future = S::Future;
function poll_ready (line 35) | fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::...
function call (line 39) | fn call(&mut self, mut req: Request<B>) -> Self::Future {
function strip_prefix (line 47) | fn strip_prefix(uri: &Uri, prefix: &str) -> Option<Uri> {
function segments (line 124) | fn segments(s: &str) -> impl Iterator<Item = &str> {
function zip_longest (line 136) | fn zip_longest<I, I2>(a: I, b: I2) -> impl Iterator<Item = Item<I::Item>>
function is_capture (line 151) | fn is_capture(segment: &str) -> bool {
type Item (line 160) | enum Item<T> {
function does_not_panic (line 384) | fn does_not_panic(uri_and_prefix: UriAndPrefix) -> bool {
type UriAndPrefix (line 391) | struct UriAndPrefix {
method arbitrary (line 397) | fn arbitrary(g: &mut quickcheck::Gen) -> Self {
function ascii_alphanumeric (line 442) | fn ascii_alphanumeric(g: &mut quickcheck::Gen) -> String {
function u8_between (line 467) | fn u8_between(lower: u8, upper: u8, g: &mut quickcheck::Gen) -> u8 {
FILE: axum/src/routing/tests/fallback.rs
function basic (line 5) | async fn basic() {
function nest (line 20) | async fn nest() {
function two (line 35) | async fn two() {
function or (line 47) | async fn or() {
function fallback_accessing_state (line 64) | async fn fallback_accessing_state() {
function inner_fallback (line 76) | async fn inner_fallback() -> impl IntoResponse {
function outer_fallback (line 80) | async fn outer_fallback() -> impl IntoResponse {
function nested_router_inherits_fallback (line 85) | async fn nested_router_inherits_fallback() {
function doesnt_inherit_fallback_if_overridden (line 97) | async fn doesnt_inherit_fallback_if_overridden() {
function deeply_nested_inherit_from_top (line 113) | async fn deeply_nested_inherit_from_top() {
function deeply_nested_inherit_from_middle (line 126) | async fn deeply_nested_inherit_from_middle() {
function with_middleware_on_inner_fallback (line 142) | async fn with_middleware_on_inner_fallback() {
function also_inherits_default_layered_fallback (line 158) | async fn also_inherits_default_layered_fallback() {
function nest_fallback_on_inner (line 180) | async fn nest_fallback_on_inner() {
function doesnt_panic_if_used_with_nested_router (line 199) | async fn doesnt_panic_if_used_with_nested_router() {
function issue_2072 (line 214) | async fn issue_2072() {
function issue_2072_outer_fallback_before_merge (line 233) | async fn issue_2072_outer_fallback_before_merge() {
function issue_2072_outer_fallback_after_merge (line 253) | async fn issue_2072_outer_fallback_after_merge() {
function merge_router_with_fallback_into_nested_router_with_fallback (line 273) | async fn merge_router_with_fallback_into_nested_router_with_fallback() {
function merging_nested_router_with_fallback_into_router_with_fallback (line 292) | async fn merging_nested_router_with_fallback_into_router_with_fallback() {
function merge_empty_into_router_with_fallback (line 311) | async fn merge_empty_into_router_with_fallback() {
function merge_router_with_fallback_into_empty (line 322) | async fn merge_router_with_fallback_into_empty() {
function mna_fallback_not_405 (line 333) | async fn mna_fallback_not_405() {
function mna_fallback_with_existing_fallback (line 350) | async fn mna_fallback_with_existing_fallback() {
function mna_fallback_with_state (line 371) | async fn mna_fallback_with_state() {
function mna_fallback_with_unused_state (line 383) | async fn mna_fallback_with_unused_state() {
function state_isnt_cloned_too_much_with_fallback (line 395) | async fn state_isnt_cloned_too_much_with_fallback() {
FILE: axum/src/routing/tests/get_to_head.rs
function get_handles_head (line 9) | async fn get_handles_head() {
function get_handles_head (line 43) | async fn get_handles_head() {
FILE: axum/src/routing/tests/handle_error.rs
function unit (line 5) | async fn unit() {}
function forever (line 7) | async fn forever() {
function timeout (line 11) | fn timeout() -> TimeoutLayer {
function handler (line 16) | async fn handler() {
function handler_multiple_methods_first (line 32) | async fn handler_multiple_methods_first() {
function handler_multiple_methods_middle (line 49) | async fn handler_multiple_methods_middle() {
function handler_multiple_methods_last (line 67) | async fn handler_multiple_methods_last() {
function handler_service_ext (line 83) | async fn handler_service_ext() {
FILE: axum/src/routing/tests/merge.rs
function basic (line 7) | async fn basic() {
function multiple_ors_balanced_differently (line 30) | async fn multiple_ors_balanced_differently() {
function nested_or (line 75) | async fn nested_or() {
function or_with_route_following (line 91) | async fn or_with_route_following() {
function layer (line 109) | async fn layer() {
function layer_and_handle_error (line 126) | async fn layer_and_handle_error() {
function nesting (line 145) | async fn nesting() {
function boxed (line 157) | async fn boxed() {
function many_ors (line 169) | async fn many_ors() {
function services (line 191) | async fn services() {
function all_the_uris (line 217) | async fn all_the_uris(
function nesting_and_seeing_the_right_uri (line 230) | async fn nesting_and_seeing_the_right_uri() {
function nesting_and_seeing_the_right_uri_at_more_levels_of_nesting (line 260) | async fn nesting_and_seeing_the_right_uri_at_more_levels_of_nesting() {
function nesting_and_seeing_the_right_uri_ors_with_nesting (line 293) | async fn nesting_and_seeing_the_right_uri_ors_with_nesting() {
function nesting_and_seeing_the_right_uri_ors_with_multi_segment_uris (line 338) | async fn nesting_and_seeing_the_right_uri_ors_with_multi_segment_uris() {
function middleware_that_return_early (line 372) | async fn middleware_that_return_early() {
FILE: axum/src/routing/tests/mod.rs
function take_route_or_internal_error_panics_on_second_call (line 50) | fn take_route_or_internal_error_panics_on_second_call() {
function hello_world (line 73) | async fn hello_world() {
function routing (line 106) | async fn routing() {
function router_type_doesnt_change (line 141) | async fn router_type_doesnt_change() {
function routing_between_services (line 162) | async fn routing_between_services() {
function middleware_on_single_route (line 208) | async fn middleware_on_single_route() {
function service_in_bottom (line 226) | async fn service_in_bottom() {
function wrong_method_handler (line 237) | async fn wrong_method_handler() {
function wrong_method_service (line 260) | async fn wrong_method_service() {
function multiple_methods_for_one_handler (line 300) | async fn multiple_methods_for_one_handler() {
function wildcard_sees_whole_url (line 317) | async fn wildcard_sees_whole_url() {
function middleware_applies_to_routes_above (line 330) | async fn middleware_applies_to_routes_above() {
function not_found_for_extra_trailing_slash (line 349) | async fn not_found_for_extra_trailing_slash() {
function not_found_for_missing_trailing_slash (line 362) | async fn not_found_for_missing_trailing_slash() {
function with_and_without_trailing_slash (line 372) | async fn with_and_without_trailing_slash() {
function wildcard_doesnt_match_just_trailing_slash (line 390) | async fn wildcard_doesnt_match_just_trailing_slash() {
function what_matches_wildcard (line 410) | async fn what_matches_wildcard() {
function colliding_fallback_with_wildcard (line 441) | fn colliding_fallback_with_wildcard() {
function colliding_wildcard_with_fallback (line 449) | async fn colliding_wildcard_with_fallback() {
function colliding_fallback_with_fallback (line 467) | async fn colliding_fallback_with_fallback() {
function colliding_root_with_fallback (line 484) | async fn colliding_root_with_fallback() {
function colliding_fallback_with_root (line 501) | async fn colliding_fallback_with_root() {
function static_and_dynamic_paths (line 519) | async fn static_and_dynamic_paths() {
function empty_route (line 538) | async fn empty_route() {
function middleware_still_run_for_unmatched_requests (line 544) | async fn middleware_still_run_for_unmatched_requests() {
function routing_to_router_panics (line 588) | async fn routing_to_router_panics() {
function route_layer (line 594) | async fn route_layer() {
function different_methods_added_in_different_routes (line 621) | async fn different_methods_added_in_different_routes() {
function merging_routers_with_fallbacks_panics (line 639) | async fn merging_routers_with_fallbacks_panics() {
function routes_with_overlapping_method_routes (line 648) | fn routes_with_overlapping_method_routes() {
function merging_with_overlapping_method_routes (line 657) | fn merging_with_overlapping_method_routes() {
function merging_routers_with_same_paths_but_different_methods (line 664) | async fn merging_routers_with_same_paths_but_different_methods() {
function head_content_length_through_hyper_server (line 680) | async fn head_content_length_through_hyper_server() {
function head_content_length_through_hyper_server_that_hits_fallback (line 697) | async fn head_content_length_through_hyper_server_that_hits_fallback() {
function head_with_middleware_applied (line 707) | async fn head_with_middleware_applied() {
function routes_must_start_with_slash (line 736) | async fn routes_must_start_with_slash() {
function body_limited_by_default (line 742) | async fn body_limited_by_default() {
function disabling_the_default_limit (line 770) | async fn disabling_the_default_limit() {
function limited_body_with_content_length (line 786) | async fn limited_body_with_content_length() {
function changing_the_default_limit (line 808) | async fn changing_the_default_limit() {
function changing_the_default_limit_differently_on_different_routes (line 831) | async fn changing_the_default_limit_differently_on_different_routes() {
function limited_body_with_streaming_body (line 893) | async fn limited_body_with_streaming_body() {
function extract_state (line 923) | async fn extract_state() {
function explicitly_set_state (line 959) | async fn explicitly_set_state() {
function layer_response_into_response (line 973) | async fn layer_response_into_response() {
function method_router_fallback_with_state (line 992) | fn method_router_fallback_with_state() {
function test_path_for_nested_route (line 1005) | fn test_path_for_nested_route() {
function state_isnt_cloned_too_much (line 1020) | async fn state_isnt_cloned_too_much() {
function state_isnt_cloned_too_much_in_layer (line 1038) | async fn state_isnt_cloned_too_much_in_layer() {
function logging_rejections (line 1058) | async fn logging_rejections() {
function connect_going_to_custom_fallback (line 1126) | async fn connect_going_to_custom_fallback() {
function connect_going_to_default_fallback (line 1144) | async fn connect_going_to_default_fallback() {
function impl_handler_for_into_response (line 1161) | async fn impl_handler_for_into_response() {
function colon_in_route (line 1175) | async fn colon_in_route() {
function asterisk_in_route (line 1183) | async fn asterisk_in_route() {
function middleware_adding_body (line 1188) | async fn middleware_adding_body() {
FILE: axum/src/routing/tests/nest.rs
function nesting_apps (line 6) | async fn nesting_apps() {
function wrong_method_nest (line 61) | async fn wrong_method_nest() {
function nest_router_at_root (line 80) | fn nest_router_at_root() {
function nest_router_at_empty_path (line 87) | fn nest_router_at_empty_path() {
function nest_service_at_root (line 96) | fn nest_service_at_root() {
function nest_service_at_empty_path (line 104) | fn nest_service_at_empty_path() {
function nest_no_slash (line 110) | fn nest_no_slash() {
function nest_service_no_slash (line 116) | fn nest_service_no_slash() {
function nested_url_extractor (line 121) | async fn nested_url_extractor() {
function nested_url_original_extractor (line 147) | async fn nested_url_original_extractor() {
function nested_service_sees_stripped_uri (line 167) | async fn nested_service_sees_stripped_uri() {
function nest_static_file_server (line 190) | async fn nest_static_file_server() {
function nested_multiple_routes (line 200) | async fn nested_multiple_routes() {
function multiple_top_level_nests (line 218) | async fn multiple_top_level_nests() {
function nest_cannot_contain_wildcards (line 237) | async fn nest_cannot_contain_wildcards() {
function outer_middleware_still_see_whole_url (line 242) | async fn outer_middleware_still_see_whole_url() {
function nest_at_capture (line 290) | async fn nest_at_capture() {
function nest_with_and_without_trailing (line 306) | async fn nest_with_and_without_trailing() {
function nesting_with_root_inner_router (line 322) | async fn nesting_with_root_inner_router() {
function colon_in_route (line 391) | async fn colon_in_route() {
function asterisk_in_route (line 399) | async fn asterisk_in_route() {
function nesting_router_with_fallback (line 404) | async fn nesting_router_with_fallback() {
function defining_missing_routes_in_nested_router (line 420) | async fn defining_missing_routes_in_nested_router() {
function overriding_by_nested_router (line 454) | fn overriding_by_nested_router() {
function overriding_nested_router_ (line 467) | fn overriding_nested_router_() {
function overriding_nested_service_router (line 478) | async fn overriding_nested_service_router() {
FILE: axum/src/routing/url_params.rs
type UrlParams (line 7) | pub(crate) enum UrlParams {
function insert_url_params (line 12) | pub(super) fn insert_url_params(extensions: &mut Extensions, params: &Pa...
FILE: axum/src/serve/listener.rs
type Listener (line 18) | pub trait Listener: Send + 'static {
method accept (line 29) | fn accept(&mut self) -> impl Future<Output = (Self::Io, Self::Addr)> +...
method local_addr (line 32) | fn local_addr(&self) -> io::Result<Self::Addr>;
type Io (line 36) | type Io = TcpStream;
type Addr (line 37) | type Addr = std::net::SocketAddr;
method accept (line 39) | async fn accept(&mut self) -> (Self::Io, Self::Addr) {
method local_addr (line 49) | fn local_addr(&self) -> io::Result<Self::Addr> {
type Io (line 56) | type Io = tokio::net::UnixStream;
type Addr (line 57) | type Addr = tokio::net::unix::SocketAddr;
method accept (line 59) | async fn accept(&mut self) -> (Self::Io, Self::Addr) {
method local_addr (line 69) | fn local_addr(&self) -> io::Result<Self::Addr> {
type Io (line 139) | type Io = ConnLimiterIo<T::Io>;
type Addr (line 140) | type Addr = T::Addr;
method accept (line 142) | async fn accept(&mut self) -> (Self::Io, Self::Addr) {
method local_addr (line 148) | fn local_addr(&self) -> tokio::io::Result<Self::Addr> {
type Io (line 231) | type Io = L::Io;
type Addr (line 232) | type Addr = L::Addr;
method accept (line 234) | async fn accept(&mut self) -> (Self::Io, Self::Addr) {
method local_addr (line 240) | fn local_addr(&self) -> io::Result<Self::Addr> {
type ListenerExt (line 75) | pub trait ListenerExt: Listener + Sized {
method limit_connections (line 87) | fn limit_connections(self, limit: usize) -> ConnLimiter<Self> {
method tap_io (line 116) | fn tap_io<F>(self, tap_fn: F) -> TapIo<Self, F>
type ConnLimiter (line 133) | pub struct ConnLimiter<T> {
method poll_read (line 167) | fn poll_read(
method is_write_vectored (line 178) | fn is_write_vectored(&self) -> bool {
method poll_flush (line 182) | fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Re...
method poll_shutdown (line 186) | fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io:...
method poll_write (line 190) | fn poll_write(
method poll_write_vectored (line 198) | fn poll_write_vectored(
type TapIo (line 210) | pub struct TapIo<L, F> {
function fmt (line 219) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
function handle_accept_error (line 245) | async fn handle_accept_error(e: io::Error) {
function is_connection_error (line 265) | fn is_connection_error(e: &io::Error) -> bool {
function limit_connections (line 283) | async fn limit_connections() {
FILE: axum/src/serve/mod.rs
function serve (line 101) | pub fn serve<L, M, S, B>(listener: L, make_service: M) -> Serve<L, M, S, B>
type Serve (line 121) | pub struct Serve<L, M, S, B> {
function with_graceful_shutdown (line 157) | pub fn with_graceful_shutdown<F>(self, signal: F) -> WithGracefulShutdow...
function local_addr (line 170) | pub fn local_addr(&self) -> io::Result<L::Addr> {
function run (line 188) | async fn run(self) -> ! {
method fmt (line 211) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
type Output (line 239) | type Output = Infallible;
type IntoFuture (line 240) | type IntoFuture = private::ServeFuture;
method into_future (line 242) | fn into_future(self) -> Self::IntoFuture {
type WithGracefulShutdown (line 250) | pub struct WithGracefulShutdown<L, M, S, F, B> {
function local_addr (line 263) | pub fn local_addr(&self) -> io::Result<L::Addr> {
function run (line 282) | async fn run(self) {
method fmt (line 330) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
type Output (line 360) | type Output = ();
type IntoFuture (line 361) | type IntoFuture = private::ServeFuture<()>;
method into_future (line 363) | fn into_future(self) -> Self::IntoFuture {
function handle_connection (line 368) | async fn handle_connection<L, M, S, B>(
type IncomingStream (line 447) | pub struct IncomingStream<'a, L>
function io (line 460) | pub fn io(&self) -> &L::Io {
function remote_addr (line 465) | pub fn remote_addr(&self) -> &L::Addr {
type ServeFuture (line 478) | pub struct ServeFuture<T = Infallible>(pub(super) futures_core::future::...
method fmt (line 490) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
type Output (line 481) | type Output = T;
method poll (line 484) | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Ou...
type ReadyListener (line 528) | struct ReadyListener<T>(Option<T>);
type Io (line 534) | type Io = T;
type Addr (line 535) | type Addr = ();
method accept (line 537) | async fn accept(&mut self) -> (Self::Io, Self::Addr) {
method local_addr (line 544) | fn local_addr(&self) -> io::Result<Self::Addr> {
function if_it_compiles_it_works (line 550) | async fn if_it_compiles_it_works() {
function handler (line 685) | async fn handler() {}
function test_serve_local_addr (line 688) | async fn test_serve_local_addr() {
function test_with_graceful_shutdown_local_addr (line 700) | async fn test_with_graceful_shutdown_local_addr() {
function test_with_graceful_shutdown_request_header_timeout (line 713) | async fn test_with_graceful_shutdown_request_header_timeout() {
function test_hyper_header_read_timeout_is_enabled (line 740) | async fn test_hyper_header_read_timeout_is_enabled() {
function into_future_outside_tokio (line 771) | fn into_future_outside_tokio() {
function serving_on_custom_io_type (line 787) | async fn serving_on_custom_io_type() {
function serving_with_custom_body_type (line 811) | async fn serving_with_custom_body_type() {
FILE: axum/src/service_ext.rs
type ServiceExt (line 8) | pub trait ServiceExt<R>: Service<R> + Sized {
method into_make_service (line 18) | fn into_make_service(self) -> IntoMakeService<Self>;
method into_make_service_with_connect_info (line 33) | fn into_make_service_with_connect_info<C>(self) -> IntoMakeServiceWith...
method handle_error (line 42) | fn handle_error<F, T>(self, f: F) -> HandleError<Self, F, T> {
method into_make_service (line 51) | fn into_make_service(self) -> IntoMakeService<Self> {
method into_make_service_with_connect_info (line 56) | fn into_make_service_with_connect_info<C>(self) -> IntoMakeServiceWithCo...
FILE: axum/src/test_helpers/counting_cloneable_state.rs
type CountingCloneableState (line 6) | pub(crate) struct CountingCloneableState {
method new (line 16) | pub(crate) fn new() -> Self {
method setup_done (line 26) | pub(crate) fn setup_done(&self) {
method count (line 30) | pub(crate) fn count(&self) -> usize {
type InnerState (line 10) | struct InnerState {
method clone (line 36) | fn clone(&self) -> Self {
FILE: axum/src/test_helpers/mod.rs
function assert_send (line 15) | pub(crate) fn assert_send<T: Send>() {}
function assert_sync (line 17) | pub(crate) fn assert_sync<T: Sync>() {}
type NotSendSync (line 20) | pub(crate) struct NotSendSync(*const ());
FILE: axum/src/test_helpers/test_client.rs
function spawn_service (line 11) | pub(crate) fn spawn_service<S>(svc: S) -> SocketAddr
type TestClient (line 30) | pub struct TestClient {
method new (line 36) | pub fn new<S>(svc: S) -> Self
method get (line 51) | pub fn get(&self, url: &str) -> RequestBuilder {
method head (line 57) | pub fn head(&self, url: &str) -> RequestBuilder {
method post (line 63) | pub fn post(&self, url: &str) -> RequestBuilder {
method put (line 70) | pub fn put(&self, url: &str) -> RequestBuilder {
method patch (line 77) | pub fn patch(&self, url: &str) -> RequestBuilder {
method server_port (line 85) | pub fn server_port(&self) -> u16 {
type RequestBuilder (line 91) | pub struct RequestBuilder {
method body (line 96) | pub fn body(mut self, body: impl Into<reqwest::Body>) -> Self {
method json (line 101) | pub fn json<T>(mut self, json: &T) -> Self
method header (line 109) | pub fn header<K, V>(mut self, key: K, value: V) -> Self
method multipart (line 121) | pub fn multipart(mut self, form: reqwest::multipart::Form) -> Self {
type Output (line 128) | type Output = TestResponse;
type IntoFuture (line 129) | type IntoFuture = BoxFuture<'static, Self::Output>;
method into_future (line 131) | fn into_future(self) -> Self::IntoFuture {
type TestResponse (line 141) | pub struct TestResponse {
method bytes (line 155) | pub async fn bytes(self) -> Bytes {
method text (line 159) | pub async fn text(self) -> String {
method json (line 164) | pub async fn json<T>(self) -> T
method chunk (line 171) | pub async fn chunk(&mut self) -> Option<Bytes> {
method chunk_text (line 175) | pub async fn chunk_text(&mut self) -> Option<String> {
type Target (line 146) | type Target = reqwest::Response;
method deref (line 148) | fn deref(&self) -> &Self::Target {
FILE: axum/src/test_helpers/tracing_helpers.rs
type TracingEvent (line 16) | pub(crate) struct TracingEvent<T> {
function capture_tracing (line 23) | pub(crate) fn capture_tracing<T, F>(f: F) -> CaptureTracing<T, F>
type CaptureTracing (line 34) | pub(crate) struct CaptureTracing<T, F> {
function with_filter (line 41) | pub(crate) fn with_filter(mut self, filter_string: &str) -> Self {
type Output (line 53) | type Output = Vec<TracingEvent<T>>;
type IntoFuture (line 54) | type IntoFuture = Pin<Box<dyn Future<Output = Self::Output> + Send>>;
method into_future (line 56) | fn into_future(self) -> Self::IntoFuture {
type TestMakeWriter (line 88) | struct TestMakeWriter {
method new (line 93) | fn new() -> (Self, Handle) {
type Writer (line 106) | type Writer = Writer<'a>;
method make_writer (line 108) | fn make_writer(&'a self) -> Self::Writer {
type Writer (line 113) | struct Writer<'a>(&'a TestMakeWriter);
function write (line 116) | fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
function flush (line 127) | fn flush(&mut self) -> io::Result<()> {
type Handle (line 132) | struct Handle {
method take (line 137) | fn take(self) -> String {
FILE: axum/src/util.rs
type PercentDecodedStr (line 13) | pub(crate) struct PercentDecodedStr(Arc<str>);
method new (line 16) | pub(crate) fn new<S>(s: S) -> Option<Self>
method as_str (line 26) | pub(crate) fn as_str(&self) -> &str {
type Target (line 32) | type Target = str;
method deref (line 35) | fn deref(&self) -> &Self::Target {
type MapIntoResponse (line 49) | pub(crate) struct MapIntoResponse<S> {
function new (line 54) | pub(crate) fn new(inner: S) -> Self {
type Response (line 64) | type Response = Response;
type Error (line 65) | type Error = S::Error;
type Future (line 66) | type Future = MapIntoResponseFuture<S::Future>;
type Output (line 91) | type Output = Result<Response, E>;
method poll (line 93) | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Outp...
function poll_ready (line 68) | fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::...
function call (line 72) | fn call(&mut self, req: http::Request<B>) -> Self::Future {
function try_downcast (line 99) | pub(crate) fn try_downcast<T, K>(k: K) -> Result<T, K>
function test_try_downcast (line 113) | fn test_try_downcast() {
FILE: axum/tests/panic_location.rs
function routes_with_overlapping_method_routes (line 12) | fn routes_with_overlapping_method_routes() {
FILE: examples/anyhow-error-response/src/main.rs
function main (line 15) | async fn main() {
function handler (line 25) | async fn handler() -> Result<(), AppError> {
function try_thing (line 30) | fn try_thing() -> Result<(), anyhow::Error> {
type AppError (line 35) | struct AppError(anyhow::Error);
method from (line 58) | fn from(err: E) -> Self {
method into_response (line 39) | fn into_response(self) -> Response {
function app (line 48) | fn app() -> Router {
function test_main_page (line 71) | async fn test_main_page() {
FILE: examples/auto-reload/src/main.rs
function main (line 12) | async fn main() {
function handler (line 32) | async fn handler() -> Html<&'static str> {
FILE: examples/chat/src/main.rs
type AppState (line 27) | struct AppState {
function main (line 35) | async fn main() {
function websocket_handler (line 62) | async fn websocket_handler(
function websocket (line 72) | async fn websocket(stream: WebSocket, state: Arc<AppState>) {
function check_username (line 148) | fn check_username(state: &AppState, string: &mut String, name: &str) {
function index (line 159) | async fn index() -> Html<&'static str> {
FILE: examples/compression/src/main.rs
function main (line 11) | async fn main() {
function app (line 29) | fn app() -> Router {
function root (line 37) | async fn root(Json(value): Json<Value>) -> Json<Value> {
FILE: examples/compression/src/tests.rs
function handle_uncompressed_request_bodies (line 16) | async fn handle_uncompressed_request_bodies() {
function decompress_gzip_request_bodies (line 37) | async fn decompress_gzip_request_bodies() {
function decompress_br_request_bodies (line 59) | async fn decompress_br_request_bodies() {
function decompress_zstd_request_bodies (line 81) | async fn decompress_zstd_request_bodies() {
function do_not_compress_response_bodies (line 103) | async fn do_not_compress_response_bodies() {
function compress_response_bodies_with_gzip (line 121) | async fn compress_response_bodies_with_gzip() {
function compress_response_bodies_with_br (line 147) | async fn compress_response_bodies_with_br() {
function compress_response_bodies_with_zstd (line 172) | async fn compress_response_bodies_with_zstd() {
function json (line 195) | fn json() -> Value {
function json_body (line 205) | fn json_body(input: &Value) -> Body {
function json_from_response (line 209) | async fn json_from_response(response: Response) -> Value {
function byte_from_response (line 214) | async fn byte_from_response(response: Response) -> Bytes {
function body_as_json (line 220) | fn body_as_json(body: Bytes) -> Value {
function compress_gzip (line 224) | fn compress_gzip(json: &Value) -> Vec<u8> {
function compress_br (line 232) | fn compress_br(json: &Value) -> Vec<u8> {
function compress_zstd (line 242) | fn compress_zstd(json: &Value) -> Vec<u8> {
FILE: examples/consume-body-in-extractor-or-middleware/src/main.rs
function main (line 20) | async fn main() {
function print_request_body (line 41) | async fn print_request_body(request: Request, next: Next) -> Result<impl...
function buffer_request_body (line 49) | async fn buffer_request_body(request: Request) -> Result<Request, Respon...
function do_thing_with_request_body (line 64) | fn do_thing_with_request_body(bytes: Bytes) {
function handler (line 68) | async fn handler(BufferRequestBody(body): BufferRequestBody) {
type BufferRequestBody (line 73) | struct BufferRequestBody(Bytes);
type Rejection (line 80) | type Rejection = Response;
method from_request (line 82) | async fn from_request(req: Request, state: &S) -> Result<Self, Self::R...
FILE: examples/cors/src/main.rs
function main (line 17) | async fn main() {
function serve (line 41) | async fn serve(app: Router, port: u16) {
function html (line 47) | async fn html() -> impl IntoResponse {
function json (line 59) | async fn json() -> impl IntoResponse {
FILE: examples/customize-extractor-error/src/custom_extractor.rs
function handler (line 15) | pub async fn handler(Json(value): Json<Value>) -> impl IntoResponse {
type Json (line 20) | pub struct Json<T>(pub T);
type Rejection (line 27) | type Rejection = (StatusCode, axum::Json<Value>);
function from_request (line 29) | async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rej...
FILE: examples/customize-extractor-error/src/derive_from_request.rs
function handler (line 21) | pub async fn handler(Json(value): Json<Value>) -> impl IntoResponse {
type Json (line 28) | pub struct Json<T>(T);
method into_response (line 32) | fn into_response(self) -> axum::response::Response {
type ApiError (line 40) | pub struct ApiError {
method from (line 47) | fn from(rejection: JsonRejection) -> Self {
method into_response (line 57) | fn into_response(self) -> axum::response::Response {
FILE: examples/customize-extractor-error/src/main.rs
function main (line 15) | async fn main() {
FILE: examples/customize-extractor-error/src/with_rejection.rs
function handler (line 21) | pub async fn handler(
type ApiError (line 34) | pub enum ApiError {
method into_response (line 43) | fn into_response(self) -> axum::response::Response {
FILE: examples/customize-path-rejection/src/main.rs
function main (line 18) | async fn main() {
function handler (line 38) | async fn handler(Path(params): Path<Params>) -> impl IntoResponse {
type Params (line 43) | struct Params {
type Path (line 49) | struct Path<T>(T);
type Rejection (line 57) | type Rejection = (StatusCode, axum::Json<PathError>);
function from_request_parts (line 59) | async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self...
type PathError (line 140) | struct PathError {
FILE: examples/dependency-injection/src/main.rs
function main (line 24) | async fn main() {
type AppStateDyn (line 76) | struct AppStateDyn {
type AppStateGeneric (line 81) | struct AppStateGeneric<T> {
type User (line 86) | struct User {
type UserParams (line 92) | struct UserParams {
function create_user_dyn (line 96) | async fn create_user_dyn(
function get_user_dyn (line 110) | async fn get_user_dyn(
function create_user_generic (line 120) | async fn create_user_generic<T>(
function get_user_generic (line 137) | async fn get_user_generic<T>(
type UserRepo (line 150) | trait UserRepo: Send + Sync {
method get_user (line 151) | fn get_user(&self, id: Uuid) -> Option<User>;
method save_user (line 153) | fn save_user(&self, user: &User);
method get_user (line 162) | fn get_user(&self, id: Uuid) -> Option<User> {
method save_user (line 166) | fn save_user(&self, user: &User) {
type InMemoryUserRepo (line 157) | struct InMemoryUserRepo {
FILE: examples/diesel-async-postgres/migrations/2023-03-14-180127_add_users/up.sql
type "users" (line 2) | CREATE TABLE "users"(
FILE: examples/diesel-async-postgres/src/main.rs
constant MIGRATIONS (line 30) | pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!();
type User (line 42) | struct User {
type NewUser (line 50) | struct NewUser {
type Pool (line 55) | type Pool = bb8::Pool<AsyncPgConnection>;
function main (line 58) | async fn main() {
function create_user (line 89) | async fn create_user(
type DatabaseConnection (line 106) | struct DatabaseConnection(bb8::PooledConnection<'static, AsyncPgConnecti...
type Rejection (line 113) | type Rejection = (StatusCode, String);
method from_request_parts (line 115) | async fn from_request_parts(_parts: &mut Parts, state: &S) -> Result<S...
function list_users (line 124) | async fn list_users(
function internal_error (line 136) | fn internal_error<E>(err: E) -> (StatusCode, String)
FILE: examples/diesel-postgres/migrations/2023-03-14-180127_add_users/up.sql
type "users" (line 2) | CREATE TABLE "users"(
FILE: examples/diesel-postgres/src/main.rs
constant MIGRATIONS (line 27) | pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!("migrations...
type User (line 39) | struct User {
type NewUser (line 47) | struct NewUser {
function main (line 53) | async fn main() {
function create_user (line 92) | async fn create_user(
function list_users (line 110) | async fn list_users(
function internal_error (line 124) | fn internal_error<E>(err: E) -> (StatusCode, String)
FILE: examples/error-handling/src/main.rs
function main (line 46) | async fn main() {
type AppState (line 92) | struct AppState {
type UserParams (line 98) | struct UserParams {
type User (line 103) | struct User {
function users_create (line 109) | async fn users_create(
type AppJson (line 138) | struct AppJson<T>(T);
method into_response (line 144) | fn into_response(self) -> Response {
type AppError (line 151) | enum AppError {
method from (line 196) | fn from(rejection: JsonRejection) -> Self {
method from (line 202) | fn from(error: time_library::Error) -> Self {
method into_response (line 160) | fn into_response(self) -> Response {
function log_app_errors (line 208) | async fn log_app_errors(request: Request, next: Next) -> Response {
type Timestamp (line 225) | pub struct Timestamp(u64);
method now (line 228) | pub fn now() -> Result<Self, Error> {
type Error (line 241) | pub enum Error {
method fmt (line 246) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
FILE: examples/form/src/main.rs
function main (line 12) | async fn main() {
function app (line 32) | fn app() -> Router {
function show_form (line 36) | async fn show_form() -> Html<&'static str> {
type Input (line 64) | struct Input {
function accept_form (line 69) | async fn accept_form(Form(input): Form<Input>) -> Html<String> {
function test_get (line 88) | async fn test_get() {
function test_post (line 105) | async fn test_post() {
FILE: examples/global-404-handler/src/main.rs
function main (line 16) | async fn main() {
function handler (line 39) | async fn handler() -> Html<&'static str> {
function handler_404 (line 43) | async fn handler_404() -> impl IntoResponse {
FILE: examples/graceful-shutdown/src/main.rs
function main (line 19) | async fn main() {
function shutdown_signal (line 54) | async fn shutdown_signal() {
FILE: examples/handle-head-request/src/main.rs
function app (line 10) | fn app() -> Router {
function main (line 15) | async fn main() {
function get_head_handler (line 25) | async fn get_head_handler(method: http::Method) -> Response {
function do_some_computing_task (line 38) | fn do_some_computing_task() {
function test_get (line 51) | async fn test_get() {
function test_implicit_head (line 67) | async fn test_implicit_head() {
FILE: examples/hello-world/src/main.rs
function main (line 10) | async fn main() {
function handler (line 22) | async fn handler() -> Html<&'static str> {
FILE: examples/http-proxy/src/main.rs
function main (line 36) | async fn main() {
function proxy (line 86) | async fn proxy(req: Request) -> Result<Response, hyper::Error> {
function tunnel (line 112) | async fn tunnel(upgraded: Upgraded, addr: String) -> std::io::Result<()> {
FILE: examples/jwt/src/main.rs
function main (line 59) | async fn main() {
function protected (line 79) | async fn protected(claims: Claims) -> Result<String, AuthError> {
function authorize (line 86) | async fn authorize(Json(payload): Json<AuthPayload>) -> Result<Json<Auth...
method fmt (line 110) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
method into_response (line 145) | fn into_response(self) -> Response {
type Keys (line 159) | struct Keys {
method new (line 165) | fn new(secret: &[u8]) -> Self {
type Claims (line 174) | struct Claims {
type Rejection (line 128) | type Rejection = AuthError;
method from_request_parts (line 130) | async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result<S...
type AuthBody (line 181) | struct AuthBody {
method new (line 116) | fn new(access_token: String) -> Self {
type AuthPayload (line 187) | struct AuthPayload {
type AuthError (line 193) | enum AuthError {
FILE: examples/key-value-store/src/main.rs
function main (line 33) | async fn main() {
type SharedState (line 84) | type SharedState = Arc<RwLock<AppState>>;
type AppState (line 87) | struct AppState {
function kv_get (line 91) | async fn kv_get(
function kv_set (line 104) | async fn kv_set(Path(key): Path<String>, State(state): State<SharedState...
function list_keys (line 108) | async fn list_keys(State(state): State<SharedState>) -> String {
function admin_routes (line 117) | fn admin_routes() -> Router<SharedState> {
function handle_error (line 134) | async fn handle_error(error: BoxError) -> impl IntoResponse {
FILE: examples/low-level-native-tls/src/main.rs
function main (line 21) | async fn main() {
function handler (line 85) | async fn handler() -> &'static str {
function native_tls_acceptor (line 89) | fn native_tls_acceptor(key_file: PathBuf, cert_file: PathBuf) -> NativeT...
FILE: examples/low-level-openssl/src/main.rs
functio
Condensed preview — 480 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,765K chars).
[
{
"path": ".clippy.toml",
"chars": 169,
"preview": "allow-mixed-uninlined-format-args = false\ndisallowed-types = [\n { path = \"tower::util::BoxCloneService\", reason = \"Us"
},
{
"path": ".github/DISCUSSION_TEMPLATE/q-a.yml",
"chars": 582,
"preview": "body:\n - type: textarea\n attributes:\n label: Summary\n description: 'Your question:'\n validations:\n "
},
{
"path": ".github/ISSUE_TEMPLATE/bug_report.md",
"chars": 910,
"preview": "---\nname: 🐛 Bug Report\nabout: If something isn't working as expected 🤔.\n---\n\n<!--\nThank you for reporting an issue.\n\nPle"
},
{
"path": ".github/ISSUE_TEMPLATE/config.yml",
"chars": 283,
"preview": "contact_links:\n - name: 🙏 Q&A (GitHub Discussions)\n url: https://github.com/tokio-rs/axum/discussions/categories/q-a"
},
{
"path": ".github/ISSUE_TEMPLATE/feature_request.md",
"chars": 582,
"preview": "---\nname: 💡 Feature Request\nabout: I have a suggestion (and may want to implement it 🙂)!\n---\n\n- [ ] I have looked for ex"
},
{
"path": ".github/PULL_REQUEST_TEMPLATE.md",
"chars": 573,
"preview": "<!--\nThank you for your Pull Request. Please provide a description above and review\nthe requirements below.\n\nBug fixes a"
},
{
"path": ".github/workflows/CI.yml",
"chars": 6933,
"preview": "name: CI\n\nenv:\n CARGO_TERM_COLOR: always\n MSRV: '1.80'\n\non:\n push:\n branches:\n - main\n - v0.*\n pull_req"
},
{
"path": ".gitignore",
"chars": 25,
"preview": "target\n.DS_Store\n.vscode\n"
},
{
"path": "CHANGELOG.md",
"chars": 111,
"preview": "axum's changelog has moved and now lives [here](https://github.com/tokio-rs/axum/blob/main/axum/CHANGELOG.md).\n"
},
{
"path": "CONTRIBUTING.md",
"chars": 12526,
"preview": "# Contributing to axum\n\n🎈 Thanks for your help improving the project! We are so happy to have\nyou!\n\nThere are opportunit"
},
{
"path": "Cargo.toml",
"chars": 1641,
"preview": "[workspace]\nmembers = [\"axum\", \"axum-*\"]\nresolver = \"2\"\n\n[workspace.package]\nrust-version = \"1.80\"\n\n[workspace.lints.rus"
},
{
"path": "ECOSYSTEM.md",
"chars": 16353,
"preview": "# Community Projects\n\nIf your project isn't listed here and you would like it to be, please feel free to create a PR.\n\n#"
},
{
"path": "LICENSE",
"chars": 1078,
"preview": "MIT License\n\nCopyright (c) 2019–2025 axum Contributors\n\nPermission is hereby granted, free of charge, to any\nperson obta"
},
{
"path": "axum/CHANGELOG.md",
"chars": 100888,
"preview": "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Change"
},
{
"path": "axum/Cargo.toml",
"chars": 6702,
"preview": "[package]\nname = \"axum\"\nversion = \"0.8.8\" # remember to bump the version that axum-extra depends on\ncategories = [\"async"
},
{
"path": "axum/README.md",
"chars": 5566,
"preview": "# axum\n\n`axum` is an HTTP routing and request-handling library that focuses on ergonomics and modularity.\n\n[![Build stat"
},
{
"path": "axum/benches/benches.rs",
"chars": 6645,
"preview": "#![allow(missing_docs)]\n\nuse axum::{\n extract::State,\n routing::{get, post},\n Extension, Json, Router,\n};\nuse s"
},
{
"path": "axum/src/body/mod.rs",
"chars": 1430,
"preview": "//! HTTP body utilities.\n\n#[doc(no_inline)]\npub use http_body::Body as HttpBody;\n\n#[doc(no_inline)]\npub use bytes::Bytes"
},
{
"path": "axum/src/boxed.rs",
"chars": 4409,
"preview": "use std::{convert::Infallible, fmt};\n\nuse crate::extract::Request;\nuse tower::Service;\n\nuse crate::{\n handler::Handle"
},
{
"path": "axum/src/docs/debugging_handler_type_errors.md",
"chars": 1614,
"preview": "## Debugging handler type errors\n\nFor a function to be used as a handler it must implement the [`Handler`] trait.\naxum p"
},
{
"path": "axum/src/docs/error_handling.md",
"chars": 5529,
"preview": "Error handling model and utilities\n\n# axum's error handling model\n\naxum is based on [`tower::Service`] which bundles err"
},
{
"path": "axum/src/docs/extract.md",
"chars": 19050,
"preview": "Types and traits for extracting data from requests.\n\n# Intro\n\nA handler function is an async function that takes any num"
},
{
"path": "axum/src/docs/handlers_intro.md",
"chars": 392,
"preview": "In axum a \"handler\" is an async function that accepts zero or more\n[\"extractors\"](crate::extract) as arguments and retur"
},
{
"path": "axum/src/docs/method_routing/fallback.md",
"chars": 1525,
"preview": "Add a fallback service to the router.\n\nThis service will be called if no routes matches the incoming request.\n\n```rust\nu"
},
{
"path": "axum/src/docs/method_routing/layer.md",
"chars": 790,
"preview": "Apply a [`tower::Layer`] to all routes in the router.\n\nThis can be used to add additional processing to a request for a "
},
{
"path": "axum/src/docs/method_routing/merge.md",
"chars": 385,
"preview": "Merge two routers into one.\n\nThis is useful for breaking routers into smaller pieces and combining them\ninto one.\n\n```ru"
},
{
"path": "axum/src/docs/method_routing/route_layer.md",
"chars": 1065,
"preview": "Apply a [`tower::Layer`] to the router that will only run if the request matches\na route.\n\nNote that the middleware is o"
},
{
"path": "axum/src/docs/middleware.md",
"chars": 18430,
"preview": "# Intro\n\naxum is unique in that it doesn't have its own bespoke middleware system and\ninstead integrates with [`tower`]."
},
{
"path": "axum/src/docs/response.md",
"chars": 8339,
"preview": "Types and traits for generating responses.\n\n# Building responses\n\nAnything that implements [`IntoResponse`] can be retur"
},
{
"path": "axum/src/docs/routing/fallback.md",
"chars": 1615,
"preview": "Add a fallback [`Handler`] to the router.\n\nThis service will be called if no routes matches the incoming request.\n\n```ru"
},
{
"path": "axum/src/docs/routing/into_make_service_with_connect_info.md",
"chars": 1939,
"preview": "Convert this router into a [`MakeService`], that will store `C`'s\nassociated `ConnectInfo` in a request extension such t"
},
{
"path": "axum/src/docs/routing/layer.md",
"chars": 2025,
"preview": "Apply a [`tower::Layer`] to all routes in the router.\n\nThis can be used to add additional processing to a request for a "
},
{
"path": "axum/src/docs/routing/merge.md",
"chars": 1850,
"preview": "Merge the paths and fallbacks of two routers into a single [`Router`].\n\nThis is useful for breaking apps into smaller pi"
},
{
"path": "axum/src/docs/routing/method_not_allowed_fallback.md",
"chars": 1241,
"preview": "Add a fallback [`Handler`] for the case where a route exists, but the method of the request is not supported.\n\nSets a fa"
},
{
"path": "axum/src/docs/routing/nest.md",
"chars": 4800,
"preview": "Nest a [`Router`] at some path.\n\nThis allows you to break your application into smaller pieces and compose\nthem together"
},
{
"path": "axum/src/docs/routing/route.md",
"chars": 3715,
"preview": "Add another route to the router.\n\n`path` is a string of path segments separated by `/`. Each segment\ncan be either stati"
},
{
"path": "axum/src/docs/routing/route_layer.md",
"chars": 1311,
"preview": "Apply a [`tower::Layer`] to the router that will only run if the request matches\na route.\n\nNote that the middleware is o"
},
{
"path": "axum/src/docs/routing/route_service.md",
"chars": 2015,
"preview": "Add another route to the router that calls a [`Service`].\n\n# Example\n\n```rust,no_run\nuse axum::{\n Router,\n body::B"
},
{
"path": "axum/src/docs/routing/with_state.md",
"chars": 6866,
"preview": "Provide the state for the router. State passed to this method is global and will be used\nfor all requests this router re"
},
{
"path": "axum/src/docs/routing/without_v07_checks.md",
"chars": 1027,
"preview": "Turn off checks for compatibility with route matching syntax from 0.7.\n\nThis allows usage of paths starting with a colon"
},
{
"path": "axum/src/error_handling/mod.rs",
"chars": 7343,
"preview": "#![doc = include_str!(\"../docs/error_handling.md\")]\n\nuse crate::{\n extract::FromRequestParts,\n http::Request,\n "
},
{
"path": "axum/src/extension.rs",
"chars": 6787,
"preview": "use crate::{extract::rejection::*, response::IntoResponseParts};\nuse axum_core::extract::OptionalFromRequestParts;\nuse a"
},
{
"path": "axum/src/extract/connect_info.rs",
"chars": 12510,
"preview": "//! Extractor for getting connection information from a client.\n//!\n//! See [`Router::into_make_service_with_connect_inf"
},
{
"path": "axum/src/extract/matched_path.rs",
"chars": 12142,
"preview": "use super::{rejection::*, FromRequestParts};\nuse crate::routing::{RouteId, NEST_TAIL_PARAM_CAPTURE};\nuse axum_core::extr"
},
{
"path": "axum/src/extract/mod.rs",
"chars": 2362,
"preview": "#![doc = include_str!(\"../docs/extract.md\")]\n\nuse http::header::{self, HeaderMap};\n\n#[cfg(feature = \"tokio\")]\npub mod co"
},
{
"path": "axum/src/extract/multipart.rs",
"chars": 14637,
"preview": "//! Extractor that parses `multipart/form-data` requests commonly used with file uploads.\n//!\n//! See [`Multipart`] for "
},
{
"path": "axum/src/extract/nested_path.rs",
"chars": 5963,
"preview": "use std::{\n sync::Arc,\n task::{Context, Poll},\n};\n\nuse crate::extract::Request;\nuse axum_core::extract::FromReques"
},
{
"path": "axum/src/extract/original_uri.rs",
"chars": 2577,
"preview": "use super::{Extension, FromRequestParts};\nuse http::{request::Parts, Uri};\nuse std::convert::Infallible;\n\n/// Extractor "
},
{
"path": "axum/src/extract/path/de.rs",
"chars": 28586,
"preview": "use super::{ErrorKind, PathDeserializationError};\nuse crate::util::PercentDecodedStr;\nuse serde_core::{\n de::{self, D"
},
{
"path": "axum/src/extract/path/mod.rs",
"chars": 32191,
"preview": "//! Extractor that will get captures from the URL and parse them using\n//! [`serde`].\n\nmod de;\n\nuse crate::{\n extract"
},
{
"path": "axum/src/extract/query.rs",
"chars": 5239,
"preview": "use super::{rejection::*, FromRequestParts};\nuse http::{request::Parts, Uri};\nuse serde_core::de::DeserializeOwned;\n\n///"
},
{
"path": "axum/src/extract/raw_form.rs",
"chars": 2882,
"preview": "use axum_core::extract::{FromRequest, Request};\nuse bytes::Bytes;\nuse http::Method;\n\nuse super::{\n has_content_type,\n"
},
{
"path": "axum/src/extract/raw_query.rs",
"chars": 852,
"preview": "use super::FromRequestParts;\nuse http::request::Parts;\nuse std::convert::Infallible;\n\n/// Extractor that extracts the ra"
},
{
"path": "axum/src/extract/rejection.rs",
"chars": 6343,
"preview": "//! Rejection response types.\n\nuse axum_core::__composite_rejection as composite_rejection;\nuse axum_core::__define_reje"
},
{
"path": "axum/src/extract/state.rs",
"chars": 8995,
"preview": "use axum_core::extract::{FromRef, FromRequestParts};\nuse http::request::Parts;\nuse std::{\n convert::Infallible,\n o"
},
{
"path": "axum/src/extract/ws.rs",
"chars": 42106,
"preview": "//! Handle WebSocket connections.\n//!\n//! # Example\n//!\n//! ```\n//! use axum::{\n//! extract::ws::{WebSocketUpgrade, "
},
{
"path": "axum/src/form.rs",
"chars": 8357,
"preview": "use crate::extract::Request;\nuse crate::extract::{rejection::*, FromRequest, RawForm};\nuse axum_core::response::{IntoRes"
},
{
"path": "axum/src/handler/future.rs",
"chars": 1238,
"preview": "//! Handler future types.\n\nuse crate::response::Response;\nuse axum_core::extract::Request;\nuse futures_util::future::Map"
},
{
"path": "axum/src/handler/mod.rs",
"chars": 14682,
"preview": "//! Async functions that can be used to handle requests.\n//!\n#![doc = include_str!(\"../docs/handlers_intro.md\")]\n//!\n//!"
},
{
"path": "axum/src/handler/service.rs",
"chars": 5798,
"preview": "use super::Handler;\nuse crate::body::{Body, Bytes, HttpBody};\n#[cfg(feature = \"tokio\")]\nuse crate::extract::connect_info"
},
{
"path": "axum/src/json.rs",
"chars": 11518,
"preview": "use crate::extract::Request;\nuse crate::extract::{rejection::*, FromRequest};\nuse axum_core::extract::OptionalFromReques"
},
{
"path": "axum/src/lib.rs",
"chars": 15730,
"preview": "//! axum is an HTTP routing and request-handling library that focuses on ergonomics and modularity.\n//!\n//! # High-level"
},
{
"path": "axum/src/macros.rs",
"chars": 2776,
"preview": "//! Internal macros\n\nmacro_rules! opaque_future {\n ($(#[$m:meta])* pub type $name:ident = $actual:ty;) => {\n o"
},
{
"path": "axum/src/middleware/from_extractor.rs",
"chars": 10479,
"preview": "use crate::{\n extract::FromRequestParts,\n response::{IntoResponse, Response},\n};\nuse futures_core::future::BoxFutu"
},
{
"path": "axum/src/middleware/from_fn.rs",
"chars": 11342,
"preview": "use axum_core::extract::{FromRequest, FromRequestParts, Request};\nuse futures_core::future::BoxFuture;\nuse std::{\n an"
},
{
"path": "axum/src/middleware/map_request.rs",
"chars": 12264,
"preview": "use crate::body::{Body, Bytes, HttpBody};\nuse crate::response::{IntoResponse, Response};\nuse crate::BoxError;\nuse axum_c"
},
{
"path": "axum/src/middleware/map_response.rs",
"chars": 10169,
"preview": "use crate::response::{IntoResponse, Response};\nuse axum_core::extract::FromRequestParts;\nuse futures_core::future::BoxFu"
},
{
"path": "axum/src/middleware/mod.rs",
"chars": 1107,
"preview": "//! Utilities for writing middleware\n//!\n#![doc = include_str!(\"../docs/middleware.md\")]\n\nmod from_extractor;\nmod from_f"
},
{
"path": "axum/src/middleware/response_axum_body.rs",
"chars": 2051,
"preview": "use std::{\n error::Error,\n future::Future,\n pin::Pin,\n task::{ready, Context, Poll},\n};\n\nuse axum_core::{bod"
},
{
"path": "axum/src/response/mod.rs",
"chars": 16139,
"preview": "#![doc = include_str!(\"../docs/response.md\")]\n\nuse http::{header, HeaderValue, StatusCode};\n\nmod redirect;\n\npub mod sse;"
},
{
"path": "axum/src/response/redirect.rs",
"chars": 4458,
"preview": "use axum_core::response::{IntoResponse, Response};\nuse http::{header::LOCATION, HeaderValue, StatusCode};\n\n/// Response "
},
{
"path": "axum/src/response/sse.rs",
"chars": 25238,
"preview": "//! Server-Sent Events (SSE) responses.\n//!\n//! # Example\n//!\n//! ```\n//! use axum::{\n//! Router,\n//! routing::g"
},
{
"path": "axum/src/routing/future.rs",
"chars": 134,
"preview": "//! Future types.\n\npub use super::{\n into_make_service::IntoMakeServiceFuture,\n route::{InfallibleRouteFuture, Rou"
},
{
"path": "axum/src/routing/into_make_service.rs",
"chars": 1143,
"preview": "use std::{\n convert::Infallible,\n future::ready,\n task::{Context, Poll},\n};\nuse tower_service::Service;\n\n/// A "
},
{
"path": "axum/src/routing/method_filter.rs",
"chars": 5004,
"preview": "use http::Method;\nuse std::{\n fmt,\n fmt::{Debug, Formatter},\n};\n\n/// A filter that matches one or more HTTP method"
},
{
"path": "axum/src/routing/method_routing.rs",
"chars": 53181,
"preview": "//! Route to services and handlers based on HTTP methods.\n\nuse super::{future::InfallibleRouteFuture, IntoMakeService};\n"
},
{
"path": "axum/src/routing/mod.rs",
"chars": 27297,
"preview": "//! Routing between [`Service`]s and handlers.\n\nuse self::{future::RouteFuture, not_found::NotFound, path_router::PathRo"
},
{
"path": "axum/src/routing/not_found.rs",
"chars": 913,
"preview": "use crate::response::Response;\nuse axum_core::response::IntoResponse;\nuse http::{Request, StatusCode};\nuse std::{\n co"
},
{
"path": "axum/src/routing/path_router.rs",
"chars": 14619,
"preview": "use crate::{\n extract::{nested_path::SetNestedPath, Request},\n handler::Handler,\n};\nuse axum_core::response::IntoR"
},
{
"path": "axum/src/routing/route.rs",
"chars": 7338,
"preview": "use crate::{\n body::{Body, HttpBody},\n response::Response,\n util::MapIntoResponse,\n};\nuse axum_core::{extract::"
},
{
"path": "axum/src/routing/strip_prefix.rs",
"chars": 11824,
"preview": "use http::{Request, Uri};\nuse std::{\n sync::Arc,\n task::{Context, Poll},\n};\nuse tower::Layer;\nuse tower_layer::lay"
},
{
"path": "axum/src/routing/tests/fallback.rs",
"chars": 12262,
"preview": "use super::*;\nuse crate::middleware::{map_request, map_response};\n\n#[crate::test]\nasync fn basic() {\n let app = Route"
},
{
"path": "axum/src/routing/tests/get_to_head.rs",
"chars": 2023,
"preview": "use super::*;\nuse http::Method;\nuse tower::ServiceExt;\n\nmod for_handlers {\n use super::*;\n\n #[crate::test]\n asy"
},
{
"path": "axum/src/routing/tests/handle_error.rs",
"chars": 2385,
"preview": "use super::*;\nuse std::future::pending;\nuse tower::timeout::TimeoutLayer;\n\nasync fn unit() {}\n\nasync fn forever() {\n "
},
{
"path": "axum/src/routing/tests/merge.rs",
"chars": 11312,
"preview": "use super::*;\nuse crate::extract::OriginalUri;\nuse serde_json::{json, Value};\nuse tower::limit::ConcurrencyLimitLayer;\n\n"
},
{
"path": "axum/src/routing/tests/mod.rs",
"chars": 35782,
"preview": "use crate::{\n body::{Body, Bytes},\n error_handling::HandleErrorLayer,\n extract::{self, DefaultBodyLimit, FromRe"
},
{
"path": "axum/src/routing/tests/nest.rs",
"chars": 15646,
"preview": "use super::*;\nuse std::collections::HashMap;\nuse tower_http::services::ServeDir;\n\n#[crate::test]\nasync fn nesting_apps()"
},
{
"path": "axum/src/routing/url_params.rs",
"chars": 1505,
"preview": "use crate::util::PercentDecodedStr;\nuse http::Extensions;\nuse matchit::Params;\nuse std::sync::Arc;\n\n#[derive(Clone)]\npub"
},
{
"path": "axum/src/serve/listener.rs",
"chars": 9220,
"preview": "use std::{\n fmt,\n future::Future,\n pin::Pin,\n sync::Arc,\n task::{Context, Poll},\n time::Duration,\n};\n\n"
},
{
"path": "axum/src/serve/mod.rs",
"chars": 26516,
"preview": "//! Serve services.\n\nuse std::{\n convert::Infallible,\n error::Error as StdError,\n fmt::Debug,\n future::{Futu"
},
{
"path": "axum/src/service_ext.rs",
"chars": 2447,
"preview": "use crate::error_handling::HandleError;\n#[cfg(feature = \"tokio\")]\nuse crate::extract::connect_info::IntoMakeServiceWithC"
},
{
"path": "axum/src/test_helpers/counting_cloneable_state.rs",
"chars": 1326,
"preview": "use std::sync::{\n atomic::{AtomicBool, AtomicUsize, Ordering},\n Arc,\n};\n\npub(crate) struct CountingCloneableState "
},
{
"path": "axum/src/test_helpers/mod.rs",
"chars": 414,
"preview": "#![allow(clippy::disallowed_names)]\n\nuse crate::{extract::Request, response::Response, serve};\n\nmod test_client;\npub use"
},
{
"path": "axum/src/test_helpers/test_client.rs",
"chars": 4504,
"preview": "use super::{serve, Request, Response};\nuse bytes::Bytes;\nuse futures_core::future::BoxFuture;\nuse http::header::{HeaderN"
},
{
"path": "axum/src/test_helpers/tracing_helpers.rs",
"chars": 3502,
"preview": "use std::{\n future::{Future, IntoFuture},\n io,\n marker::PhantomData,\n pin::Pin,\n sync::{Arc, Mutex},\n};\n\n"
},
{
"path": "axum/src/util.rs",
"chars": 2547,
"preview": "use axum_core::response::{IntoResponse, Response};\nuse pin_project_lite::pin_project;\nuse std::{\n future::Future,\n "
},
{
"path": "axum/tests/panic_location.rs",
"chars": 1141,
"preview": "//! Separate test binary, because the panic hook is a global resource\n\nuse std::{\n panic::{catch_unwind, set_hook, ta"
},
{
"path": "axum-core/CHANGELOG.md",
"chars": 12271,
"preview": "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Change"
},
{
"path": "axum-core/Cargo.toml",
"chars": 1728,
"preview": "[package]\ncategories = [\"asynchronous\", \"network-programming\", \"web-programming\"]\ndescription = \"Core types and traits f"
},
{
"path": "axum-core/README.md",
"chars": 1439,
"preview": "# axum-core\n\n[](https://"
},
{
"path": "axum-core/src/body.rs",
"chars": 5715,
"preview": "//! HTTP body utilities.\n\nuse crate::{BoxError, Error};\nuse bytes::Bytes;\nuse futures_core::{Stream, TryStream};\nuse htt"
},
{
"path": "axum-core/src/error.rs",
"chars": 757,
"preview": "use crate::BoxError;\nuse std::{error::Error as StdError, fmt};\n\n/// Errors that can happen when using axum.\n#[derive(Deb"
},
{
"path": "axum-core/src/ext_traits/mod.rs",
"chars": 1268,
"preview": "pub(crate) mod request;\npub(crate) mod request_parts;\n\n#[cfg(test)]\nmod tests {\n use std::convert::Infallible;\n\n u"
},
{
"path": "axum-core/src/ext_traits/request.rs",
"chars": 13300,
"preview": "use crate::body::Body;\nuse crate::extract::{DefaultBodyLimitKind, FromRequest, FromRequestParts, Request};\nuse std::futu"
},
{
"path": "axum-core/src/ext_traits/request_parts.rs",
"chars": 5553,
"preview": "use crate::extract::FromRequestParts;\nuse http::request::Parts;\nuse std::future::Future;\n\nmod sealed {\n pub trait Sea"
},
{
"path": "axum-core/src/extract/default_body_limit.rs",
"chars": 7329,
"preview": "use self::private::DefaultBodyLimitService;\nuse http::Request;\nuse tower_layer::Layer;\n\n/// Layer for configuring the de"
},
{
"path": "axum-core/src/extract/from_ref.rs",
"chars": 843,
"preview": "/// Used to do reference-to-value conversions thus not consuming the input value.\n///\n/// This is mainly used with [`Sta"
},
{
"path": "axum-core/src/extract/mod.rs",
"chars": 3996,
"preview": "//! Types and traits for extracting data from requests.\n//!\n//! See [`axum::extract`] for more details.\n//!\n//! [`axum::"
},
{
"path": "axum-core/src/extract/option.rs",
"chars": 2026,
"preview": "use std::future::Future;\n\nuse http::request::Parts;\n\nuse crate::response::IntoResponse;\n\nuse super::{private, FromReques"
},
{
"path": "axum-core/src/extract/rejection.rs",
"chars": 2596,
"preview": "//! Rejection response types.\n\nuse crate::__composite_rejection as composite_rejection;\nuse crate::__define_rejection as"
},
{
"path": "axum-core/src/extract/request_parts.rs",
"chars": 5024,
"preview": "use super::{rejection::*, FromRequest, FromRequestParts, Request};\nuse crate::{body::Body, RequestExt};\nuse bytes::{BufM"
},
{
"path": "axum-core/src/extract/tuple.rs",
"chars": 3523,
"preview": "use super::{FromRequest, FromRequestParts, Request};\nuse crate::response::{IntoResponse, Response};\nuse http::request::P"
},
{
"path": "axum-core/src/lib.rs",
"chars": 1030,
"preview": "//! Core types and traits for [`axum`].\n//!\n//! Libraries authors that want to provide [`FromRequest`] or [`IntoResponse"
},
{
"path": "axum-core/src/macros.rs",
"chars": 10253,
"preview": "/// Private API.\n#[cfg(feature = \"tracing\")]\n#[doc(hidden)]\n#[macro_export]\nmacro_rules! __log_rejection {\n (\n "
},
{
"path": "axum-core/src/response/append_headers.rs",
"chars": 2021,
"preview": "use super::{IntoResponse, IntoResponseParts, Response, ResponseParts, TryIntoHeaderError};\nuse http::header::{HeaderName"
},
{
"path": "axum-core/src/response/into_response.rs",
"chars": 14451,
"preview": "use super::{ForceStatusCode, IntoResponseFailed, IntoResponseParts, Response, ResponseParts};\nuse crate::{body::Body, Bo"
},
{
"path": "axum-core/src/response/into_response_parts.rs",
"chars": 8319,
"preview": "use super::{IntoResponse, Response};\nuse http::{\n header::{HeaderMap, HeaderName, HeaderValue},\n Extensions, Statu"
},
{
"path": "axum-core/src/response/mod.rs",
"chars": 6162,
"preview": "//! Types and traits for generating responses.\n//!\n//! See [`axum::response`] for more details.\n//!\n//! [`axum::response"
},
{
"path": "axum-extra/CHANGELOG.md",
"chars": 22101,
"preview": "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Change"
},
{
"path": "axum-extra/Cargo.toml",
"chars": 5096,
"preview": "[package]\ncategories = [\"asynchronous\", \"network-programming\", \"web-programming\"]\ndescription = \"Extra utilities for axu"
},
{
"path": "axum-extra/README.md",
"chars": 1446,
"preview": "# axum-extra\n\n[](https:/"
},
{
"path": "axum-extra/src/body/async_read_body.rs",
"chars": 2334,
"preview": "use axum_core::{\n body::Body,\n response::{IntoResponse, Response},\n Error,\n};\nuse bytes::Bytes;\nuse http_body::"
},
{
"path": "axum-extra/src/body/mod.rs",
"chars": 164,
"preview": "//! Additional bodies.\n\n#[cfg(feature = \"async-read-body\")]\nmod async_read_body;\n\n#[cfg(feature = \"async-read-body\")]\npu"
},
{
"path": "axum-extra/src/either.rs",
"chars": 8396,
"preview": "//! `Either*` types for combining extractors or responses into a single type.\n//!\n//! # As an extractor\n//!\n//! ```\n//! "
},
{
"path": "axum-extra/src/extract/cached.rs",
"chars": 4636,
"preview": "use axum::extract::FromRequestParts;\nuse http::request::Parts;\n\n/// Cache results of other extractors.\n///\n/// `Cached` "
},
{
"path": "axum-extra/src/extract/cookie/mod.rs",
"chars": 11522,
"preview": "//! Cookie parsing and cookie jar management.\n//!\n//! See [`CookieJar`], [`SignedCookieJar`], and [`PrivateCookieJar`] f"
},
{
"path": "axum-extra/src/extract/cookie/private.rs",
"chars": 9228,
"preview": "use super::{cookies_from_request, set_cookies, Cookie, Key};\nuse axum_core::{\n extract::{FromRef, FromRequestParts},\n"
},
{
"path": "axum-extra/src/extract/cookie/signed.rs",
"chars": 9931,
"preview": "use super::{cookies_from_request, set_cookies};\nuse axum_core::{\n extract::{FromRef, FromRequestParts},\n response:"
},
{
"path": "axum-extra/src/extract/form.rs",
"chars": 4831,
"preview": "#![allow(deprecated)]\n\nuse axum::extract::rejection::RawFormRejection;\nuse axum::{\n extract::{FromRequest, RawForm, R"
},
{
"path": "axum-extra/src/extract/json_deserializer.rs",
"chars": 13963,
"preview": "use axum_core::__composite_rejection as composite_rejection;\nuse axum_core::__define_rejection as define_rejection;\nuse "
},
{
"path": "axum-extra/src/extract/mod.rs",
"chars": 1408,
"preview": "//! Additional extractors.\n\n#[cfg(feature = \"cached\")]\nmod cached;\n\n#[cfg(feature = \"with-rejection\")]\nmod with_rejectio"
},
{
"path": "axum-extra/src/extract/multipart.rs",
"chars": 14983,
"preview": "//! Extractor that parses `multipart/form-data` requests commonly used with file uploads.\n//!\n//! See [`Multipart`] for "
},
{
"path": "axum-extra/src/extract/query.rs",
"chars": 10196,
"preview": "#![allow(deprecated)]\n\nuse axum_core::__composite_rejection as composite_rejection;\nuse axum_core::__define_rejection as"
},
{
"path": "axum-extra/src/extract/with_rejection.rs",
"chars": 5285,
"preview": "use axum::extract::{FromRequest, FromRequestParts, Request};\nuse axum::response::IntoResponse;\nuse http::request::Parts;"
},
{
"path": "axum-extra/src/handler/mod.rs",
"chars": 6356,
"preview": "//! Additional handler utilities.\n\nuse axum::body::Body;\nuse axum::extract::Request;\nuse axum::{\n extract::FromReques"
},
{
"path": "axum-extra/src/handler/or.rs",
"chars": 4237,
"preview": "use super::HandlerCallWithExtractors;\nuse crate::either::Either;\nuse axum::{\n extract::{FromRequest, FromRequestParts"
},
{
"path": "axum-extra/src/json_lines.rs",
"chars": 7742,
"preview": "//! Newline delimited JSON extractor and response.\n\nuse axum_core::{\n body::Body,\n extract::{FromRequest, Request}"
},
{
"path": "axum-extra/src/lib.rs",
"chars": 3656,
"preview": "//! Extra utilities for [`axum`].\n//!\n//! # Feature flags\n//!\n//! axum-extra uses a set of [feature flags] to reduce the"
},
{
"path": "axum-extra/src/middleware.rs",
"chars": 2353,
"preview": "//! Additional middleware utilities.\n\nuse crate::either::Either;\nuse axum::middleware::ResponseAxumBodyLayer;\nuse tower_"
},
{
"path": "axum-extra/src/protobuf.rs",
"chars": 7103,
"preview": "//! Protocol Buffer extractor and response.\n\nuse axum_core::__composite_rejection as composite_rejection;\nuse axum_core:"
},
{
"path": "axum-extra/src/response/attachment.rs",
"chars": 4939,
"preview": "use super::content_disposition::EscapedFilename;\nuse axum_core::response::IntoResponse;\nuse http::{header, HeaderMap, He"
},
{
"path": "axum-extra/src/response/content_disposition.rs",
"chars": 1201,
"preview": "use std::fmt::{self, Write};\n\n/// A wrapper type that escapes backslashes and double quotes when formatted,\n/// for safe"
},
{
"path": "axum-extra/src/response/erased_json.rs",
"chars": 4493,
"preview": "use std::sync::Arc;\n\nuse axum_core::response::{IntoResponse, IntoResponseFailed, Response};\nuse bytes::{BufMut, Bytes, B"
},
{
"path": "axum-extra/src/response/error_response.rs",
"chars": 1622,
"preview": "use axum_core::response::{IntoResponse, Response};\nuse http::StatusCode;\nuse std::error::Error;\nuse tracing::error;\n\n///"
},
{
"path": "axum-extra/src/response/file_stream.rs",
"chars": 22600,
"preview": "use axum_core::{\n body,\n response::{IntoResponse, Response},\n BoxError,\n};\nuse bytes::Bytes;\nuse futures_core::"
},
{
"path": "axum-extra/src/response/mod.rs",
"chars": 2577,
"preview": "//! Additional types for generating responses.\n\n#[cfg(any(feature = \"attachment\", feature = \"file-stream\"))]\nmod content"
},
{
"path": "axum-extra/src/response/multiple.rs",
"chars": 11823,
"preview": "//! Generate forms to use in responses.\n\nuse axum_core::response::{IntoResponse, Response};\nuse fastrand;\nuse http::{hea"
},
{
"path": "axum-extra/src/routing/mod.rs",
"chars": 17428,
"preview": "//! Additional types for defining routes.\n\nuse axum::{\n extract::{OriginalUri, Request},\n response::{IntoResponse,"
},
{
"path": "axum-extra/src/routing/resource.rs",
"chars": 6544,
"preview": "use axum::{\n handler::Handler,\n routing::{delete, get, on, post, MethodFilter, MethodRouter},\n Router,\n};\n\n/// "
},
{
"path": "axum-extra/src/routing/typed.rs",
"chars": 13278,
"preview": "use std::{any::type_name, fmt};\n\nuse super::sealed::Sealed;\nuse http::Uri;\nuse serde_core::Serialize;\n\n/// A type safe p"
},
{
"path": "axum-extra/src/typed_header.rs",
"chars": 7252,
"preview": "//! Extractor and response for typed headers.\n\nuse axum_core::{\n extract::{FromRequestParts, OptionalFromRequestParts"
},
{
"path": "axum-extra/test_files/index.html",
"chars": 23,
"preview": "<h1>Hello, World!</h1>\n"
},
{
"path": "axum-extra/test_files/index_2.html",
"chars": 31,
"preview": "<strong>Hello, World!</strong>\n"
},
{
"path": "axum-extra/test_files/script.js",
"chars": 18,
"preview": "console.log('hi')\n"
},
{
"path": "axum-macros/CHANGELOG.md",
"chars": 7481,
"preview": "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Change"
},
{
"path": "axum-macros/Cargo.toml",
"chars": 1163,
"preview": "[package]\ncategories = [\"asynchronous\", \"network-programming\", \"web-programming\"]\ndescription = \"Macros for axum\"\neditio"
},
{
"path": "axum-macros/README.md",
"chars": 1446,
"preview": "# axum-macros\n\n[](https:"
},
{
"path": "axum-macros/rust-toolchain",
"chars": 19,
"preview": "nightly-2025-09-28\n"
},
{
"path": "axum-macros/src/attr_parsing.rs",
"chars": 2568,
"preview": "use quote::ToTokens;\nuse syn::{\n parse::{Parse, ParseStream},\n Token,\n};\n\npub(crate) fn parse_parenthesized_attrib"
},
{
"path": "axum-macros/src/axum_test.rs",
"chars": 1204,
"preview": "use proc_macro2::TokenStream;\nuse quote::{format_ident, quote};\nuse syn::{parse::Parse, parse_quote, visit_mut::VisitMut"
},
{
"path": "axum-macros/src/debug_handler.rs",
"chars": 26315,
"preview": "use std::{collections::HashSet, fmt};\n\nuse crate::{\n attr_parsing::{parse_assignment_attribute, second},\n with_pos"
},
{
"path": "axum-macros/src/from_ref.rs",
"chars": 2598,
"preview": "use proc_macro2::{Ident, TokenStream};\nuse quote::quote_spanned;\nuse syn::{\n parse::{Parse, ParseStream},\n spanned"
},
{
"path": "axum-macros/src/from_request/attr.rs",
"chars": 2516,
"preview": "use crate::attr_parsing::{combine_attribute, parse_parenthesized_attribute, Combine};\nuse syn::{\n parse::{Parse, Pars"
},
{
"path": "axum-macros/src/from_request/mod.rs",
"chars": 36635,
"preview": "use self::attr::FromRequestContainerAttrs;\nuse crate::{\n attr_parsing::{parse_attrs, second},\n from_request::attr:"
},
{
"path": "axum-macros/src/lib.rs",
"chars": 23004,
"preview": "//! Macros for [`axum`].\n//!\n//! [`axum`]: https://crates.io/crates/axum\n\n#![cfg_attr(docsrs, feature(doc_cfg))]\n#![cfg_"
},
{
"path": "axum-macros/src/typed_path.rs",
"chars": 13120,
"preview": "use proc_macro2::{Span, TokenStream};\nuse quote::{format_ident, quote, quote_spanned};\nuse syn::{parse::Parse, ItemStruc"
},
{
"path": "axum-macros/src/with_position.rs",
"chars": 3535,
"preview": "// this is copied from itertools under the following license\n//\n// Copyright (c) 2015\n//\n// Permission is hereby granted"
},
{
"path": "axum-macros/tests/debug_handler/fail/.gitkeep",
"chars": 0,
"preview": ""
},
{
"path": "axum-macros/tests/debug_handler/fail/argument_not_extractor.rs",
"chars": 96,
"preview": "use axum_macros::debug_handler;\n\n#[debug_handler]\nasync fn handler(_foo: bool) {}\n\nfn main() {}\n"
},
{
"path": "axum-macros/tests/debug_handler/fail/argument_not_extractor.stderr",
"chars": 1403,
"preview": "error[E0277]: the trait bound `bool: FromRequest<(), axum_core::extract::private::ViaParts>` is not satisfied\n --> tests"
},
{
"path": "axum-macros/tests/debug_handler/fail/duplicate_args.rs",
"chars": 110,
"preview": "use axum_macros::debug_handler;\n\n#[debug_handler(state = (), state = ())]\nasync fn handler() {}\n\nfn main() {}\n"
},
{
"path": "axum-macros/tests/debug_handler/fail/duplicate_args.stderr",
"chars": 180,
"preview": "error: `state` specified more than once\n --> tests/debug_handler/fail/duplicate_args.rs:3:29\n |\n3 | #[debug_handler(sta"
},
{
"path": "axum-macros/tests/debug_handler/fail/extension_not_clone.rs",
"chars": 181,
"preview": "use axum::extract::Extension;\nuse axum_macros::debug_handler;\n\nstruct NonCloneType;\n\n#[debug_handler]\nasync fn test_exte"
},
{
"path": "axum-macros/tests/debug_handler/fail/extension_not_clone.stderr",
"chars": 1328,
"preview": "error[E0277]: the trait bound `NonCloneType: Clone` is not satisfied\n --> tests/debug_handler/fail/extension_not_clone.r"
},
{
"path": "axum-macros/tests/debug_handler/fail/extract_self_mut.rs",
"chars": 373,
"preview": "use axum::extract::{FromRequest, Request};\nuse axum_macros::debug_handler;\n\nstruct A;\n\nimpl<S> FromRequest<S> for A\nwher"
},
{
"path": "axum-macros/tests/debug_handler/fail/extract_self_mut.stderr",
"chars": 182,
"preview": "error: Handlers must only take owned values\n --> tests/debug_handler/fail/extract_self_mut.rs:19:22\n |\n19 | async"
},
{
"path": "axum-macros/tests/debug_handler/fail/extract_self_ref.rs",
"chars": 369,
"preview": "use axum::extract::{FromRequest, Request};\nuse axum_macros::debug_handler;\n\nstruct A;\n\nimpl<S> FromRequest<S> for A\nwher"
},
{
"path": "axum-macros/tests/debug_handler/fail/extract_self_ref.stderr",
"chars": 174,
"preview": "error: Handlers must only take owned values\n --> tests/debug_handler/fail/extract_self_ref.rs:19:22\n |\n19 | async"
},
{
"path": "axum-macros/tests/debug_handler/fail/generics.rs",
"chars": 100,
"preview": "use axum_macros::debug_handler;\n\n#[debug_handler]\nasync fn handler<T>(_extract: T) {}\n\nfn main() {}\n"
},
{
"path": "axum-macros/tests/debug_handler/fail/generics.stderr",
"chars": 188,
"preview": "error: `#[axum_macros::debug_handler]` doesn't support generic functions\n --> tests/debug_handler/fail/generics.rs:4:17\n"
},
{
"path": "axum-macros/tests/debug_handler/fail/invalid_attrs.rs",
"chars": 91,
"preview": "use axum_macros::debug_handler;\n\n#[debug_handler(foo)]\nasync fn handler() {}\n\nfn main() {}\n"
},
{
"path": "axum-macros/tests/debug_handler/fail/invalid_attrs.stderr",
"chars": 130,
"preview": "error: expected `state`\n --> tests/debug_handler/fail/invalid_attrs.rs:3:17\n |\n3 | #[debug_handler(foo)]\n | "
},
{
"path": "axum-macros/tests/debug_handler/fail/json_not_deserialize.rs",
"chars": 138,
"preview": "use axum::Json;\nuse axum_macros::debug_handler;\n\nstruct Struct {}\n\n#[debug_handler]\nasync fn handler(_foo: Json<Struct>)"
},
{
"path": "axum-macros/tests/debug_handler/fail/json_not_deserialize.stderr",
"chars": 2628,
"preview": "error[E0277]: the trait bound `Struct: serde::Deserialize<'de>` is not satisfied\n --> tests/debug_handler/fail/json_not_"
},
{
"path": "axum-macros/tests/debug_handler/fail/multiple_paths.rs",
"chars": 143,
"preview": "use axum::extract::Path;\nuse axum_macros::debug_handler;\n\n#[debug_handler]\nasync fn handler(_: Path<String>, _: Path<Str"
},
{
"path": "axum-macros/tests/debug_handler/fail/multiple_paths.stderr",
"chars": 624,
"preview": "error: Multiple parameters must be extracted with a tuple `Path<(_, _)>` or a struct `Path<YourParams>`, not by applying"
},
{
"path": "axum-macros/tests/debug_handler/fail/multiple_request_consumers.rs",
"chars": 266,
"preview": "use axum::{\n body::Bytes,\n http::{Method, Uri},\n Json,\n};\nuse axum_macros::debug_handler;\n\n#[debug_handler]\nasy"
},
{
"path": "axum-macros/tests/debug_handler/fail/multiple_request_consumers.stderr",
"chars": 606,
"preview": "error: Can't have two extractors that consume the request body. `Json<_>` and `String` both do that.\n --> tests/debug_ha"
},
{
"path": "axum-macros/tests/debug_handler/fail/not_a_function.rs",
"chars": 74,
"preview": "use axum_macros::debug_handler;\n\n#[debug_handler]\nstruct A;\n\nfn main() {}\n"
},
{
"path": "axum-macros/tests/debug_handler/fail/not_a_function.stderr",
"chars": 102,
"preview": "error: expected `fn`\n --> tests/debug_handler/fail/not_a_function.rs:4:1\n |\n4 | struct A;\n | ^^^^^^\n"
},
{
"path": "axum-macros/tests/debug_handler/fail/not_async.rs",
"chars": 80,
"preview": "use axum_macros::debug_handler;\n\n#[debug_handler]\nfn handler() {}\n\nfn main() {}\n"
},
{
"path": "axum-macros/tests/debug_handler/fail/not_async.stderr",
"chars": 114,
"preview": "error: Handlers must be `async fn`s\n --> tests/debug_handler/fail/not_async.rs:4:1\n |\n4 | fn handler() {}\n | ^^\n"
},
{
"path": "axum-macros/tests/debug_handler/fail/not_send.rs",
"chars": 143,
"preview": "use axum_macros::debug_handler;\n\n#[debug_handler]\nasync fn handler() {\n let _rc = std::rc::Rc::new(());\n async {}."
},
{
"path": "axum-macros/tests/debug_handler/fail/not_send.stderr",
"chars": 886,
"preview": "error: future cannot be sent between threads safely\n --> tests/debug_handler/fail/not_send.rs:3:1\n |\n3 | #[debug_handle"
},
{
"path": "axum-macros/tests/debug_handler/fail/output_tuple_too_many.rs",
"chars": 1260,
"preview": "use axum::response::AppendHeaders;\n\n#[axum::debug_handler]\nasync fn handler() -> (\n axum::http::StatusCode,\n Appen"
},
{
"path": "axum-macros/tests/debug_handler/fail/output_tuple_too_many.stderr",
"chars": 419,
"preview": "error: Cannot return tuples with more than 17 elements\n --> tests/debug_handler/fail/output_tuple_too_many.rs:4:20\n |"
},
{
"path": "axum-macros/tests/debug_handler/fail/returning_request_parts.rs",
"chars": 192,
"preview": "#[axum::debug_handler]\nasync fn handler() -> (\n axum::http::request::Parts, // this should be response parts, not req"
},
{
"path": "axum-macros/tests/debug_handler/fail/returning_request_parts.stderr",
"chars": 382,
"preview": "error[E0308]: mismatched types\n --> tests/debug_handler/fail/returning_request_parts.rs:3:5\n |\n3 | axum::http::requ"
},
{
"path": "axum-macros/tests/debug_handler/fail/single_wrong_return_tuple.rs",
"chars": 145,
"preview": "#![allow(unused_parens)]\n\nstruct NotIntoResponse;\n\n#[axum::debug_handler]\nasync fn handler() -> (NotIntoResponse) {\n "
},
{
"path": "axum-macros/tests/debug_handler/fail/single_wrong_return_tuple.stderr",
"chars": 1050,
"preview": "error[E0277]: the trait bound `NotIntoResponse: IntoResponse` is not satisfied\n --> tests/debug_handler/fail/single_wron"
}
]
// ... and 280 more files (download for full content)
About this extraction
This page contains the full source code of the tokio-rs/axum GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 480 files (1.6 MB), approximately 439.9k tokens, and a symbol index with 2652 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.