├── .gitattributes ├── examples ├── todo │ ├── db │ │ └── DB_LIVES_HERE │ ├── migrations │ │ ├── .gitkeep │ │ └── 20160720150332_create_tasks_table │ │ │ ├── down.sql │ │ │ └── up.sql │ ├── static │ │ ├── images │ │ │ └── favicon.png │ │ └── css │ │ │ └── style.css │ ├── Rocket.toml │ ├── README.md │ └── Cargo.toml ├── pastebin │ ├── upload │ │ └── UPLOADS_GO_HERE │ ├── Cargo.toml │ └── src │ │ ├── main.rs │ │ └── paste_id.rs ├── databases │ ├── db │ │ ├── diesel │ │ │ └── migrations │ │ │ │ ├── .gitkeep │ │ │ │ └── 20210329150332_create_posts_table │ │ │ │ ├── down.sql │ │ │ │ └── up.sql │ │ └── sqlx │ │ │ └── migrations │ │ │ └── 20210331024424_create-posts-table.sql │ ├── Rocket.toml │ ├── README.md │ ├── src │ │ └── main.rs │ └── Cargo.toml ├── fairings │ ├── Rocket.toml │ ├── Cargo.toml │ └── src │ │ └── tests.rs ├── static-files │ ├── static │ │ ├── hidden │ │ │ ├── hi.txt │ │ │ └── index.html │ │ ├── rocket-icon.jpg │ │ └── index.html │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── manual-routing │ ├── Rocket.toml │ └── Cargo.toml ├── templating │ ├── Rocket.toml │ ├── templates │ │ ├── hbs │ │ │ ├── footer.html.hbs │ │ │ ├── nav.html.hbs │ │ │ ├── layout.html.hbs │ │ │ ├── error │ │ │ │ └── 404.html.hbs │ │ │ └── index.html.hbs │ │ └── tera │ │ │ ├── nav.html.tera │ │ │ ├── error │ │ │ └── 404.html.tera │ │ │ ├── base.html.tera │ │ │ └── index.html.tera │ ├── Cargo.toml │ └── src │ │ ├── main.rs │ │ ├── tera.rs │ │ └── hbs.rs ├── forms │ ├── Rocket.toml │ ├── Cargo.toml │ └── templates │ │ └── success.html.tera ├── tls │ ├── private │ │ ├── ed25519.p12 │ │ ├── rsa_sha256.p12 │ │ ├── ecdsa_nistp256_sha256.p12 │ │ ├── ecdsa_nistp384_sha384.p12 │ │ ├── ed25519_key.pem │ │ ├── ecdsa_nistp256_sha256_key_pkcs8.pem │ │ ├── ecdsa_nistp384_sha384_key_pkcs8.pem │ │ ├── ed25519_cert.pem │ │ ├── ecdsa_nistp256_sha256_cert.pem │ │ └── ecdsa_nistp384_sha384_cert.pem │ ├── Cargo.toml │ ├── src │ │ ├── tests.rs │ │ └── main.rs │ └── Rocket.toml ├── cookies │ ├── Rocket.toml │ ├── Cargo.toml │ ├── templates │ │ ├── session.html.hbs │ │ ├── message.html.hbs │ │ └── login.html.hbs │ └── src │ │ ├── main.rs │ │ └── message.rs ├── hello │ └── Cargo.toml ├── testing │ ├── Cargo.toml │ └── src │ │ ├── main.rs │ │ └── async_required.rs ├── error-handling │ └── Cargo.toml ├── state │ ├── Cargo.toml │ └── src │ │ ├── main.rs │ │ ├── managed_hit_count.rs │ │ └── managed_queue.rs ├── config │ ├── Cargo.toml │ ├── Rocket.toml │ └── src │ │ ├── main.rs │ │ └── tests.rs ├── responders │ └── Cargo.toml ├── serialization │ ├── Cargo.toml │ └── src │ │ ├── main.rs │ │ ├── msgpack.rs │ │ └── uuid.rs ├── chat │ ├── Cargo.toml │ └── static │ │ ├── reset.css │ │ └── index.html └── Cargo.toml ├── core ├── lib │ ├── tests │ │ ├── static │ │ │ ├── .hidden │ │ │ ├── inner │ │ │ │ ├── .hideme │ │ │ │ ├── goodbye │ │ │ │ └── index.html │ │ │ ├── other │ │ │ │ └── hello.txt │ │ │ └── index.html │ │ ├── twice_managed_state.rs │ │ ├── mount_point.rs │ │ ├── local-client-access-runtime-in-drop.rs │ │ ├── typed-uri-docs-redef-issue-1373.rs │ │ ├── config-secret-key-1500.rs │ │ ├── timer-on-attach.rs │ │ ├── encoded-uris.rs │ │ ├── can-correct-bad-local-uri.rs │ │ ├── on_launch_fairing_can_inspect_port.rs │ │ ├── redirect_from_catcher-issue-113.rs │ │ ├── local-client-json.rs │ │ ├── session-cookies-issue-1506.rs │ │ ├── can-launch-tls.rs │ │ ├── tls-config-from-source-1503.rs │ │ ├── responder_lifetime-issue-345.rs │ │ ├── absolute-uris-okay-issue-443.rs │ │ ├── route_guard.rs │ │ ├── form_value_from_encoded_str-issue-1425.rs │ │ ├── scoped-uri.rs │ │ ├── form_value_decoding-issue-82.rs │ │ ├── unsound-local-request-1312.rs │ │ ├── form_method-issue-45.rs │ │ ├── derive-reexports.rs │ │ ├── local_request_private_cookie-issue-368.rs │ │ ├── untracked-vs-tracked.rs │ │ ├── replace-content-type-518.rs │ │ ├── catcher-cookies-1213.rs │ │ ├── many-cookie-jars-at-once.rs │ │ ├── segments-issues-41-86.rs │ │ ├── uri-percent-encoding-issue-808.rs │ │ ├── conditionally-set-server-header-996.rs │ │ ├── mapped-base-issue-1262.rs │ │ ├── head_handling.rs │ │ └── flash-lazy-removes-issue-466.rs │ ├── fuzz │ │ ├── corpus │ │ │ └── uri-parsing │ │ │ │ ├── asterisk.seed │ │ │ │ ├── authority.seed │ │ │ │ ├── absolute.seed │ │ │ │ ├── origin.seed │ │ │ │ └── reference.seed │ │ ├── .gitignore │ │ ├── README.md │ │ ├── Cargo.toml │ │ └── targets │ │ │ ├── uri-parsing.rs │ │ │ └── uri-roundtrip.rs │ ├── src │ │ ├── router │ │ │ └── mod.rs │ │ ├── catcher │ │ │ └── mod.rs │ │ ├── form │ │ │ ├── name │ │ │ │ └── mod.rs │ │ │ └── options.rs │ │ ├── route │ │ │ ├── mod.rs │ │ │ └── segment.rs │ │ ├── fs │ │ │ └── mod.rs │ │ ├── data │ │ │ └── mod.rs │ │ ├── local │ │ │ ├── asynchronous │ │ │ │ └── mod.rs │ │ │ └── blocking │ │ │ │ └── mod.rs │ │ ├── serde │ │ │ └── mod.rs │ │ ├── mtls.rs │ │ ├── response │ │ │ ├── stream │ │ │ │ └── one.rs │ │ │ └── mod.rs │ │ └── request │ │ │ └── mod.rs │ └── build.rs ├── codegen │ ├── tests │ │ ├── ui-fail-nightly │ │ │ ├── catch.rs │ │ │ ├── catchers.rs │ │ │ ├── routes.rs │ │ │ ├── from_form.rs │ │ │ ├── responder.rs │ │ │ ├── async-entry.rs │ │ │ ├── uri_display.rs │ │ │ ├── from_form_field.rs │ │ │ ├── responder-types.rs │ │ │ ├── route-warnings.rs │ │ │ ├── catch_type_errors.rs │ │ │ ├── route-type-errors.rs │ │ │ ├── typed-uri-bad-type.rs │ │ │ ├── bad-ignored-segments.rs │ │ │ ├── from_form_type_errors.rs │ │ │ ├── route-path-bad-syntax.rs │ │ │ ├── typed-uris-bad-params.rs │ │ │ ├── uri_display_type_errors.rs │ │ │ ├── typed-uris-invalid-syntax.rs │ │ │ ├── route-attribute-general-syntax.rs │ │ │ ├── bad-ignored-segments.stderr │ │ │ ├── routes.stderr │ │ │ ├── catchers.stderr │ │ │ ├── from_form_type_errors.stderr │ │ │ └── route-warnings.stderr │ │ ├── ui-fail-stable │ │ │ ├── catch.rs │ │ │ ├── routes.rs │ │ │ ├── catchers.rs │ │ │ ├── async-entry.rs │ │ │ ├── from_form.rs │ │ │ ├── responder.rs │ │ │ ├── uri_display.rs │ │ │ ├── from_form_field.rs │ │ │ ├── responder-types.rs │ │ │ ├── route-warnings.rs │ │ │ ├── catch_type_errors.rs │ │ │ ├── route-type-errors.rs │ │ │ ├── typed-uri-bad-type.rs │ │ │ ├── bad-ignored-segments.rs │ │ │ ├── from_form_type_errors.rs │ │ │ ├── route-path-bad-syntax.rs │ │ │ ├── typed-uris-bad-params.rs │ │ │ ├── uri_display_type_errors.rs │ │ │ ├── typed-uris-invalid-syntax.rs │ │ │ ├── route-attribute-general-syntax.rs │ │ │ ├── route-warnings.stderr │ │ │ ├── bad-ignored-segments.stderr │ │ │ ├── routes.stderr │ │ │ ├── catchers.stderr │ │ │ ├── from_form_type_errors.stderr │ │ │ └── catch_type_errors.stderr │ │ ├── ui-fail │ │ │ ├── routes.rs │ │ │ ├── catchers.rs │ │ │ ├── bad-ignored-segments.rs │ │ │ ├── from_form_type_errors.rs │ │ │ ├── catch_type_errors.rs │ │ │ ├── route-type-errors.rs │ │ │ ├── responder-types.rs │ │ │ ├── route-warnings.rs │ │ │ ├── catch.rs │ │ │ ├── synchronize.sh │ │ │ ├── uri_display.rs │ │ │ ├── uri_display_type_errors.rs │ │ │ ├── typed-uris-invalid-syntax.rs │ │ │ ├── responder.rs │ │ │ ├── typed-uris-bad-params.rs │ │ │ ├── async-entry.rs │ │ │ └── route-path-bad-syntax.rs │ │ ├── ui-fail.rs │ │ ├── async-routes.rs │ │ ├── route-raw.rs │ │ ├── route-data.rs │ │ ├── route-ranking.rs │ │ └── expansion.rs │ ├── src │ │ ├── attribute │ │ │ ├── mod.rs │ │ │ ├── entry │ │ │ │ ├── test.rs │ │ │ │ └── main.rs │ │ │ └── param │ │ │ │ └── guard.rs │ │ ├── derive │ │ │ └── mod.rs │ │ └── bang │ │ │ ├── test_guide.rs │ │ │ └── export.rs │ └── Cargo.toml └── http │ └── src │ ├── tls │ └── mod.rs │ ├── parse │ ├── mod.rs │ ├── checkers.rs │ └── uri │ │ └── mod.rs │ ├── uri │ ├── fmt │ │ └── mod.rs │ ├── mod.rs │ └── error.rs │ ├── header │ └── mod.rs │ ├── hyper.rs │ └── lib.rs ├── contrib ├── dyn_templates │ ├── tests │ │ └── templates │ │ │ ├── hbs │ │ │ ├── reload.txt.hbs │ │ │ ├── common │ │ │ │ ├── footer.html.hbs │ │ │ │ └── header.html.hbs │ │ │ └── test.html.hbs │ │ │ └── tera │ │ │ ├── txt_test.txt.tera │ │ │ ├── html_test.html.tera │ │ │ └── base.txt.tera │ ├── Cargo.toml │ └── src │ │ └── handlebars_templates.rs ├── db_pools │ ├── codegen │ │ ├── tests │ │ │ ├── ui-fail-nightly │ │ │ │ ├── database-types.rs │ │ │ │ ├── database-syntax.rs │ │ │ │ └── database-types.stderr │ │ │ ├── ui-fail-stable │ │ │ │ ├── database-syntax.rs │ │ │ │ ├── database-types.rs │ │ │ │ └── database-types.stderr │ │ │ ├── ui-fail │ │ │ │ ├── database-types.rs │ │ │ │ └── database-syntax.rs │ │ │ └── ui-fail.rs │ │ └── Cargo.toml │ └── lib │ │ └── src │ │ └── error.rs └── sync_db_pools │ ├── codegen │ ├── tests │ │ ├── ui-fail-nightly │ │ │ ├── database-types.rs │ │ │ ├── database-syntax.rs │ │ │ ├── database-types.stderr │ │ │ └── database-syntax.stderr │ │ ├── ui-fail-stable │ │ │ ├── database-syntax.rs │ │ │ ├── database-types.rs │ │ │ ├── database-types.stderr │ │ │ └── database-syntax.stderr │ │ ├── ui-fail │ │ │ ├── database-types.rs │ │ │ └── database-syntax.rs │ │ └── ui-fail.rs │ └── Cargo.toml │ └── lib │ ├── src │ └── error.rs │ └── Cargo.toml ├── benchmarks ├── src │ └── bench.rs ├── Cargo.toml └── static │ └── rust-lang.routes ├── .github └── ISSUE_TEMPLATE │ ├── config.yml │ ├── suggestion.md │ ├── bug-report.md │ └── feature-request.md ├── Cargo.toml ├── .gitignore ├── site ├── tests │ ├── Cargo.toml │ └── src │ │ └── lib.rs ├── guide │ ├── 1-quickstart.md │ └── 11-conclusion.md └── README.md ├── scripts ├── mk-docs.sh ├── bump_version.sh └── publish.sh └── LICENSE-MIT /.gitattributes: -------------------------------------------------------------------------------- 1 | * text eol=lf 2 | -------------------------------------------------------------------------------- /examples/todo/db/DB_LIVES_HERE: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/todo/migrations/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/pastebin/upload/UPLOADS_GO_HERE: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /core/lib/tests/static/.hidden: -------------------------------------------------------------------------------- 1 | Peek-a-boo. 2 | -------------------------------------------------------------------------------- /core/lib/tests/static/inner/.hideme: -------------------------------------------------------------------------------- 1 | Oh no! 2 | -------------------------------------------------------------------------------- /core/lib/tests/static/other/hello.txt: -------------------------------------------------------------------------------- 1 | Hi! 2 | -------------------------------------------------------------------------------- /examples/databases/db/diesel/migrations/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /core/lib/fuzz/corpus/uri-parsing/asterisk.seed: -------------------------------------------------------------------------------- 1 | * 2 | -------------------------------------------------------------------------------- /core/lib/tests/static/inner/goodbye: -------------------------------------------------------------------------------- 1 | Thanks for coming! 2 | -------------------------------------------------------------------------------- /core/lib/tests/static/inner/index.html: -------------------------------------------------------------------------------- 1 | Inner index. 2 | -------------------------------------------------------------------------------- /examples/fairings/Rocket.toml: -------------------------------------------------------------------------------- 1 | [global] 2 | token = 123 3 | -------------------------------------------------------------------------------- /contrib/dyn_templates/tests/templates/hbs/reload.txt.hbs: -------------------------------------------------------------------------------- 1 | initial -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail-nightly/catch.rs: -------------------------------------------------------------------------------- 1 | ../ui-fail/catch.rs -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail-stable/catch.rs: -------------------------------------------------------------------------------- 1 | ../ui-fail/catch.rs -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail-stable/routes.rs: -------------------------------------------------------------------------------- 1 | ../ui-fail/routes.rs -------------------------------------------------------------------------------- /examples/static-files/static/hidden/hi.txt: -------------------------------------------------------------------------------- 1 | You found me! :o 2 | -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail-nightly/catchers.rs: -------------------------------------------------------------------------------- 1 | ../ui-fail/catchers.rs -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail-nightly/routes.rs: -------------------------------------------------------------------------------- 1 | ../ui-fail/routes.rs -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail-stable/catchers.rs: -------------------------------------------------------------------------------- 1 | ../ui-fail/catchers.rs -------------------------------------------------------------------------------- /core/lib/tests/static/index.html: -------------------------------------------------------------------------------- 1 | Just a file here: index.html. 2 | -------------------------------------------------------------------------------- /examples/manual-routing/Rocket.toml: -------------------------------------------------------------------------------- 1 | [global] 2 | port = 8000 3 | -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail-nightly/from_form.rs: -------------------------------------------------------------------------------- 1 | ../ui-fail/from_form.rs -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail-nightly/responder.rs: -------------------------------------------------------------------------------- 1 | ../ui-fail/responder.rs -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail-stable/async-entry.rs: -------------------------------------------------------------------------------- 1 | ../ui-fail/async-entry.rs -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail-stable/from_form.rs: -------------------------------------------------------------------------------- 1 | ../ui-fail/from_form.rs -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail-stable/responder.rs: -------------------------------------------------------------------------------- 1 | ../ui-fail/responder.rs -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail-stable/uri_display.rs: -------------------------------------------------------------------------------- 1 | ../ui-fail/uri_display.rs -------------------------------------------------------------------------------- /contrib/dyn_templates/tests/templates/hbs/common/footer.html.hbs: -------------------------------------------------------------------------------- 1 | Done. 2 | -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail-nightly/async-entry.rs: -------------------------------------------------------------------------------- 1 | ../ui-fail/async-entry.rs -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail-nightly/uri_display.rs: -------------------------------------------------------------------------------- 1 | ../ui-fail/uri_display.rs -------------------------------------------------------------------------------- /core/lib/fuzz/.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | corpus/*/* 3 | artifacts 4 | !*.seed 5 | -------------------------------------------------------------------------------- /examples/templating/Rocket.toml: -------------------------------------------------------------------------------- 1 | [default] 2 | template_dir = "templates" 3 | -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail-nightly/from_form_field.rs: -------------------------------------------------------------------------------- 1 | ../ui-fail/from_form_field.rs -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail-nightly/responder-types.rs: -------------------------------------------------------------------------------- 1 | ../ui-fail/responder-types.rs -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail-nightly/route-warnings.rs: -------------------------------------------------------------------------------- 1 | ../ui-fail/route-warnings.rs -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail-stable/from_form_field.rs: -------------------------------------------------------------------------------- 1 | ../ui-fail/from_form_field.rs -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail-stable/responder-types.rs: -------------------------------------------------------------------------------- 1 | ../ui-fail/responder-types.rs -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail-stable/route-warnings.rs: -------------------------------------------------------------------------------- 1 | ../ui-fail/route-warnings.rs -------------------------------------------------------------------------------- /contrib/dyn_templates/tests/templates/hbs/common/header.html.hbs: -------------------------------------------------------------------------------- 1 | Hello {{ title }}! 2 | -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail-nightly/catch_type_errors.rs: -------------------------------------------------------------------------------- 1 | ../ui-fail/catch_type_errors.rs -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail-nightly/route-type-errors.rs: -------------------------------------------------------------------------------- 1 | ../ui-fail/route-type-errors.rs -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail-nightly/typed-uri-bad-type.rs: -------------------------------------------------------------------------------- 1 | ../ui-fail/typed-uri-bad-type.rs -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail-stable/catch_type_errors.rs: -------------------------------------------------------------------------------- 1 | ../ui-fail/catch_type_errors.rs -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail-stable/route-type-errors.rs: -------------------------------------------------------------------------------- 1 | ../ui-fail/route-type-errors.rs -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail-stable/typed-uri-bad-type.rs: -------------------------------------------------------------------------------- 1 | ../ui-fail/typed-uri-bad-type.rs -------------------------------------------------------------------------------- /core/lib/fuzz/corpus/uri-parsing/authority.seed: -------------------------------------------------------------------------------- 1 | username:password@some.host:8088 2 | -------------------------------------------------------------------------------- /examples/todo/migrations/20160720150332_create_tasks_table/down.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE tasks 2 | -------------------------------------------------------------------------------- /contrib/db_pools/codegen/tests/ui-fail-nightly/database-types.rs: -------------------------------------------------------------------------------- 1 | ../ui-fail/database-types.rs -------------------------------------------------------------------------------- /contrib/db_pools/codegen/tests/ui-fail-stable/database-syntax.rs: -------------------------------------------------------------------------------- 1 | ../ui-fail/database-syntax.rs -------------------------------------------------------------------------------- /contrib/db_pools/codegen/tests/ui-fail-stable/database-types.rs: -------------------------------------------------------------------------------- 1 | ../ui-fail/database-types.rs -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail-nightly/bad-ignored-segments.rs: -------------------------------------------------------------------------------- 1 | ../ui-fail/bad-ignored-segments.rs -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail-stable/bad-ignored-segments.rs: -------------------------------------------------------------------------------- 1 | ../ui-fail/bad-ignored-segments.rs -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail-stable/from_form_type_errors.rs: -------------------------------------------------------------------------------- 1 | ../ui-fail/from_form_type_errors.rs -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail-stable/route-path-bad-syntax.rs: -------------------------------------------------------------------------------- 1 | ../ui-fail/route-path-bad-syntax.rs -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail-stable/typed-uris-bad-params.rs: -------------------------------------------------------------------------------- 1 | ../ui-fail/typed-uris-bad-params.rs -------------------------------------------------------------------------------- /benchmarks/src/bench.rs: -------------------------------------------------------------------------------- 1 | mod routing; 2 | 3 | criterion::criterion_main!(routing::routing); 4 | -------------------------------------------------------------------------------- /contrib/db_pools/codegen/tests/ui-fail-nightly/database-syntax.rs: -------------------------------------------------------------------------------- 1 | ../ui-fail/database-syntax.rs -------------------------------------------------------------------------------- /contrib/sync_db_pools/codegen/tests/ui-fail-nightly/database-types.rs: -------------------------------------------------------------------------------- 1 | ../ui-fail/database-types.rs -------------------------------------------------------------------------------- /contrib/sync_db_pools/codegen/tests/ui-fail-stable/database-syntax.rs: -------------------------------------------------------------------------------- 1 | ../ui-fail/database-syntax.rs -------------------------------------------------------------------------------- /contrib/sync_db_pools/codegen/tests/ui-fail-stable/database-types.rs: -------------------------------------------------------------------------------- 1 | ../ui-fail/database-types.rs -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail-nightly/from_form_type_errors.rs: -------------------------------------------------------------------------------- 1 | ../ui-fail/from_form_type_errors.rs -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail-nightly/route-path-bad-syntax.rs: -------------------------------------------------------------------------------- 1 | ../ui-fail/route-path-bad-syntax.rs -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail-nightly/typed-uris-bad-params.rs: -------------------------------------------------------------------------------- 1 | ../ui-fail/typed-uris-bad-params.rs -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail-nightly/uri_display_type_errors.rs: -------------------------------------------------------------------------------- 1 | ../ui-fail/uri_display_type_errors.rs -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail-stable/uri_display_type_errors.rs: -------------------------------------------------------------------------------- 1 | ../ui-fail/uri_display_type_errors.rs -------------------------------------------------------------------------------- /contrib/sync_db_pools/codegen/tests/ui-fail-nightly/database-syntax.rs: -------------------------------------------------------------------------------- 1 | ../ui-fail/database-syntax.rs -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail-nightly/typed-uris-invalid-syntax.rs: -------------------------------------------------------------------------------- 1 | ../ui-fail/typed-uris-invalid-syntax.rs -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail-stable/typed-uris-invalid-syntax.rs: -------------------------------------------------------------------------------- 1 | ../ui-fail/typed-uris-invalid-syntax.rs -------------------------------------------------------------------------------- /core/lib/fuzz/corpus/uri-parsing/absolute.seed: -------------------------------------------------------------------------------- 1 | http://user:pass@domain.com:4444/foo/bar?some=query 2 | -------------------------------------------------------------------------------- /core/lib/fuzz/corpus/uri-parsing/origin.seed: -------------------------------------------------------------------------------- 1 | /first_segment/second_segment/third?optional=query 2 | -------------------------------------------------------------------------------- /examples/forms/Rocket.toml: -------------------------------------------------------------------------------- 1 | [default] 2 | limits.data-form = "2MiB" 3 | template_dir = "templates/" 4 | -------------------------------------------------------------------------------- /examples/templating/templates/hbs/footer.html.hbs: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /examples/databases/db/diesel/migrations/20210329150332_create_posts_table/down.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE posts; 2 | -------------------------------------------------------------------------------- /core/codegen/src/attribute/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod entry; 2 | pub mod catch; 3 | pub mod route; 4 | pub mod param; 5 | -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail-nightly/route-attribute-general-syntax.rs: -------------------------------------------------------------------------------- 1 | ../ui-fail/route-attribute-general-syntax.rs -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail-stable/route-attribute-general-syntax.rs: -------------------------------------------------------------------------------- 1 | ../ui-fail/route-attribute-general-syntax.rs -------------------------------------------------------------------------------- /core/lib/fuzz/corpus/uri-parsing/reference.seed: -------------------------------------------------------------------------------- 1 | http://user:pass@domain.com:4444/foo/bar?some=query#and-fragment 2 | -------------------------------------------------------------------------------- /examples/tls/private/ed25519.p12: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rocket-org/Rocket/HEAD/examples/tls/private/ed25519.p12 -------------------------------------------------------------------------------- /examples/templating/templates/hbs/nav.html.hbs: -------------------------------------------------------------------------------- 1 | Hello | About 2 | -------------------------------------------------------------------------------- /examples/tls/private/rsa_sha256.p12: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rocket-org/Rocket/HEAD/examples/tls/private/rsa_sha256.p12 -------------------------------------------------------------------------------- /examples/templating/templates/tera/nav.html.tera: -------------------------------------------------------------------------------- 1 | Hello | About 2 | -------------------------------------------------------------------------------- /examples/todo/static/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rocket-org/Rocket/HEAD/examples/todo/static/images/favicon.png -------------------------------------------------------------------------------- /examples/cookies/Rocket.toml: -------------------------------------------------------------------------------- 1 | [default] 2 | secret_key = "itlYmFR2vYKrOmFhupMIn/hyB6lYCCTXz4yaQX89XVg=" 3 | template_dir = "templates" 4 | -------------------------------------------------------------------------------- /examples/todo/Rocket.toml: -------------------------------------------------------------------------------- 1 | [default] 2 | template_dir = "static" 3 | 4 | [default.databases.sqlite_database] 5 | url = "db/db.sqlite" 6 | -------------------------------------------------------------------------------- /examples/static-files/static/rocket-icon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rocket-org/Rocket/HEAD/examples/static-files/static/rocket-icon.jpg -------------------------------------------------------------------------------- /contrib/dyn_templates/tests/templates/hbs/test.html.hbs: -------------------------------------------------------------------------------- 1 | {{> hbs/common/header }} 2 |
{{ content }}
3 | {{> hbs/common/footer }} 4 | -------------------------------------------------------------------------------- /examples/tls/private/ecdsa_nistp256_sha256.p12: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rocket-org/Rocket/HEAD/examples/tls/private/ecdsa_nistp256_sha256.p12 -------------------------------------------------------------------------------- /examples/tls/private/ecdsa_nistp384_sha384.p12: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rocket-org/Rocket/HEAD/examples/tls/private/ecdsa_nistp384_sha384.p12 -------------------------------------------------------------------------------- /core/codegen/src/derive/mod.rs: -------------------------------------------------------------------------------- 1 | mod form_field; 2 | pub mod from_form; 3 | pub mod from_form_field; 4 | pub mod responder; 5 | pub mod uri_display; 6 | -------------------------------------------------------------------------------- /core/lib/src/router/mod.rs: -------------------------------------------------------------------------------- 1 | //! Rocket's router. 2 | 3 | mod router; 4 | mod collider; 5 | 6 | pub(crate) use router::*; 7 | pub(crate) use collider::*; 8 | -------------------------------------------------------------------------------- /examples/tls/private/ed25519_key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MC4CAQAwBQYDK2VwBCIEIKzhuOs4KVtmEBw86yumn8ID4tYm/aPmz8QtBIrlJkTE 3 | -----END PRIVATE KEY----- 4 | -------------------------------------------------------------------------------- /core/http/src/tls/mod.rs: -------------------------------------------------------------------------------- 1 | mod listener; 2 | mod util; 3 | 4 | #[cfg(feature = "mtls")] 5 | pub mod mtls; 6 | 7 | pub use rustls; 8 | pub use listener::{TlsListener, Config}; 9 | -------------------------------------------------------------------------------- /core/lib/tests/twice_managed_state.rs: -------------------------------------------------------------------------------- 1 | struct A; 2 | 3 | #[test] 4 | #[should_panic] 5 | fn twice_managed_state() { 6 | let _ = rocket::build().manage(A).manage(A); 7 | } 8 | -------------------------------------------------------------------------------- /examples/static-files/static/index.html: -------------------------------------------------------------------------------- 1 |

Hello, world!

2 | 3 | 4 | A rocket icon. 5 | 6 | -------------------------------------------------------------------------------- /core/lib/src/catcher/mod.rs: -------------------------------------------------------------------------------- 1 | //! Types and traits for error catchers and their handlers and return types. 2 | 3 | mod catcher; 4 | mod handler; 5 | 6 | pub use catcher::*; 7 | pub use handler::*; 8 | -------------------------------------------------------------------------------- /contrib/dyn_templates/tests/templates/tera/txt_test.txt.tera: -------------------------------------------------------------------------------- 1 | {% extends "tera/base" %} 2 | {% block title %}{{ title }}{% endblock title %} 3 | {% block content %} 4 | {{ content }} 5 | {% endblock content %} 6 | -------------------------------------------------------------------------------- /contrib/dyn_templates/tests/templates/tera/html_test.html.tera: -------------------------------------------------------------------------------- 1 | {% extends "tera/base" %} 2 | {% block title %}{{ title }}{% endblock title %} 3 | {% block content %} 4 | {{ content }} 5 | {% endblock content %} 6 | -------------------------------------------------------------------------------- /examples/hello/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "hello" 3 | version = "0.0.0" 4 | workspace = "../" 5 | edition = "2018" 6 | publish = false 7 | 8 | [dependencies] 9 | rocket = { path = "../../core/lib" } 10 | -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail/routes.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] extern crate rocket; 2 | 3 | fn main() { 4 | let _ = routes![a b]; 5 | let _ = routes![]; 6 | let _ = routes![a::, ]; 7 | let _ = routes![a::]; 8 | } 9 | -------------------------------------------------------------------------------- /examples/testing/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "testing" 3 | version = "0.0.0" 4 | workspace = "../" 5 | edition = "2018" 6 | publish = false 7 | 8 | [dependencies] 9 | rocket = { path = "../../core/lib" } 10 | -------------------------------------------------------------------------------- /examples/fairings/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "fairings" 3 | version = "0.0.0" 4 | workspace = "../" 5 | edition = "2018" 6 | publish = false 7 | 8 | [dependencies] 9 | rocket = { path = "../../core/lib" } 10 | -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail/catchers.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] extern crate rocket; 2 | 3 | fn main() { 4 | let _ = catchers![a b]; 5 | let _ = catchers![]; 6 | let _ = catchers![a::, ]; 7 | let _ = catchers![a::]; 8 | } 9 | -------------------------------------------------------------------------------- /core/http/src/parse/mod.rs: -------------------------------------------------------------------------------- 1 | mod media_type; 2 | mod accept; 3 | mod checkers; 4 | mod indexed; 5 | 6 | pub use self::media_type::*; 7 | pub use self::accept::*; 8 | 9 | pub mod uri; 10 | 11 | pub use self::indexed::*; 12 | -------------------------------------------------------------------------------- /examples/static-files/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "static-files" 3 | version = "0.0.0" 4 | workspace = "../" 5 | edition = "2018" 6 | publish = false 7 | 8 | [dependencies] 9 | rocket = { path = "../../core/lib" } 10 | -------------------------------------------------------------------------------- /examples/error-handling/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "error-handling" 3 | version = "0.0.0" 4 | workspace = "../" 5 | edition = "2018" 6 | publish = false 7 | 8 | [dependencies] 9 | rocket = { path = "../../core/lib" } 10 | -------------------------------------------------------------------------------- /examples/manual-routing/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "manual_routes" 3 | version = "0.0.0" 4 | workspace = "../" 5 | edition = "2018" 6 | publish = false 7 | 8 | [dependencies] 9 | rocket = { path = "../../core/lib" } 10 | -------------------------------------------------------------------------------- /examples/state/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "state" 3 | version = "0.0.0" 4 | workspace = "../" 5 | edition = "2018" 6 | publish = false 7 | 8 | [dependencies] 9 | rocket = { path = "../../core/lib" } 10 | flume = "0.10" 11 | -------------------------------------------------------------------------------- /examples/pastebin/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pastebin" 3 | version = "0.0.0" 4 | workspace = "../" 5 | edition = "2018" 6 | publish = false 7 | 8 | [dependencies] 9 | rocket = { path = "../../core/lib" } 10 | rand = "0.8" 11 | -------------------------------------------------------------------------------- /examples/tls/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "tls" 3 | version = "0.0.0" 4 | workspace = "../" 5 | edition = "2018" 6 | publish = false 7 | 8 | [dependencies] 9 | rocket = { path = "../../core/lib", features = ["tls", "mtls"] } 10 | -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail-stable/route-warnings.stderr: -------------------------------------------------------------------------------- 1 | error: checking for warnings! 2 | --> $DIR/route-warnings.rs:25:5 3 | | 4 | 25 | compile_error!("checking for warnings!") 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 6 | -------------------------------------------------------------------------------- /examples/config/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "config" 3 | version = "0.0.0" 4 | workspace = "../" 5 | edition = "2018" 6 | publish = false 7 | 8 | [dependencies] 9 | rocket = { path = "../../core/lib", features = ["secrets"] } 10 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: true 2 | contact_links: 3 | - name: Question 4 | url: https://github.com/SergioBenitez/Rocket/discussions 5 | about: Please ask questions or raise indefinite concerns on Dicussions 6 | -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail/bad-ignored-segments.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] extern crate rocket; 2 | 3 | #[get("/<_>")] 4 | fn i0() {} 5 | 6 | #[get("/c?<_>")] 7 | fn i1() {} 8 | 9 | #[post("/d", data = "<_>")] 10 | fn i2() {} 11 | 12 | fn main() { } 13 | -------------------------------------------------------------------------------- /examples/responders/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "responders" 3 | version = "0.0.0" 4 | workspace = "../" 5 | edition = "2018" 6 | publish = false 7 | 8 | [dependencies] 9 | rocket = { path = "../../core/lib" } 10 | parking_lot = "0.11" 11 | -------------------------------------------------------------------------------- /examples/databases/db/sqlx/migrations/20210331024424_create-posts-table.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE posts ( 2 | id INTEGER PRIMARY KEY AUTOINCREMENT, 3 | title VARCHAR NOT NULL, 4 | text VARCHAR NOT NULL, 5 | published BOOLEAN NOT NULL DEFAULT 0 6 | ); 7 | -------------------------------------------------------------------------------- /contrib/dyn_templates/tests/templates/tera/base.txt.tera: -------------------------------------------------------------------------------- 1 | {% block head %} 2 | h_start 3 | title: {% block title %}{% endblock title %} 4 | h_end 5 | {% endblock head %} 6 | {% block content %}{% endblock content %} 7 | {% block footer %}foot{% endblock footer %} 8 | -------------------------------------------------------------------------------- /core/lib/src/form/name/mod.rs: -------------------------------------------------------------------------------- 1 | //! Types for field names, name keys, and key indices. 2 | 3 | mod name; 4 | mod view; 5 | mod key; 6 | mod buf; 7 | 8 | pub use name::Name; 9 | pub use view::NameView; 10 | pub use key::Key; 11 | pub use buf::NameBuf; 12 | -------------------------------------------------------------------------------- /core/lib/tests/mount_point.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | #[should_panic] 3 | fn bad_dynamic_mount() { 4 | rocket::build().mount("", vec![]); 5 | } 6 | 7 | #[test] 8 | fn good_static_mount() { 9 | rocket::build().mount("/abcdefghijkl_mno", vec![]); 10 | } 11 | -------------------------------------------------------------------------------- /examples/databases/db/diesel/migrations/20210329150332_create_posts_table/up.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE posts ( 2 | id INTEGER PRIMARY KEY AUTOINCREMENT, 3 | title VARCHAR NOT NULL, 4 | text VARCHAR NOT NULL, 5 | published BOOLEAN NOT NULL DEFAULT 0 6 | ); 7 | -------------------------------------------------------------------------------- /examples/databases/Rocket.toml: -------------------------------------------------------------------------------- 1 | [default.databases.rusqlite] 2 | url = "file:rusqlite?mode=memory&cache=shared" 3 | 4 | [default.databases.sqlx] 5 | url = "db/sqlx/db.sqlite" 6 | 7 | [default.databases.diesel] 8 | url = "db/diesel/db.sqlite" 9 | timeout = 10 10 | -------------------------------------------------------------------------------- /examples/serialization/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "serialization" 3 | version = "0.0.0" 4 | workspace = "../" 5 | edition = "2018" 6 | publish = false 7 | 8 | [dependencies.rocket] 9 | path = "../../core/lib" 10 | features = ["json", "msgpack", "uuid"] 11 | -------------------------------------------------------------------------------- /contrib/sync_db_pools/codegen/tests/ui-fail/database-types.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] extern crate rocket_sync_db_pools; 2 | 3 | struct Unknown; 4 | 5 | #[database("foo")] 6 | struct A(Unknown); 7 | 8 | #[database("foo")] 9 | struct B(Vec); 10 | 11 | fn main() { } 12 | -------------------------------------------------------------------------------- /examples/templating/templates/hbs/layout.html.hbs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Rocket Example - {{ title }} 5 | 6 | 7 | {{> hbs/nav}} 8 | {{~> page}} 9 | {{> hbs/footer}} 10 | 11 | 12 | -------------------------------------------------------------------------------- /examples/chat/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "chat" 3 | version = "0.0.0" 4 | workspace = "../" 5 | edition = "2018" 6 | publish = false 7 | 8 | [dependencies] 9 | rocket = { path = "../../core/lib", features = ["json"] } 10 | 11 | [dev-dependencies] 12 | rand = "0.8" 13 | -------------------------------------------------------------------------------- /examples/static-files/static/hidden/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Hmm... 7 | 8 | 9 | 👀 10 | 11 | 12 | -------------------------------------------------------------------------------- /core/lib/src/route/mod.rs: -------------------------------------------------------------------------------- 1 | //! Types and traits for routes and their request handlers and return types. 2 | 3 | mod route; 4 | mod handler; 5 | mod uri; 6 | mod segment; 7 | 8 | pub use route::*; 9 | pub use handler::*; 10 | pub use uri::*; 11 | 12 | pub(crate) use segment::Segment; 13 | -------------------------------------------------------------------------------- /examples/tls/src/tests.rs: -------------------------------------------------------------------------------- 1 | use rocket::local::blocking::Client; 2 | 3 | #[test] 4 | fn hello_world() { 5 | let client = Client::tracked(super::rocket()).unwrap(); 6 | let response = client.get("/").dispatch(); 7 | assert_eq!(response.into_string(), Some("Hello, world!".into())); 8 | } 9 | -------------------------------------------------------------------------------- /examples/databases/README.md: -------------------------------------------------------------------------------- 1 | # Databases Example 2 | 3 | This example makes use of SQLite. You'll need `sqlite3` and its development 4 | headers installed: 5 | 6 | * **macOS:** `brew install sqlite` 7 | * **Debian**, **Ubuntu:** `apt-get install libsqlite3-dev` 8 | * **Arch:** `pacman -S sqlite` 9 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "core/lib/", 4 | "core/codegen/", 5 | "core/http/", 6 | "contrib/db_pools/codegen/", 7 | "contrib/db_pools/lib/", 8 | "contrib/sync_db_pools/codegen/", 9 | "contrib/sync_db_pools/lib/", 10 | "contrib/dyn_templates/", 11 | "site/tests", 12 | ] 13 | -------------------------------------------------------------------------------- /contrib/db_pools/codegen/tests/ui-fail/database-types.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] extern crate rocket_db_pools; 2 | 3 | struct Unknown; 4 | 5 | #[derive(Database)] 6 | #[database("foo")] 7 | struct A(Unknown); 8 | 9 | #[derive(Database)] 10 | #[database("bar")] 11 | struct B(Vec); 12 | 13 | fn main() { } 14 | -------------------------------------------------------------------------------- /core/lib/src/fs/mod.rs: -------------------------------------------------------------------------------- 1 | //! File serving, file accepting, and file metadata types. 2 | 3 | mod server; 4 | mod named_file; 5 | mod temp_file; 6 | mod file_name; 7 | 8 | pub use server::*; 9 | pub use named_file::*; 10 | pub use temp_file::*; 11 | pub use file_name::*; 12 | pub use server::relative; 13 | -------------------------------------------------------------------------------- /examples/tls/private/ecdsa_nistp256_sha256_key_pkcs8.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgz5+60CMzUC7X2U50 3 | S8KIDYQ6MHUtwMTsHcUrbDhLfLahRANCAAQ7QL6wwC1f2Rrq0iXaERQ7wdquz7HY 4 | 1lr8xVr0KK7VM5ll7hTuO0CfL5apbg7UCiu4B5jZtdDKw5NqNIqTJK80 5 | -----END PRIVATE KEY----- 6 | -------------------------------------------------------------------------------- /examples/templating/templates/hbs/error/404.html.hbs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 404 - hbs 6 | 7 | 8 |

404: Hey! There's nothing here.

9 | The page at {{ uri }} does not exist! 10 | 11 | 12 | -------------------------------------------------------------------------------- /examples/templating/templates/tera/error/404.html.tera: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 404 - tera 6 | 7 | 8 |

404: Hey! There's nothing here.

9 | The page at {{ uri }} does not exist! 10 | 11 | 12 | -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn ui() { 3 | let path = match version_check::is_feature_flaggable() { 4 | Some(true) => "ui-fail-nightly", 5 | _ => "ui-fail-stable" 6 | }; 7 | 8 | let t = trybuild::TestCases::new(); 9 | t.compile_fail(format!("tests/{}/*.rs", path)); 10 | } 11 | -------------------------------------------------------------------------------- /examples/forms/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "forms" 3 | version = "0.0.0" 4 | workspace = "../" 5 | edition = "2018" 6 | publish = false 7 | 8 | [dependencies] 9 | rocket = { path = "../../core/lib" } 10 | 11 | [dependencies.rocket_dyn_templates] 12 | path = "../../contrib/dyn_templates" 13 | features = ["tera"] 14 | -------------------------------------------------------------------------------- /benchmarks/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rocket-benchmarks" 3 | version = "0.0.0" 4 | edition = "2018" 5 | publish = false 6 | 7 | [workspace] 8 | 9 | [[bench]] 10 | name = "main" 11 | path = "src/bench.rs" 12 | harness = false 13 | 14 | [dev-dependencies] 15 | rocket = { path = "../core/lib/" } 16 | criterion = "0.3" 17 | -------------------------------------------------------------------------------- /contrib/db_pools/codegen/tests/ui-fail.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn ui() { 3 | let path = match version_check::is_feature_flaggable() { 4 | Some(true) => "ui-fail-nightly", 5 | _ => "ui-fail-stable" 6 | }; 7 | 8 | let t = trybuild::TestCases::new(); 9 | t.compile_fail(format!("tests/{}/*.rs", path)); 10 | } 11 | -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail/from_form_type_errors.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] extern crate rocket; 2 | 3 | struct Unknown; 4 | 5 | #[derive(FromForm)] 6 | struct BadType3 { 7 | field: Unknown, 8 | } 9 | 10 | struct Foo(T); 11 | 12 | #[derive(FromForm)] 13 | struct Other { 14 | field: Foo, 15 | } 16 | 17 | fn main() { } 18 | -------------------------------------------------------------------------------- /examples/todo/migrations/20160720150332_create_tasks_table/up.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE tasks ( 2 | id INTEGER PRIMARY KEY AUTOINCREMENT, 3 | description VARCHAR NOT NULL, 4 | completed BOOLEAN NOT NULL DEFAULT 0 5 | ); 6 | 7 | INSERT INTO tasks (description) VALUES ("demo task"); 8 | INSERT INTO tasks (description) VALUES ("demo task2"); 9 | -------------------------------------------------------------------------------- /contrib/sync_db_pools/codegen/tests/ui-fail.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn ui() { 3 | let path = match version_check::is_feature_flaggable() { 4 | Some(true) => "ui-fail-nightly", 5 | _ => "ui-fail-stable" 6 | }; 7 | 8 | let t = trybuild::TestCases::new(); 9 | t.compile_fail(format!("tests/{}/*.rs", path)); 10 | } 11 | -------------------------------------------------------------------------------- /examples/serialization/src/main.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] extern crate rocket; 2 | 3 | #[cfg(test)] mod tests; 4 | 5 | mod json; 6 | mod msgpack; 7 | mod uuid; 8 | 9 | #[launch] 10 | fn rocket() -> _ { 11 | rocket::build() 12 | .attach(json::stage()) 13 | .attach(msgpack::stage()) 14 | .attach(uuid::stage()) 15 | } 16 | -------------------------------------------------------------------------------- /examples/todo/README.md: -------------------------------------------------------------------------------- 1 | # Rocket Todo Example 2 | 3 | This example makes use of a SQLite database via `diesel` to store todo tasks. As 4 | a result, you'll need to have `sqlite3` and its headers installed: 5 | 6 | * **OS X:** `brew install sqlite` 7 | * **Debian/Ubuntu:** `apt-get install libsqlite3-dev` 8 | * **Arch:** `pacman -S sqlite` 9 | -------------------------------------------------------------------------------- /core/lib/fuzz/README.md: -------------------------------------------------------------------------------- 1 | # Fuzzing 2 | 3 | Install `cargo-fuzz`: 4 | 5 | ```sh 6 | cargo install -f cargo-fuzz 7 | ``` 8 | 9 | Run any available target where `$target` is the name of the target and `$n` is 10 | the number of CPUs to use for fuzzing: 11 | 12 | ```sh 13 | cargo fuzz list # get list of targets 14 | cargo fuzz run $target -j $n 15 | ``` 16 | -------------------------------------------------------------------------------- /examples/cookies/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "cookies" 3 | version = "0.0.0" 4 | workspace = "../" 5 | edition = "2018" 6 | publish = false 7 | 8 | [dependencies] 9 | rocket = { path = "../../core/lib", features = ["secrets"] } 10 | 11 | [dependencies.rocket_dyn_templates] 12 | path = "../../contrib/dyn_templates" 13 | features = ["handlebars"] 14 | -------------------------------------------------------------------------------- /core/http/src/uri/fmt/mod.rs: -------------------------------------------------------------------------------- 1 | //! Type safe and URI safe formatting types and traits. 2 | 3 | mod uri_display; 4 | mod formatter; 5 | mod from_uri_param; 6 | mod encoding; 7 | mod part; 8 | 9 | pub use self::formatter::*; 10 | pub use self::uri_display::*; 11 | pub use self::from_uri_param::*; 12 | pub use self::part::*; 13 | 14 | pub(crate) use self::encoding::*; 15 | -------------------------------------------------------------------------------- /examples/tls/private/ecdsa_nistp384_sha384_key_pkcs8.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDClF5pKlKs9J5iaOAJE 3 | He7v7RfcSt14yMjrp6y1jntK9j9jzTXAGtHCyWwdW0GYTVmhZANiAATZKfDYqkqF 4 | HPG8CatHyERcr3QzdI1E+PvTHaCfwicih43lVQXDFlwSWyk5qKxW5CelnFGwVN9C 5 | tPik76l/bRS1zpqcFGQ8qppHlO/FVewyawyksuR4Mc+YVyd9PZc/iq8= 6 | -----END PRIVATE KEY----- 7 | -------------------------------------------------------------------------------- /core/http/src/header/mod.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | mod known_media_types; 3 | mod media_type; 4 | mod content_type; 5 | mod accept; 6 | mod header; 7 | 8 | pub use self::content_type::ContentType; 9 | pub use self::accept::{Accept, QMediaType}; 10 | pub use self::media_type::MediaType; 11 | pub use self::header::{Header, HeaderMap}; 12 | 13 | pub(crate) use self::media_type::Source; 14 | -------------------------------------------------------------------------------- /core/http/src/parse/checkers.rs: -------------------------------------------------------------------------------- 1 | #[inline(always)] 2 | pub fn is_whitespace(&byte: &char) -> bool { 3 | byte == ' ' || byte == '\t' 4 | } 5 | 6 | #[inline] 7 | pub fn is_valid_token(&c: &char) -> bool { 8 | match c { 9 | '0'..='9' | 'A'..='Z' | '^'..='~' | '#'..='\'' 10 | | '!' | '*' | '+' | '-' | '.' => true, 11 | _ => false 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /examples/state/src/main.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] extern crate rocket; 2 | 3 | #[cfg(test)] mod tests; 4 | 5 | mod request_local; 6 | mod managed_hit_count; 7 | mod managed_queue; 8 | 9 | #[launch] 10 | fn rocket() -> _ { 11 | rocket::build() 12 | .attach(request_local::stage()) 13 | .attach(managed_hit_count::stage()) 14 | .attach(managed_queue::stage()) 15 | } 16 | -------------------------------------------------------------------------------- /examples/templating/templates/tera/base.html.tera: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Tera Demo - {{ title }} 6 | 7 | 8 | {% include "tera/nav" %} 9 | 10 | {% block content %}{% endblock content %} 11 | 12 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /examples/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "config", 4 | "cookies", 5 | "databases", 6 | "error-handling", 7 | "fairings", 8 | "forms", 9 | "hello", 10 | "manual-routing", 11 | "responders", 12 | "serialization", 13 | "state", 14 | "static-files", 15 | "templating", 16 | "testing", 17 | "tls", 18 | 19 | "pastebin", 20 | "todo", 21 | "chat", 22 | ] 23 | -------------------------------------------------------------------------------- /examples/templating/templates/tera/index.html.tera: -------------------------------------------------------------------------------- 1 | {% extends "tera/base" %} 2 | 3 | {% block content %} 4 |

Hi {{ name }}!

5 |

Here are your items:

6 |
    7 | {% for s in items %} 8 |
  • {{ s }}
  • 9 | {% endfor %} 10 |
11 | 12 |

Try going to /tera/hello/Your Name

13 | {% endblock content %} 14 | -------------------------------------------------------------------------------- /core/lib/tests/local-client-access-runtime-in-drop.rs: -------------------------------------------------------------------------------- 1 | use rocket::local::blocking::Client; 2 | 3 | struct SpawnBlockingOnDrop; 4 | 5 | impl Drop for SpawnBlockingOnDrop { 6 | fn drop(&mut self) { 7 | rocket::tokio::task::spawn_blocking(|| ()); 8 | } 9 | } 10 | 11 | #[test] 12 | fn test_access_runtime_in_state_drop() { 13 | Client::debug(rocket::build().manage(SpawnBlockingOnDrop)).unwrap(); 14 | } 15 | -------------------------------------------------------------------------------- /examples/templating/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "templating" 3 | version = "0.0.0" 4 | workspace = "../" 5 | edition = "2018" 6 | publish = false 7 | 8 | [dependencies] 9 | rocket = { path = "../../core/lib" } 10 | 11 | # in your application, you should enable only the template engine(s) used 12 | [dependencies.rocket_dyn_templates] 13 | path = "../../contrib/dyn_templates" 14 | features = ["tera", "handlebars"] 15 | -------------------------------------------------------------------------------- /core/lib/tests/typed-uri-docs-redef-issue-1373.rs: -------------------------------------------------------------------------------- 1 | #![allow(dead_code)] // This test is only here to ensure it compiles. 2 | #![allow(unused_variables)] // This test is only here to ensure it compiles. 3 | 4 | mod a { 5 | /// Docs. 6 | #[rocket::post("/typed_uris/")] 7 | fn simple(id: i32) { } 8 | } 9 | 10 | mod b { 11 | /// Docs. 12 | #[rocket::post("/typed_uris/")] 13 | fn simple(id: i32) { } 14 | } 15 | -------------------------------------------------------------------------------- /examples/chat/static/reset.css: -------------------------------------------------------------------------------- 1 | html,body,p,ol,ul,li,dl,dt,dd,blockquote,figure,fieldset,legend,textarea,pre,iframe,hr,h1,h2,h3,h4,h5,h6{margin:0;padding:0}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal}ul{list-style:none}button,input,select{margin:0}html{box-sizing:border-box}*,*::before,*::after{box-sizing:inherit}img,video{height:auto;max-width:100%}iframe,button,input{border:0}table{border-collapse:collapse;border-spacing:0}td,th{padding:0} 2 | -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail/catch_type_errors.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] extern crate rocket; 2 | 3 | use rocket::Request; 4 | 5 | #[catch(404)] 6 | fn f1(_request: &Request) -> usize { 7 | 10 8 | } 9 | 10 | #[catch(404)] 11 | fn f2(_request: &Request) -> bool { 12 | false 13 | } 14 | 15 | #[catch(404)] 16 | fn f3(_request: bool) -> usize { 17 | 10 18 | } 19 | 20 | #[catch(404)] 21 | fn f4() -> usize { 22 | 10 23 | } 24 | 25 | fn main() { } 26 | -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail-stable/bad-ignored-segments.stderr: -------------------------------------------------------------------------------- 1 | error: parameter must be named 2 | --- help: use a name such as `_guard` or `_param` 3 | --> $DIR/bad-ignored-segments.rs:6:7 4 | | 5 | 6 | #[get("/c?<_>")] 6 | | ^^^^^^^^ 7 | 8 | error: parameter must be named 9 | --- help: use a name such as `_guard` or `_param` 10 | --> $DIR/bad-ignored-segments.rs:9:21 11 | | 12 | 9 | #[post("/d", data = "<_>")] 13 | | ^^^^^ 14 | -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail-nightly/bad-ignored-segments.stderr: -------------------------------------------------------------------------------- 1 | error: parameter must be named 2 | --> $DIR/bad-ignored-segments.rs:6:12 3 | | 4 | 6 | #[get("/c?<_>")] 5 | | ^ 6 | | 7 | = help: use a name such as `_guard` or `_param` 8 | 9 | error: parameter must be named 10 | --> $DIR/bad-ignored-segments.rs:9:22 11 | | 12 | 9 | #[post("/d", data = "<_>")] 13 | | ^^^ 14 | | 15 | = help: use a name such as `_guard` or `_param` 16 | -------------------------------------------------------------------------------- /core/lib/src/data/mod.rs: -------------------------------------------------------------------------------- 1 | //! Types and traits for handling incoming body data. 2 | 3 | #[macro_use] 4 | mod capped; 5 | mod data; 6 | mod data_stream; 7 | mod from_data; 8 | mod limits; 9 | 10 | pub use self::data::Data; 11 | pub use self::data_stream::DataStream; 12 | pub use self::from_data::{FromData, Outcome}; 13 | pub use self::limits::Limits; 14 | pub use self::capped::{N, Capped}; 15 | pub use ubyte::{ByteUnit, ToByteUnit}; 16 | 17 | pub(crate) use self::data_stream::StreamReader; 18 | -------------------------------------------------------------------------------- /examples/databases/src/main.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] extern crate rocket; 2 | #[macro_use] extern crate rocket_sync_db_pools; 3 | #[macro_use] extern crate diesel_migrations; 4 | #[macro_use] extern crate diesel; 5 | 6 | #[cfg(test)] mod tests; 7 | 8 | mod sqlx; 9 | mod diesel_sqlite; 10 | mod rusqlite; 11 | 12 | #[launch] 13 | fn rocket() -> _ { 14 | rocket::build() 15 | .attach(sqlx::stage()) 16 | .attach(rusqlite::stage()) 17 | .attach(diesel_sqlite::stage()) 18 | } 19 | -------------------------------------------------------------------------------- /examples/templating/templates/hbs/index.html.hbs: -------------------------------------------------------------------------------- 1 | {{#*inline "page"}} 2 | 3 |
4 |

Hi {{ name }}!

5 |

Here are your items:

6 |
    7 | {{#each items}} 8 |
  • {{ this }}
  • 9 | {{/each}} 10 |
11 |
12 | 13 |
14 |

Try going to /hbs/hello/Your Name.

15 |

Also, check {{ wow "this" }} (custom helper) out!

16 |
17 | 18 | {{/inline}} 19 | {{> hbs/layout}} 20 | -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail/route-type-errors.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] extern crate rocket; 2 | 3 | struct Q; 4 | 5 | #[get("/")] 6 | fn f0(foo: Q) {} 7 | 8 | #[get("/")] 9 | fn f1(foo: Q) {} 10 | 11 | #[get("/?")] 12 | fn f2(foo: Q) {} 13 | 14 | #[get("/?")] 15 | fn f3(foo: Q) {} 16 | 17 | #[post("/", data = "")] 18 | fn f4(foo: Q) {} 19 | 20 | #[get("/")] 21 | fn f5(a: Q, foo: Q) {} 22 | 23 | #[get("//other///okay")] 24 | fn f6(a: Q, foo: Q, good: usize, bar: Q) {} 25 | 26 | fn main() { } 27 | -------------------------------------------------------------------------------- /core/lib/src/local/asynchronous/mod.rs: -------------------------------------------------------------------------------- 1 | //! Asynchronous local dispatching of requests. 2 | //! 3 | //! This module contains the `asynchronous` variant of the `local` API: it can 4 | //! be used with `#[rocket::async_test]` or another asynchronous test harness. 5 | //! For the blocking variant, see [`blocking`](super::blocking). 6 | //! 7 | //! See the [top-level documentation](super) for more usage details. 8 | 9 | mod client; 10 | mod request; 11 | mod response; 12 | 13 | pub use client::*; 14 | pub use request::*; 15 | pub use response::*; 16 | -------------------------------------------------------------------------------- /core/lib/tests/config-secret-key-1500.rs: -------------------------------------------------------------------------------- 1 | #![cfg(feature = "secrets")] 2 | 3 | use rocket::figment::Figment; 4 | use rocket::config::{Config, SecretKey}; 5 | 6 | #[test] 7 | fn secret_key_in_config_not_zero() { 8 | let original_key = SecretKey::generate().expect("get key"); 9 | 10 | let config = Config { secret_key: original_key.clone(), ..Default::default() }; 11 | let figment = Figment::from(config); 12 | let figment_key: SecretKey = figment.extract_inner("secret_key").unwrap(); 13 | assert_eq!(original_key, figment_key); 14 | } 15 | -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail/responder-types.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] extern crate rocket; 2 | 3 | #[derive(Responder)] 4 | struct Thing1 { 5 | thing: u8, 6 | } 7 | 8 | #[derive(Responder)] 9 | struct Thing2 { 10 | thing: String, 11 | other: u8, 12 | } 13 | 14 | #[derive(Responder)] 15 | struct Thing3 { 16 | thing: u8, 17 | other: u8, 18 | } 19 | 20 | #[derive(Responder)] 21 | struct Thing4 { 22 | thing: String, 23 | other: rocket::http::ContentType, 24 | then: String, 25 | } 26 | 27 | #[get("/")] 28 | fn foo() -> usize { 0 } 29 | 30 | fn main() { } 31 | -------------------------------------------------------------------------------- /core/lib/tests/timer-on-attach.rs: -------------------------------------------------------------------------------- 1 | #[rocket::async_test] 2 | async fn test_await_timer_inside_attach() { 3 | 4 | async fn do_async_setup() { 5 | // By using a timer or I/O resource, we ensure that do_async_setup will 6 | // deadlock if no thread is able to tick the time or I/O drivers. 7 | rocket::tokio::time::sleep(std::time::Duration::from_millis(100)).await; 8 | } 9 | 10 | rocket::build() 11 | .attach(rocket::fairing::AdHoc::on_ignite("1", |rocket| async { 12 | do_async_setup().await; 13 | rocket 14 | })); 15 | } 16 | -------------------------------------------------------------------------------- /core/lib/tests/encoded-uris.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] extern crate rocket; 2 | 3 | #[get("/hello süper $?a&?&")] 4 | fn index(value: &str) -> &str { 5 | value 6 | } 7 | 8 | mod encoded_uris { 9 | use rocket::local::blocking::Client; 10 | 11 | #[test] 12 | fn can_route_to_encoded_uri() { 13 | let client = Client::debug_with(routes![super::index]).unwrap(); 14 | let response = client.get("/hello%20s%C3%BCper%20%24?a&%3F&value=a+b") 15 | .dispatch() 16 | .into_string(); 17 | 18 | assert_eq!(response.unwrap(), "a b"); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /examples/cookies/templates/session.html.hbs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Rocket: Session Example 7 | 8 | 9 |

Rocket Session Example

10 |

Logged in with user ID {{ user_id }}.

11 |
12 | 13 |
14 | 15 | Home 16 | 17 | 18 | -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail-nightly/routes.stderr: -------------------------------------------------------------------------------- 1 | error: expected `,` 2 | --> $DIR/routes.rs:4:23 3 | | 4 | 4 | let _ = routes![a b]; 5 | | ^ 6 | 7 | error: expected identifier 8 | --> $DIR/routes.rs:6:24 9 | | 10 | 6 | let _ = routes![a::, ]; 11 | | ^ 12 | 13 | error: unexpected end of input, expected identifier 14 | --> $DIR/routes.rs:7:13 15 | | 16 | 7 | let _ = routes![a::]; 17 | | ^^^^^^^^^^^^ 18 | | 19 | = note: this error originates in the macro `routes` (in Nightly builds, run with -Z macro-backtrace for more info) 20 | -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail-stable/routes.stderr: -------------------------------------------------------------------------------- 1 | error: expected `,` 2 | --> $DIR/routes.rs:4:23 3 | | 4 | 4 | let _ = routes![a b]; 5 | | ^ 6 | 7 | error: expected identifier 8 | --> $DIR/routes.rs:6:24 9 | | 10 | 6 | let _ = routes![a::, ]; 11 | | ^ 12 | 13 | error: unexpected end of input, expected identifier 14 | --> $DIR/routes.rs:7:13 15 | | 16 | 7 | let _ = routes![a::]; 17 | | ^^^^^^^^^^^^ 18 | | 19 | = note: this error originates in the macro `routes` (in Nightly builds, run with -Z macro-backtrace for more info) 20 | -------------------------------------------------------------------------------- /examples/todo/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "todo" 3 | version = "0.0.0" 4 | workspace = "../" 5 | edition = "2018" 6 | publish = false 7 | 8 | [dependencies] 9 | rocket = { path = "../../core/lib" } 10 | diesel = { version = "1.3", features = ["sqlite", "r2d2"] } 11 | diesel_migrations = "1.3" 12 | 13 | [dev-dependencies] 14 | parking_lot = "0.11" 15 | rand = "0.8" 16 | 17 | [dependencies.rocket_sync_db_pools] 18 | path = "../../contrib/sync_db_pools/lib/" 19 | features = ["diesel_sqlite_pool"] 20 | 21 | [dependencies.rocket_dyn_templates] 22 | path = "../../contrib/dyn_templates" 23 | features = ["tera"] 24 | -------------------------------------------------------------------------------- /core/lib/src/form/options.rs: -------------------------------------------------------------------------------- 1 | /// Form guard options. 2 | /// 3 | /// See [`Form#leniency`](crate::form::Form#leniency) for details. 4 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] 5 | pub struct Options { 6 | /// Whether parsing should be strict (no extra parameters) or not. 7 | pub strict: bool, 8 | } 9 | 10 | #[allow(non_upper_case_globals, dead_code)] 11 | impl Options { 12 | /// `Options` with `strict` set to `false`. 13 | pub const Lenient: Self = Options { strict: false }; 14 | 15 | /// `Options` with `strict` set to `true`. 16 | pub const Strict: Self = Options { strict: true }; 17 | } 18 | -------------------------------------------------------------------------------- /core/lib/tests/can-correct-bad-local-uri.rs: -------------------------------------------------------------------------------- 1 | use rocket::http::uri::Origin; 2 | use rocket::local::blocking::Client; 3 | 4 | #[test] 5 | fn can_correct_bad_local_uri() { 6 | #[rocket::get("/")] fn f() {} 7 | 8 | let client = Client::debug_with(rocket::routes![f]).unwrap(); 9 | let mut req = client.get("this is a bad URI"); 10 | req.set_uri(Origin::parse("/").unwrap()); 11 | 12 | assert_eq!(req.uri(), "/"); 13 | assert!(req.dispatch().status().class().is_success()); 14 | 15 | let req = client.get("this is a bad URI"); 16 | assert!(req.dispatch().status().class().is_client_error()); 17 | } 18 | -------------------------------------------------------------------------------- /core/codegen/tests/async-routes.rs: -------------------------------------------------------------------------------- 1 | #![allow(dead_code)] 2 | 3 | #[macro_use] extern crate rocket; 4 | use rocket::http::uri::Origin; 5 | use rocket::request::Request; 6 | 7 | async fn noop() { } 8 | 9 | #[get("/")] 10 | async fn hello(_origin: &Origin<'_>) -> &'static str { 11 | noop().await; 12 | "Hello, world!" 13 | } 14 | 15 | #[get("/repeated_query?")] 16 | async fn repeated_query(sort: Vec<&str>) -> &str { 17 | noop().await; 18 | sort[0] 19 | } 20 | 21 | #[catch(404)] 22 | async fn not_found(req: &Request<'_>) -> String { 23 | noop().await; 24 | format!("{} not found", req.uri()) 25 | } 26 | -------------------------------------------------------------------------------- /core/lib/src/serde/mod.rs: -------------------------------------------------------------------------------- 1 | //! Automatic serialization and deserialization support. 2 | 3 | #[doc(inline)] 4 | pub use serde::ser::{Serialize, Serializer}; 5 | 6 | #[doc(inline)] 7 | pub use serde::de::{Deserialize, DeserializeOwned, Deserializer}; 8 | 9 | #[doc(hidden)] 10 | pub use serde::*; 11 | 12 | #[cfg(feature = "json")] 13 | #[cfg_attr(nightly, doc(cfg(feature = "json")))] 14 | pub mod json; 15 | 16 | #[cfg(feature = "msgpack")] 17 | #[cfg_attr(nightly, doc(cfg(feature = "msgpack")))] 18 | pub mod msgpack; 19 | 20 | #[cfg(feature = "uuid")] 21 | #[cfg_attr(nightly, doc(cfg(feature = "uuid")))] 22 | pub mod uuid; 23 | -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail-nightly/catchers.stderr: -------------------------------------------------------------------------------- 1 | error: expected `,` 2 | --> $DIR/catchers.rs:4:25 3 | | 4 | 4 | let _ = catchers![a b]; 5 | | ^ 6 | 7 | error: expected identifier 8 | --> $DIR/catchers.rs:6:26 9 | | 10 | 6 | let _ = catchers![a::, ]; 11 | | ^ 12 | 13 | error: unexpected end of input, expected identifier 14 | --> $DIR/catchers.rs:7:13 15 | | 16 | 7 | let _ = catchers![a::]; 17 | | ^^^^^^^^^^^^^^ 18 | | 19 | = note: this error originates in the macro `catchers` (in Nightly builds, run with -Z macro-backtrace for more info) 20 | -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail-stable/catchers.stderr: -------------------------------------------------------------------------------- 1 | error: expected `,` 2 | --> $DIR/catchers.rs:4:25 3 | | 4 | 4 | let _ = catchers![a b]; 5 | | ^ 6 | 7 | error: expected identifier 8 | --> $DIR/catchers.rs:6:26 9 | | 10 | 6 | let _ = catchers![a::, ]; 11 | | ^ 12 | 13 | error: unexpected end of input, expected identifier 14 | --> $DIR/catchers.rs:7:13 15 | | 16 | 7 | let _ = catchers![a::]; 17 | | ^^^^^^^^^^^^^^ 18 | | 19 | = note: this error originates in the macro `catchers` (in Nightly builds, run with -Z macro-backtrace for more info) 20 | -------------------------------------------------------------------------------- /core/lib/src/local/blocking/mod.rs: -------------------------------------------------------------------------------- 1 | //! Blocking local dispatching of requests. 2 | //! 3 | //! This module contains the `blocking` variant of the `local` API: it can be 4 | //! used in Rust's synchronous `#[test]` harness. This is accomplished by 5 | //! starting and running an interal asynchronous Runtime as needed. For the 6 | //! asynchronous variant, see [`asynchronous`](super::asynchronous). 7 | //! 8 | //! See the [top-level documentation](super) for more usage details. 9 | 10 | mod client; 11 | mod request; 12 | mod response; 13 | 14 | pub use self::client::*; 15 | pub use self::request::*; 16 | pub use self::response::*; 17 | -------------------------------------------------------------------------------- /examples/tls/src/main.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] extern crate rocket; 2 | 3 | #[cfg(test)] mod tests; 4 | 5 | use rocket::mtls::Certificate; 6 | 7 | #[get("/")] 8 | fn mutual(cert: Certificate<'_>) -> String { 9 | format!("Hello! Here's what we know: [{}] {}", cert.serial(), cert.subject()) 10 | } 11 | 12 | #[get("/", rank = 2)] 13 | fn hello() -> &'static str { 14 | "Hello, world!" 15 | } 16 | 17 | #[launch] 18 | fn rocket() -> _ { 19 | // See `Rocket.toml` and `Cargo.toml` for TLS configuration. 20 | // Run `./private/gen_certs.sh` to generate a CA and key pairs. 21 | rocket::build().mount("/", routes![hello, mutual]) 22 | } 23 | -------------------------------------------------------------------------------- /core/http/src/uri/mod.rs: -------------------------------------------------------------------------------- 1 | //! Types for URIs and traits for rendering URI components. 2 | 3 | #[macro_use] 4 | mod uri; 5 | mod origin; 6 | mod reference; 7 | mod authority; 8 | mod absolute; 9 | mod segments; 10 | mod path_query; 11 | mod asterisk; 12 | mod host; 13 | 14 | pub mod error; 15 | pub mod fmt; 16 | 17 | #[doc(inline)] 18 | pub use self::error::Error; 19 | 20 | pub use self::uri::*; 21 | pub use self::authority::*; 22 | pub use self::origin::*; 23 | pub use self::absolute::*; 24 | pub use self::segments::*; 25 | pub use self::reference::*; 26 | pub use self::path_query::*; 27 | pub use self::asterisk::*; 28 | pub use self::host::*; 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled files 2 | *.o 3 | *.so 4 | *.rlib 5 | *.dll 6 | 7 | # Executables 8 | *.exe 9 | 10 | # Generated by Cargo 11 | target 12 | 13 | # Generated databases 14 | db.sqlite 15 | 16 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 17 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 18 | Cargo.lock 19 | 20 | # Cargo config directory 21 | .cargo/ 22 | 23 | # The upload script, for now. 24 | scripts/upload-docs.sh 25 | scripts/redirect.html 26 | 27 | # Backup files. 28 | *.bak 29 | 30 | # Uploads in pastebin example. 31 | examples/pastebin/upload/* 32 | -------------------------------------------------------------------------------- /core/lib/fuzz/Cargo.toml: -------------------------------------------------------------------------------- 1 | 2 | [package] 3 | name = "rocket-fuzz" 4 | version = "0.0.0" 5 | authors = ["Automatically generated"] 6 | publish = false 7 | edition = "2018" 8 | 9 | [package.metadata] 10 | cargo-fuzz = true 11 | 12 | [dependencies] 13 | libfuzzer-sys = "0.4" 14 | 15 | [dependencies.rocket] 16 | path = ".." 17 | 18 | # Prevent this from interfering with workspaces 19 | [workspace] 20 | members = ["."] 21 | 22 | [[bin]] 23 | name = "uri-parsing" 24 | path = "targets/uri-parsing.rs" 25 | test = false 26 | doc = false 27 | 28 | [[bin]] 29 | name = "uri-roundtrip" 30 | path = "targets/uri-roundtrip.rs" 31 | test = false 32 | doc = false 33 | -------------------------------------------------------------------------------- /examples/cookies/src/main.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] extern crate rocket; 2 | 3 | #[cfg(test)] mod tests; 4 | 5 | mod session; 6 | mod message; 7 | 8 | use rocket::response::content::RawHtml; 9 | use rocket_dyn_templates::Template; 10 | 11 | #[get("/")] 12 | fn index() -> RawHtml<&'static str> { 13 | RawHtml(r#"Set a Message or Use Sessions."#) 14 | } 15 | 16 | #[launch] 17 | fn rocket() -> _ { 18 | rocket::build() 19 | .attach(Template::fairing()) 20 | .mount("/", routes![index]) 21 | .mount("/message", message::routes()) 22 | .mount("/session", session::routes()) 23 | } 24 | -------------------------------------------------------------------------------- /core/lib/tests/on_launch_fairing_can_inspect_port.rs: -------------------------------------------------------------------------------- 1 | use rocket::config::Config; 2 | use rocket::fairing::AdHoc; 3 | use rocket::futures::channel::oneshot; 4 | 5 | #[rocket::async_test] 6 | async fn on_ignite_fairing_can_inspect_port() { 7 | let (tx, rx) = oneshot::channel(); 8 | let rocket = rocket::custom(Config { port: 0, ..Config::debug_default() }) 9 | .attach(AdHoc::on_liftoff("Send Port -> Channel", move |rocket| { 10 | Box::pin(async move { 11 | tx.send(rocket.config().port).unwrap(); 12 | }) 13 | })); 14 | 15 | rocket::tokio::spawn(rocket.launch()); 16 | assert_ne!(rx.await.unwrap(), 0); 17 | } 18 | -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail/route-warnings.rs: -------------------------------------------------------------------------------- 1 | // must-compile-successfully 2 | 3 | #[macro_use] extern crate rocket; 4 | 5 | // Check for unknown media types. 6 | 7 | #[get("/", format = "application/x-custom")] 8 | fn f0() {} 9 | 10 | #[get("/", format = "x-custom/plain")] 11 | fn f1() {} 12 | 13 | #[get("/", format = "x-custom/x-custom")] 14 | fn f2() {} 15 | 16 | // Check if a data argument is used with a usually non-payload bearing method. 17 | 18 | #[get("/", data = "<_foo>")] 19 | fn g0(_foo: rocket::Data<'_>) {} 20 | 21 | #[head("/", data = "<_foo>")] 22 | fn g1(_foo: rocket::Data<'_>) {} 23 | 24 | fn main() { 25 | compile_error!("checking for warnings!") 26 | } 27 | -------------------------------------------------------------------------------- /core/codegen/src/attribute/entry/test.rs: -------------------------------------------------------------------------------- 1 | use super::EntryAttr; 2 | 3 | use devise::{Spanned, Result}; 4 | use proc_macro2::TokenStream; 5 | 6 | /// `#[rocket::async_test]`: calls the attributed fn inside `rocket::async_test` 7 | pub struct Test; 8 | 9 | impl EntryAttr for Test { 10 | const REQUIRES_ASYNC: bool = true; 11 | 12 | fn function(f: &mut syn::ItemFn) -> Result { 13 | let (attrs, vis, block, sig) = (&f.attrs, &f.vis, &f.block, &mut f.sig); 14 | sig.asyncness = None; 15 | Ok(quote_spanned!(block.span() => #(#attrs)* #[test] #vis #sig { 16 | ::rocket::async_test(async move #block) 17 | })) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail/catch.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] extern crate rocket; 2 | 3 | use rocket::Request; 4 | 5 | #[catch(404)] 6 | struct Catcher(String); 7 | 8 | #[catch(404)] 9 | const CATCH: &str = "Catcher"; 10 | 11 | #[catch("404")] 12 | fn e1(_request: &Request) { } 13 | 14 | #[catch(code = "404")] 15 | fn e2(_request: &Request) { } 16 | 17 | #[catch(code = 404)] 18 | fn e3(_request: &Request) { } 19 | 20 | #[catch(99)] 21 | fn e4(_request: &Request) { } 22 | 23 | #[catch(600)] 24 | fn e5(_request: &Request) { } 25 | 26 | #[catch(400, message = "foo")] 27 | fn e5(_request: &Request) { } 28 | 29 | #[catch(404)] 30 | fn f3(_request: &Request, other: bool) { } 31 | 32 | fn main() { } 33 | -------------------------------------------------------------------------------- /examples/state/src/managed_hit_count.rs: -------------------------------------------------------------------------------- 1 | use std::sync::atomic::{AtomicUsize, Ordering}; 2 | 3 | use rocket::State; 4 | use rocket::response::content::RawHtml; 5 | use rocket::fairing::AdHoc; 6 | 7 | struct HitCount(AtomicUsize); 8 | 9 | #[get("/")] 10 | fn index(hit_count: &State) -> RawHtml { 11 | let count = hit_count.0.fetch_add(1, Ordering::Relaxed) + 1; 12 | RawHtml(format!("Your visit is recorded!

Visits: {}", count)) 13 | } 14 | 15 | pub fn stage() -> AdHoc { 16 | AdHoc::on_ignite("Managed Hit Count", |rocket| async { 17 | rocket.mount("/count", routes![index]) 18 | .manage(HitCount(AtomicUsize::new(0))) 19 | }) 20 | } 21 | -------------------------------------------------------------------------------- /contrib/sync_db_pools/codegen/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rocket_sync_db_pools_codegen" 3 | version = "0.1.0-rc.1" 4 | authors = ["Sergio Benitez "] 5 | description = "Procedural macros for rocket_sync_db_pools." 6 | repository = "https://github.com/SergioBenitez/Rocket/contrib/sync_db_pools" 7 | readme = "../README.md" 8 | keywords = ["rocket", "framework", "database", "pools"] 9 | license = "MIT OR Apache-2.0" 10 | edition = "2018" 11 | 12 | [lib] 13 | proc-macro = true 14 | 15 | [dependencies] 16 | quote = "1.0" 17 | devise = "0.3" 18 | 19 | [dev-dependencies] 20 | version_check = "0.9" 21 | trybuild = "1.0" 22 | rocket_sync_db_pools = { path = "../lib", features = ["diesel_sqlite_pool"] } 23 | -------------------------------------------------------------------------------- /examples/databases/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "databases" 3 | version = "0.0.0" 4 | workspace = "../" 5 | edition = "2018" 6 | publish = false 7 | 8 | [dependencies] 9 | rocket = { path = "../../core/lib", features = ["json"] } 10 | diesel = { version = "1.3", features = ["sqlite", "r2d2"] } 11 | diesel_migrations = "1.3" 12 | 13 | [dependencies.sqlx] 14 | version = "0.5.1" 15 | default-features = false 16 | features = ["macros", "offline", "migrate"] 17 | 18 | [dependencies.rocket_db_pools] 19 | path = "../../contrib/db_pools/lib/" 20 | features = ["sqlx_sqlite"] 21 | 22 | [dependencies.rocket_sync_db_pools] 23 | path = "../../contrib/sync_db_pools/lib/" 24 | features = ["diesel_sqlite_pool", "sqlite_pool"] 25 | -------------------------------------------------------------------------------- /site/tests/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rocket_guide_tests" 3 | version = "0.5.0-rc.1" 4 | workspace = "../../" 5 | edition = "2018" 6 | publish = false 7 | 8 | [dependencies] 9 | rocket = { path = "../../core/lib", features = ["secrets"] } 10 | 11 | [dev-dependencies] 12 | rocket = { path = "../../core/lib", features = ["secrets", "json"] } 13 | serde = { version = "1.0", features = ["derive"] } 14 | rand = "0.8" 15 | figment = { version = "0.10", features = ["toml", "env"] } 16 | 17 | [dev-dependencies.rocket_dyn_templates] 18 | path = "../../contrib/dyn_templates" 19 | features = ["tera"] 20 | 21 | [dev-dependencies.rocket_sync_db_pools] 22 | path = "../../contrib/sync_db_pools/lib" 23 | features = ["diesel_sqlite_pool"] 24 | -------------------------------------------------------------------------------- /examples/cookies/templates/message.html.hbs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Rocket: Cookie Message 7 | 8 | 9 |

Rocket Cookie Message

10 | {{#if message }} 11 |

{{message}}

12 | {{else}} 13 |

No message yet.

14 | {{/if}} 15 | 16 |
17 | 19 |

20 |
21 | 22 | Home 23 | 24 | 25 | -------------------------------------------------------------------------------- /examples/testing/src/main.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] extern crate rocket; 2 | 3 | mod async_required; 4 | 5 | #[get("/")] 6 | fn hello() -> &'static str { 7 | "Hello, world!" 8 | } 9 | 10 | #[launch] 11 | fn rocket() -> _ { 12 | async_required::rocket().mount("/", routes![hello]) 13 | } 14 | 15 | #[cfg(test)] 16 | mod test { 17 | use super::rocket; 18 | use rocket::http::Status; 19 | 20 | #[test] 21 | fn test_hello() { 22 | use rocket::local::blocking::Client; 23 | 24 | let client = Client::tracked(rocket()).unwrap(); 25 | let response = client.get("/").dispatch(); 26 | assert_eq!(response.status(), Status::Ok); 27 | assert_eq!(response.into_string(), Some("Hello, world!".into())); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail/synchronize.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | # Symlinks all of the tests in this directory with those in sibling 5 | # `ui-fail-stable` and `ui-fail-nightly` directories. 6 | 7 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 8 | 9 | stable="${SCRIPT_DIR}/../ui-fail-stable" 10 | nightly="${SCRIPT_DIR}/../ui-fail-nightly" 11 | anchor="$(basename ${SCRIPT_DIR})" 12 | 13 | echo ":: Synchronizing..." 14 | echo " stable: ${stable}" 15 | echo " nightly: ${nightly}" 16 | echo " anchor: ${anchor}" 17 | 18 | for dir in "${stable}" "${nightly}"; do 19 | find "${dir}" -type l -delete 20 | 21 | for file in "${SCRIPT_DIR}"/*.rs; do 22 | ln -s "../${anchor}/$(basename $file)" "${dir}/" 23 | done 24 | done 25 | -------------------------------------------------------------------------------- /examples/serialization/src/msgpack.rs: -------------------------------------------------------------------------------- 1 | use rocket::serde::{Serialize, Deserialize, msgpack::MsgPack}; 2 | 3 | #[derive(Serialize, Deserialize)] 4 | #[serde(crate = "rocket::serde")] 5 | struct Message<'r> { 6 | id: usize, 7 | message: &'r str 8 | } 9 | 10 | #[get("/", format = "msgpack")] 11 | fn get(id: usize) -> MsgPack> { 12 | MsgPack(Message { id, message: "Hello, world!", }) 13 | } 14 | 15 | #[post("/", data = "", format = "msgpack")] 16 | fn echo(data: MsgPack>) -> &str { 17 | data.message 18 | } 19 | 20 | pub fn stage() -> rocket::fairing::AdHoc { 21 | rocket::fairing::AdHoc::on_ignite("MessagePack", |rocket| async { 22 | rocket.mount("/msgpack", routes![echo, get]) 23 | }) 24 | } 25 | -------------------------------------------------------------------------------- /examples/state/src/managed_queue.rs: -------------------------------------------------------------------------------- 1 | use rocket::State; 2 | use rocket::fairing::AdHoc; 3 | use rocket::http::Status; 4 | 5 | struct Tx(flume::Sender); 6 | struct Rx(flume::Receiver); 7 | 8 | #[put("/push?")] 9 | fn push(event: String, tx: &State) -> Result<(), Status> { 10 | tx.0.try_send(event).map_err(|_| Status::ServiceUnavailable) 11 | } 12 | 13 | #[get("/pop")] 14 | fn pop(rx: &State) -> Option { 15 | rx.0.try_recv().ok() 16 | } 17 | 18 | pub fn stage() -> AdHoc { 19 | AdHoc::on_ignite("Managed Queue", |rocket| async { 20 | let (tx, rx) = flume::bounded(32); 21 | rocket.mount("/queue", routes![push, pop]) 22 | .manage(Tx(tx)) 23 | .manage(Rx(rx)) 24 | }) 25 | } 26 | -------------------------------------------------------------------------------- /contrib/sync_db_pools/codegen/tests/ui-fail/database-syntax.rs: -------------------------------------------------------------------------------- 1 | use rocket_sync_db_pools::database; 2 | 3 | #[allow(unused_imports)] 4 | use rocket_sync_db_pools::diesel; 5 | 6 | #[database] 7 | struct A(diesel::SqliteConnection); 8 | 9 | #[database(1)] 10 | struct B(diesel::SqliteConnection); 11 | 12 | #[database(123)] 13 | struct C(diesel::SqliteConnection); 14 | 15 | #[database("hello" "hi")] 16 | struct D(diesel::SqliteConnection); 17 | 18 | #[database("test")] 19 | enum Foo { } 20 | 21 | #[database("test")] 22 | struct Bar(diesel::SqliteConnection, diesel::SqliteConnection); 23 | 24 | #[database("test")] 25 | union Baz { } 26 | 27 | #[database("test")] 28 | struct E<'r>(&'r str); 29 | 30 | #[database("test")] 31 | struct F(T); 32 | 33 | fn main() { } 34 | -------------------------------------------------------------------------------- /core/lib/tests/redirect_from_catcher-issue-113.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] extern crate rocket; 2 | 3 | use rocket::response::Redirect; 4 | 5 | #[catch(404)] 6 | fn not_found() -> Redirect { 7 | Redirect::to("/") 8 | } 9 | 10 | mod tests { 11 | use super::*; 12 | use rocket::local::blocking::Client; 13 | use rocket::http::Status; 14 | 15 | #[test] 16 | fn error_catcher_redirect() { 17 | let client = Client::debug(rocket::build().register("/", catchers![not_found])).unwrap(); 18 | let response = client.get("/unknown").dispatch(); 19 | 20 | let location: Vec<_> = response.headers().get("location").collect(); 21 | assert_eq!(response.status(), Status::SeeOther); 22 | assert_eq!(location, vec!["/"]); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail-stable/from_form_type_errors.stderr: -------------------------------------------------------------------------------- 1 | error[E0277]: the trait bound `Unknown: FromFormField<'_>` is not satisfied 2 | --> $DIR/from_form_type_errors.rs:7:12 3 | | 4 | 7 | field: Unknown, 5 | | ^^^^^^^ the trait `FromFormField<'_>` is not implemented for `Unknown` 6 | | 7 | = note: required because of the requirements on the impl of `FromForm<'r>` for `Unknown` 8 | 9 | error[E0277]: the trait bound `Foo: FromFormField<'_>` is not satisfied 10 | --> $DIR/from_form_type_errors.rs:14:12 11 | | 12 | 14 | field: Foo, 13 | | ^^^ the trait `FromFormField<'_>` is not implemented for `Foo` 14 | | 15 | = note: required because of the requirements on the impl of `FromForm<'r>` for `Foo` 16 | -------------------------------------------------------------------------------- /contrib/db_pools/codegen/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rocket_db_pools_codegen" 3 | version = "0.1.0-rc" 4 | authors = ["Sergio Benitez ", "Jeb Rosen "] 5 | description = "Procedural macros for rocket_db_pools." 6 | repository = "https://github.com/SergioBenitez/Rocket/contrib/db_pools" 7 | readme = "../README.md" 8 | keywords = ["rocket", "framework", "database", "pools"] 9 | license = "MIT OR Apache-2.0" 10 | edition = "2018" 11 | 12 | [lib] 13 | proc-macro = true 14 | 15 | [dependencies] 16 | devise = "0.3" 17 | quote = "1" 18 | 19 | [dev-dependencies] 20 | rocket = { path = "../../../core/lib", default-features = false } 21 | rocket_db_pools = { path = "../lib", features = ["deadpool_postgres"] } 22 | trybuild = "1.0" 23 | version_check = "0.9" 24 | -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail-nightly/from_form_type_errors.stderr: -------------------------------------------------------------------------------- 1 | error[E0277]: the trait bound `Unknown: FromFormField<'_>` is not satisfied 2 | --> $DIR/from_form_type_errors.rs:7:12 3 | | 4 | 7 | field: Unknown, 5 | | ^^^^^^^ the trait `FromFormField<'_>` is not implemented for `Unknown` 6 | | 7 | = note: required because of the requirements on the impl of `FromForm<'r>` for `Unknown` 8 | 9 | error[E0277]: the trait bound `Foo: FromFormField<'_>` is not satisfied 10 | --> $DIR/from_form_type_errors.rs:14:12 11 | | 12 | 14 | field: Foo, 13 | | ^^^^^^^^^^ the trait `FromFormField<'_>` is not implemented for `Foo` 14 | | 15 | = note: required because of the requirements on the impl of `FromForm<'r>` for `Foo` 16 | -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail/uri_display.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] extern crate rocket; 2 | 3 | #[derive(UriDisplayQuery)] 4 | struct Foo1; 5 | 6 | #[derive(UriDisplayQuery)] 7 | struct Foo2(); 8 | 9 | #[derive(UriDisplayQuery)] 10 | enum Foo3 { } 11 | 12 | #[derive(UriDisplayQuery)] 13 | enum Foo4 { 14 | Variant, 15 | } 16 | 17 | #[derive(UriDisplayQuery)] 18 | struct Foo5(String, String); 19 | 20 | #[derive(UriDisplayQuery)] 21 | struct Foo6 { 22 | #[field(name = 123)] 23 | field: String, 24 | } 25 | 26 | #[derive(UriDisplayPath)] 27 | struct Foo7(String, usize); 28 | 29 | #[derive(UriDisplayPath)] 30 | struct Foo8; 31 | 32 | #[derive(UriDisplayPath)] 33 | enum Foo9 { } 34 | 35 | #[derive(UriDisplayPath)] 36 | struct Foo10 { 37 | named: usize 38 | } 39 | 40 | fn main() { } 41 | -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail/uri_display_type_errors.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] extern crate rocket; 2 | 3 | struct BadType; 4 | 5 | #[derive(UriDisplayQuery)] 6 | struct Bar1(BadType); 7 | 8 | #[derive(UriDisplayQuery)] 9 | struct Bar2 { 10 | field: BadType, 11 | } 12 | 13 | #[derive(UriDisplayQuery)] 14 | struct Bar3 { 15 | field: String, 16 | bad: BadType, 17 | } 18 | 19 | #[derive(UriDisplayQuery)] 20 | enum Bar4 { 21 | Inner(BadType), 22 | } 23 | 24 | #[derive(UriDisplayQuery)] 25 | enum Bar5 { 26 | Inner { 27 | field: BadType, 28 | }, 29 | } 30 | 31 | #[derive(UriDisplayQuery)] 32 | enum Bar6 { 33 | Inner { 34 | field: String, 35 | other: BadType, 36 | }, 37 | } 38 | 39 | #[derive(UriDisplayPath)] 40 | struct Baz(BadType); 41 | 42 | fn main() { } 43 | -------------------------------------------------------------------------------- /core/lib/src/route/segment.rs: -------------------------------------------------------------------------------- 1 | use crate::http::RawStr; 2 | 3 | #[derive(Debug, Clone)] 4 | pub struct Segment { 5 | pub value: String, 6 | pub dynamic: bool, 7 | pub trailing: bool, 8 | } 9 | 10 | impl Segment { 11 | pub fn from(segment: &RawStr) -> Self { 12 | let mut value = segment; 13 | let mut dynamic = false; 14 | let mut trailing = false; 15 | 16 | if segment.starts_with('<') && segment.ends_with('>') { 17 | dynamic = true; 18 | value = &segment[1..(segment.len() - 1)]; 19 | 20 | if value.ends_with("..") { 21 | trailing = true; 22 | value = &value[..(value.len() - 2)]; 23 | } 24 | } 25 | 26 | Segment { value: value.to_string(), dynamic, trailing } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /core/lib/tests/local-client-json.rs: -------------------------------------------------------------------------------- 1 | #![cfg(feature = "json")] 2 | 3 | #[macro_use] extern crate rocket; 4 | 5 | use rocket::serde::json::Json; 6 | 7 | #[get("/int")] fn int() -> Json { Json(5) } 8 | #[get("/nil")] fn nil() -> Json<()> { Json(()) } 9 | 10 | #[async_test] 11 | async fn async_json_works() { 12 | use rocket::local::asynchronous::Client; 13 | 14 | let client = Client::debug_with(routes![int, nil]).await.unwrap(); 15 | 16 | let int0 = client.get("/int").dispatch().await.into_json::().await; 17 | let int1 = client.get("/int").dispatch().await.into_json::().await; 18 | 19 | assert_eq!(int0, Some(5)); 20 | assert_eq!(int1, Some(5)); 21 | 22 | let nil0 = client.get("/nil").dispatch().await.into_json::<()>().await; 23 | assert_eq!(nil0, Some(())); 24 | } 25 | -------------------------------------------------------------------------------- /examples/config/Rocket.toml: -------------------------------------------------------------------------------- 1 | # Except for the secret key, none of these are actually needed; Rocket has sane 2 | # defaults. We show all of them here explicitly for demonstrative purposes. 3 | 4 | [default.limits] 5 | forms = "64 kB" 6 | json = "1 MiB" 7 | msgpack = "2 MiB" 8 | "file/jpg" = "5 MiB" 9 | 10 | [default] 11 | key = "a default app-key" 12 | extra = false 13 | ident = "Rocket" 14 | 15 | [debug] 16 | address = "127.0.0.1" 17 | port = 8000 18 | workers = 1 19 | keep_alive = 0 20 | log_level = "normal" 21 | 22 | [release] 23 | address = "127.0.0.1" 24 | port = 8000 25 | workers = 12 26 | keep_alive = 5 27 | log_level = "critical" 28 | # don't use this key! generate your own and keep it private! 29 | secret_key = "hPRYyVRiMyxpw5sBB1XeCMN1kFsDCqKvBi2QJxBVHQk=" 30 | key = "a release app-key" 31 | extra = false 32 | -------------------------------------------------------------------------------- /examples/forms/templates/success.html.tera: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Rocket Form Example 7 | 8 | 15 | 16 | 17 |
18 |

Success!

19 | 20 |

Submission Data

21 | 22 |
    23 | {% for key, value in values %} 24 |
  • {{ key }} - {{ value }}
  • 25 | {% endfor %} 26 |
27 | 28 | < Submit Another 29 | 30 | 31 | -------------------------------------------------------------------------------- /core/lib/tests/session-cookies-issue-1506.rs: -------------------------------------------------------------------------------- 1 | #![cfg(feature = "secrets")] 2 | 3 | use rocket::http::{CookieJar, Cookie}; 4 | 5 | #[rocket::get("/")] 6 | fn index(jar: &CookieJar<'_>) { 7 | let session_cookie = Cookie::build("key", "value").expires(None); 8 | jar.add_private(session_cookie.finish()); 9 | } 10 | 11 | mod test_session_cookies { 12 | use super::*; 13 | use rocket::local::blocking::Client; 14 | 15 | #[test] 16 | fn session_cookie_is_session() { 17 | let rocket = rocket::build().mount("/", rocket::routes![index]); 18 | let client = Client::debug(rocket).unwrap(); 19 | 20 | let response = client.get("/").dispatch(); 21 | let cookie = response.cookies().get_private("key").unwrap(); 22 | assert_eq!(cookie.expires_datetime(), None); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /core/lib/fuzz/targets/uri-parsing.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | 3 | use rocket::http::uri::*; 4 | use libfuzzer_sys::fuzz_target; 5 | 6 | fn fuzz(data: &str) { 7 | // Fuzz the top-level parser. 8 | if let Ok(uri) = Uri::parse_any(data) { 9 | // Ensure Uri::parse::() => T::parse(). 10 | match uri { 11 | Uri::Asterisk(_) => { Asterisk::parse(data).expect("Asterisk"); }, 12 | Uri::Origin(_) => { Origin::parse(data).expect("Origin"); }, 13 | Uri::Authority(_) => { Authority::parse(data).expect("Authority"); }, 14 | Uri::Absolute(_) => { Absolute::parse(data).expect("Absolute"); }, 15 | Uri::Reference(_) => { Reference::parse(data).expect("Reference"); }, 16 | } 17 | } 18 | } 19 | 20 | fuzz_target!(|data: &[u8]| { 21 | let _ = std::str::from_utf8(data).map(fuzz); 22 | }); 23 | -------------------------------------------------------------------------------- /examples/static-files/src/main.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] mod tests; 2 | 3 | use rocket::fs::{FileServer, relative}; 4 | 5 | // If we wanted or needed to serve files manually, we'd use `NamedFile`. Always 6 | // prefer to use `FileServer`! 7 | mod manual { 8 | use std::path::{PathBuf, Path}; 9 | use rocket::fs::NamedFile; 10 | 11 | #[rocket::get("/second/")] 12 | pub async fn second(path: PathBuf) -> Option { 13 | let mut path = Path::new(super::relative!("static")).join(path); 14 | if path.is_dir() { 15 | path.push("index.html"); 16 | } 17 | 18 | NamedFile::open(path).await.ok() 19 | } 20 | } 21 | 22 | #[rocket::launch] 23 | fn rocket() -> _ { 24 | rocket::build() 25 | .mount("/", rocket::routes![manual::second]) 26 | .mount("/", FileServer::from(relative!("static"))) 27 | } 28 | -------------------------------------------------------------------------------- /contrib/db_pools/codegen/tests/ui-fail/database-syntax.rs: -------------------------------------------------------------------------------- 1 | use rocket_db_pools::{deadpool_postgres, Database}; 2 | 3 | #[derive(Database)] 4 | #[database(123)] 5 | struct A(deadpool_postgres::Pool); 6 | 7 | #[derive(Database)] 8 | #[database("some-name", "another")] 9 | struct B(deadpool_postgres::Pool); 10 | 11 | #[derive(Database)] 12 | #[database("some-name", name = "another")] 13 | struct C(deadpool_postgres::Pool); 14 | 15 | #[derive(Database)] 16 | #[database("foo")] 17 | enum D { } 18 | 19 | #[derive(Database)] 20 | struct E(deadpool_postgres::Pool); 21 | 22 | #[derive(Database)] 23 | #[database("foo")] 24 | struct F; 25 | 26 | #[derive(Database)] 27 | #[database("foo")] 28 | struct G(deadpool_postgres::Pool, deadpool_postgres::Pool); 29 | 30 | #[derive(Database)] 31 | #[database("foo")] 32 | struct H { 33 | foo: deadpool_postgres::Pool, 34 | } 35 | 36 | fn main() { } 37 | -------------------------------------------------------------------------------- /contrib/db_pools/codegen/tests/ui-fail-stable/database-types.stderr: -------------------------------------------------------------------------------- 1 | error[E0277]: the trait bound `Unknown: Pool` is not satisfied 2 | --> $DIR/database-types.rs:7:10 3 | | 4 | 7 | struct A(Unknown); 5 | | ^^^^^^^ the trait `Pool` is not implemented for `Unknown` 6 | | 7 | ::: $WORKSPACE/contrib/db_pools/lib/src/database.rs 8 | | 9 | | type Pool: Pool; 10 | | ---- required by this bound in `rocket_db_pools::Database::Pool` 11 | 12 | error[E0277]: the trait bound `Vec: Pool` is not satisfied 13 | --> $DIR/database-types.rs:11:10 14 | | 15 | 11 | struct B(Vec); 16 | | ^^^ the trait `Pool` is not implemented for `Vec` 17 | | 18 | ::: $WORKSPACE/contrib/db_pools/lib/src/database.rs 19 | | 20 | | type Pool: Pool; 21 | | ---- required by this bound in `rocket_db_pools::Database::Pool` 22 | -------------------------------------------------------------------------------- /core/lib/fuzz/targets/uri-roundtrip.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | 3 | use rocket::http::uri::*; 4 | use libfuzzer_sys::fuzz_target; 5 | 6 | fn fuzz(data: &str) { 7 | if let Ok(uri) = Uri::parse_any(data) { 8 | let string = uri.to_string(); 9 | let _ = match uri { 10 | Uri::Asterisk(_) => Asterisk::parse_owned(string).expect("Asterisk").to_string(), 11 | Uri::Origin(_) => Origin::parse_owned(string).expect("Origin").to_string(), 12 | Uri::Authority(_) => Authority::parse_owned(string).expect("Authority").to_string(), 13 | Uri::Absolute(_) => Absolute::parse_owned(string).expect("Absolute").to_string(), 14 | Uri::Reference(_) => Reference::parse_owned(string).expect("Reference").to_string(), 15 | }; 16 | } 17 | } 18 | 19 | fuzz_target!(|data: &[u8]| { 20 | let _ = std::str::from_utf8(data).map(fuzz); 21 | }); 22 | -------------------------------------------------------------------------------- /core/lib/tests/can-launch-tls.rs: -------------------------------------------------------------------------------- 1 | #![cfg(feature = "tls")] 2 | 3 | use rocket::fs::relative; 4 | use rocket::config::{Config, TlsConfig, CipherSuite}; 5 | use rocket::local::asynchronous::Client; 6 | 7 | #[rocket::async_test] 8 | async fn can_launch_tls() { 9 | let cert_path = relative!("examples/tls/private/rsa_sha256_cert.pem"); 10 | let key_path = relative!("examples/tls/private/rsa_sha256_key.pem"); 11 | 12 | let tls = TlsConfig::from_paths(cert_path, key_path) 13 | .with_ciphers([ 14 | CipherSuite::TLS_AES_128_GCM_SHA256, 15 | CipherSuite::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 16 | ]); 17 | 18 | let rocket = rocket::custom(Config { tls: Some(tls), ..Config::debug_default() }); 19 | let client = Client::debug(rocket).await.unwrap(); 20 | 21 | client.rocket().shutdown().notify(); 22 | client.rocket().shutdown().await; 23 | } 24 | -------------------------------------------------------------------------------- /examples/cookies/src/message.rs: -------------------------------------------------------------------------------- 1 | use rocket::form::Form; 2 | use rocket::response::Redirect; 3 | use rocket::http::{Cookie, CookieJar}; 4 | use rocket_dyn_templates::{Template, context}; 5 | 6 | #[macro_export] 7 | macro_rules! message_uri { 8 | ($($t:tt)*) => (rocket::uri!("/message", $crate::message:: $($t)*)) 9 | } 10 | 11 | pub use message_uri as uri; 12 | 13 | #[post("/", data = "")] 14 | fn submit(cookies: &CookieJar<'_>, message: Form<&str>) -> Redirect { 15 | cookies.add(Cookie::new("message", message.to_string())); 16 | Redirect::to(uri!(index)) 17 | } 18 | 19 | #[get("/")] 20 | fn index(cookies: &CookieJar<'_>) -> Template { 21 | let cookie = cookies.get("message"); 22 | 23 | Template::render("message", context! { 24 | message: cookie.map(|c| c.value()), 25 | }) 26 | } 27 | 28 | pub fn routes() -> Vec { 29 | routes![submit, index] 30 | } 31 | -------------------------------------------------------------------------------- /examples/config/src/main.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] extern crate rocket; 2 | 3 | #[cfg(test)] mod tests; 4 | 5 | use rocket::{State, Config}; 6 | use rocket::fairing::AdHoc; 7 | use rocket::serde::Deserialize; 8 | 9 | #[derive(Debug, Deserialize)] 10 | #[serde(crate = "rocket::serde")] 11 | struct AppConfig { 12 | key: String, 13 | port: u16 14 | } 15 | 16 | #[get("/")] 17 | fn read_config(rocket_config: &Config, app_config: &State) -> String { 18 | format!("{:#?}\n{:#?}", app_config, rocket_config) 19 | } 20 | 21 | // See Rocket.toml file. Running this server will print the config. Try running 22 | // with `ROCKET_PROFILE=release` manually by setting the environment variable 23 | // and automatically by compiling with `--release`. 24 | #[launch] 25 | fn rocket() -> _ { 26 | rocket::build() 27 | .mount("/", routes![read_config]) 28 | .attach(AdHoc::config::()) 29 | } 30 | -------------------------------------------------------------------------------- /core/lib/tests/tls-config-from-source-1503.rs: -------------------------------------------------------------------------------- 1 | #![cfg(feature = "tls")] 2 | 3 | macro_rules! relative { 4 | ($path:expr) => { 5 | std::path::Path::new(concat!(env!("CARGO_MANIFEST_DIR"), "/", $path)) 6 | }; 7 | } 8 | 9 | #[test] 10 | fn tls_config_from_source() { 11 | use rocket::config::{Config, TlsConfig}; 12 | use rocket::figment::Figment; 13 | 14 | let cert_path = relative!("examples/tls/private/cert.pem"); 15 | let key_path = relative!("examples/tls/private/key.pem"); 16 | 17 | let rocket_config = Config { 18 | tls: Some(TlsConfig::from_paths(cert_path, key_path)), 19 | ..Default::default() 20 | }; 21 | 22 | let config: Config = Figment::from(rocket_config).extract().unwrap(); 23 | let tls = config.tls.expect("have TLS config"); 24 | assert_eq!(tls.certs().unwrap_left(), cert_path); 25 | assert_eq!(tls.key().unwrap_left(), key_path); 26 | } 27 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/suggestion.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Suggestion 3 | about: Suggest a change or improvement to existing functionality 4 | title: '' 5 | labels: suggestion 6 | assignees: '' 7 | --- 8 | 9 | **Existing Functionality** 10 | 11 | A clear and concise description of existing functionality and why it is insufficient. Examples: 12 | 13 | - "I frequently want to do X, but Rocket makes it hard. It would be nice if..." 14 | - "Feature Z exists, but it has these drawbacks. What if..." 15 | 16 | **Suggested Changes** 17 | 18 | If you have a conrete idea for an improvement, propose it with a clear and concise description. 19 | 20 | **Alternatives Considered** 21 | 22 | A clear and concise description of any alternative solutions using existing features or new features you've considered. 23 | 24 | **Additional Context** 25 | 26 | Add any other context here, for example, descriptions of elegant solutions in other software. 27 | -------------------------------------------------------------------------------- /examples/templating/src/main.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] extern crate rocket; 2 | 3 | mod hbs; 4 | mod tera; 5 | 6 | #[cfg(test)] mod tests; 7 | 8 | use rocket::response::content::RawHtml; 9 | use rocket_dyn_templates::Template; 10 | 11 | #[get("/")] 12 | fn index() -> RawHtml<&'static str> { 13 | RawHtml(r#"See Tera or Handlebars."#) 14 | } 15 | 16 | #[launch] 17 | fn rocket() -> _ { 18 | rocket::build() 19 | .mount("/", routes![index]) 20 | .mount("/tera", routes![tera::index, tera::hello, tera::about]) 21 | .mount("/hbs", routes![hbs::index, hbs::hello, hbs::about]) 22 | .register("/hbs", catchers![hbs::not_found]) 23 | .register("/tera", catchers![tera::not_found]) 24 | .attach(Template::custom(|engines| { 25 | hbs::customize(&mut engines.handlebars); 26 | tera::customize(&mut engines.tera); 27 | })) 28 | } 29 | -------------------------------------------------------------------------------- /examples/cookies/templates/login.html.hbs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Rocket: Sessions 7 | 8 | 9 |

Rocket Session: Please Login

10 | 11 |

Please login to continue.

12 | 13 | {{#if message}} 14 |

{{#if kind}}{{kind}}: {{/if}}{{ message }}

15 | {{/if}} 16 | 17 |
18 | 19 | 20 | 21 | 22 |

23 |
24 | 25 | Home 26 | 27 | 28 | -------------------------------------------------------------------------------- /core/lib/tests/responder_lifetime-issue-345.rs: -------------------------------------------------------------------------------- 1 | #![allow(dead_code)] // This test is only here so that we can ensure it compiles. 2 | 3 | #[macro_use] extern crate rocket; 4 | 5 | use rocket::{Request, State}; 6 | use rocket::response::{Responder, Result}; 7 | 8 | struct SomeState; 9 | 10 | pub struct CustomResponder<'r, R> { 11 | responder: R, 12 | state: &'r SomeState, 13 | } 14 | 15 | impl<'r, 'o: 'r, R: Responder<'r, 'o>> Responder<'r, 'o> for CustomResponder<'r, R> { 16 | fn respond_to(self, req: &'r Request<'_>) -> Result<'o> { 17 | self.responder.respond_to(req) 18 | } 19 | } 20 | 21 | #[get("/unit_state")] 22 | fn unit_state(state: &State) -> CustomResponder<()> { 23 | CustomResponder { responder: (), state: &*state } 24 | } 25 | 26 | #[get("/string_state")] 27 | fn string_state(state: &State) -> CustomResponder { 28 | CustomResponder { responder: "".to_string(), state: &*state } 29 | } 30 | -------------------------------------------------------------------------------- /contrib/sync_db_pools/lib/src/error.rs: -------------------------------------------------------------------------------- 1 | use rocket::figment; 2 | 3 | /// A wrapper around `r2d2::Error`s or a custom database error type. 4 | /// 5 | /// This type is only relevant to implementors of the [`Poolable`] trait. See 6 | /// the [`Poolable`] documentation for more information on how to use this type. 7 | /// 8 | /// [`Poolable`]: crate::Poolable 9 | #[derive(Debug)] 10 | pub enum Error { 11 | /// A custom error of type `T`. 12 | Custom(T), 13 | /// An error occurred while initializing an `r2d2` pool. 14 | Pool(r2d2::Error), 15 | /// An error occurred while extracting a `figment` configuration. 16 | Config(figment::Error), 17 | } 18 | 19 | impl From for Error { 20 | fn from(error: figment::Error) -> Self { 21 | Error::Config(error) 22 | } 23 | } 24 | 25 | impl From for Error { 26 | fn from(error: r2d2::Error) -> Self { 27 | Error::Pool(error) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /core/lib/src/mtls.rs: -------------------------------------------------------------------------------- 1 | //! Support for mutual TLS client certificates. 2 | //! 3 | //! For details on how to configure mutual TLS, see 4 | //! [`MutualTls`](crate::config::MutualTls) and the [TLS 5 | //! guide](https://rocket.rs/v0.5-rc/guide/configuration/#tls). See 6 | //! [`Certificate`] for a request guard that validated, verifies, and retrieves 7 | //! client certificates. 8 | 9 | #[doc(inline)] 10 | pub use crate::http::tls::mtls::*; 11 | 12 | use crate::request::{Request, FromRequest, Outcome}; 13 | use crate::outcome::{try_outcome, IntoOutcome}; 14 | use crate::http::Status; 15 | 16 | #[crate::async_trait] 17 | impl<'r> FromRequest<'r> for Certificate<'r> { 18 | type Error = Error; 19 | 20 | async fn from_request(req: &'r Request<'_>) -> Outcome { 21 | let certs = try_outcome!(req.connection.client_certificates.as_ref().or_forward(())); 22 | Certificate::parse(certs).into_outcome(Status::Unauthorized) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /contrib/db_pools/codegen/tests/ui-fail-nightly/database-types.stderr: -------------------------------------------------------------------------------- 1 | error[E0277]: the trait bound `Unknown: Pool` is not satisfied 2 | --> $DIR/database-types.rs:7:10 3 | | 4 | 7 | struct A(Unknown); 5 | | ^^^^^^^ the trait `Pool` is not implemented for `Unknown` 6 | | 7 | note: required by a bound in `rocket_db_pools::Database::Pool` 8 | --> $DIR/database.rs:41:16 9 | | 10 | 41 | type Pool: Pool; 11 | | ^^^^ required by this bound in `rocket_db_pools::Database::Pool` 12 | 13 | error[E0277]: the trait bound `Vec: Pool` is not satisfied 14 | --> $DIR/database-types.rs:11:10 15 | | 16 | 11 | struct B(Vec); 17 | | ^^^^^^^^ the trait `Pool` is not implemented for `Vec` 18 | | 19 | note: required by a bound in `rocket_db_pools::Database::Pool` 20 | --> $DIR/database.rs:41:16 21 | | 22 | 41 | type Pool: Pool; 23 | | ^^^^ required by this bound in `rocket_db_pools::Database::Pool` 24 | -------------------------------------------------------------------------------- /core/lib/tests/absolute-uris-okay-issue-443.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] extern crate rocket; 2 | 3 | use rocket::response::Redirect; 4 | 5 | #[get("/http")] 6 | fn http() -> Redirect { 7 | Redirect::to(uri!("http://rocket.rs")) 8 | } 9 | 10 | #[get("/rocket")] 11 | fn redirect() -> Redirect { 12 | Redirect::to("https://rocket.rs:80") 13 | } 14 | 15 | mod test_absolute_uris_okay { 16 | use super::*; 17 | use rocket::local::blocking::Client; 18 | 19 | #[test] 20 | fn redirect_works() { 21 | let client = Client::debug_with(routes![http, redirect]).unwrap(); 22 | 23 | let response = client.get(uri!(http)).dispatch(); 24 | let location = response.headers().get_one("Location"); 25 | assert_eq!(location, Some("http://rocket.rs")); 26 | 27 | let response = client.get(uri!(redirect)).dispatch(); 28 | let location = response.headers().get_one("Location"); 29 | assert_eq!(location, Some("https://rocket.rs:80")); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /contrib/sync_db_pools/codegen/tests/ui-fail-stable/database-types.stderr: -------------------------------------------------------------------------------- 1 | error[E0277]: the trait bound `Unknown: Poolable` is not satisfied 2 | --> $DIR/database-types.rs:6:10 3 | | 4 | 6 | struct A(Unknown); 5 | | ^^^^^^^ the trait `Poolable` is not implemented for `Unknown` 6 | | 7 | ::: $WORKSPACE/contrib/sync_db_pools/lib/src/connection.rs 8 | | 9 | | pub struct Connection { 10 | | -------- required by this bound in `rocket_sync_db_pools::Connection` 11 | 12 | error[E0277]: the trait bound `Vec: Poolable` is not satisfied 13 | --> $DIR/database-types.rs:9:10 14 | | 15 | 9 | struct B(Vec); 16 | | ^^^ the trait `Poolable` is not implemented for `Vec` 17 | | 18 | ::: $WORKSPACE/contrib/sync_db_pools/lib/src/connection.rs 19 | | 20 | | pub struct Connection { 21 | | -------- required by this bound in `rocket_sync_db_pools::Connection` 22 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug-report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug Report 3 | about: Report behavior that deviates from specification or expectation 4 | title: '' 5 | labels: triage 6 | assignees: '' 7 | --- 8 | 9 | **Description** 10 | 11 | A clear and concise description of what the bug is. This should include links to documentation that is contradicted or an explanation of why the present functionality doesn't match your expectation. 12 | 13 | **To Reproduce** 14 | 15 | How to reproduce the bug. A fully working code example (`main.rs` + `Cargo.toml`) is preferred. 16 | 17 | **Expected Behavior** 18 | 19 | A clear and concise description of what you expected to happen. 20 | 21 | **Environment:** 22 | 23 | - OS Distribution and Kernel: [e.g. Arch Linux 4.16.13, macOS 11.2.1] 24 | - Rocket Version: [e.g. 0.4.12, master@abf996b] 25 | 26 | **Additional Context** 27 | 28 | Add any other context about the problem here, for example, how you uncovered the bug or if you have ideas about what/where Rocket is going wrong. 29 | -------------------------------------------------------------------------------- /core/codegen/src/attribute/param/guard.rs: -------------------------------------------------------------------------------- 1 | use std::hash::{Hash, Hasher}; 2 | 3 | use devise::{FromMeta, MetaItem, Result}; 4 | use proc_macro2::Span; 5 | 6 | use crate::name::Name; 7 | use crate::proc_macro_ext::StringLit; 8 | use crate::http::uri; 9 | 10 | impl Dynamic { 11 | pub fn is_wild(&self) -> bool { 12 | self.value == "_" 13 | } 14 | } 15 | 16 | impl FromMeta for Dynamic { 17 | fn from_meta(meta: &MetaItem) -> Result { 18 | let string = StringLit::from_meta(meta)?; 19 | let span = string.subspan(1..string.len() + 1); 20 | 21 | // We don't allow `_`. We abuse `fmt::Query` to enforce this. 22 | Ok(Dynamic::parse::(&string, span)?) 23 | } 24 | } 25 | 26 | impl PartialEq for Dynamic { 27 | fn eq(&self, other: &Dynamic) -> bool { 28 | self.value == other.value 29 | } 30 | } 31 | 32 | impl Eq for Dynamic {} 33 | 34 | impl Hash for Dynamic { 35 | fn hash(&self, state: &mut H) { 36 | self.value.hash(state) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /core/codegen/src/attribute/entry/main.rs: -------------------------------------------------------------------------------- 1 | use super::EntryAttr; 2 | 3 | use devise::{Spanned, Result}; 4 | use devise::ext::SpanDiagnosticExt; 5 | use proc_macro2::{TokenStream, Span}; 6 | 7 | /// `#[rocket::async_main]`: calls the attributed fn inside `rocket::async_main` 8 | pub struct Main; 9 | 10 | impl EntryAttr for Main { 11 | const REQUIRES_ASYNC: bool = true; 12 | 13 | fn function(f: &mut syn::ItemFn) -> Result { 14 | let (attrs, vis, block, sig) = (&f.attrs, &f.vis, &f.block, &mut f.sig); 15 | if sig.ident != "main" { 16 | // FIXME(diag): warning! 17 | Span::call_site() 18 | .warning("attribute is typically applied to `main` function") 19 | .span_note(sig.ident.span(), "this function is not `main`") 20 | .emit_as_item_tokens(); 21 | } 22 | 23 | sig.asyncness = None; 24 | Ok(quote_spanned!(block.span() => #(#attrs)* #vis #sig { 25 | ::rocket::async_main(async move #block) 26 | })) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /scripts/mk-docs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | # 5 | # Builds the rustdocs for all of the libraries. 6 | # 7 | 8 | # Brings in: PROJECT_ROOT, EXAMPLES_DIR, LIB_DIR, CODEGEN_DIR, CONTRIB_DIR, DOC_DIR 9 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 10 | source "${SCRIPT_DIR}/config.sh" 11 | 12 | if [ "${1}" != "-d" ]; then 13 | # We need to clean-up beforehand so we don't get all of the dependencies. 14 | echo ":::: Cleaning up before documenting..." 15 | cargo clean 16 | cargo update 17 | fi 18 | 19 | # Generate the rustdocs for all of the crates. 20 | echo ":::: Generating the docs..." 21 | pushd "${PROJECT_ROOT}" > /dev/null 2>&1 22 | # Set the crate version and fill in missing doc URLs with docs.rs links. 23 | RUSTDOCFLAGS="-Zunstable-options --crate-version ${DOC_VERSION}" \ 24 | cargo doc -p rocket \ 25 | -p rocket_sync_db_pools -p rocket_dyn_templates -p rocket_db_pools \ 26 | -Zrustdoc-map --no-deps --all-features 27 | popd > /dev/null 2>&1 28 | 29 | # Blank index, for redirection. 30 | touch "${DOC_DIR}/index.html" 31 | -------------------------------------------------------------------------------- /contrib/sync_db_pools/codegen/tests/ui-fail-nightly/database-types.stderr: -------------------------------------------------------------------------------- 1 | error[E0277]: the trait bound `Unknown: Poolable` is not satisfied 2 | --> $DIR/database-types.rs:6:10 3 | | 4 | 6 | struct A(Unknown); 5 | | ^^^^^^^ the trait `Poolable` is not implemented for `Unknown` 6 | | 7 | note: required by a bound in `rocket_sync_db_pools::Connection` 8 | --> $DIR/connection.rs:44:29 9 | | 10 | 44 | pub struct Connection { 11 | | ^^^^^^^^ required by this bound in `rocket_sync_db_pools::Connection` 12 | 13 | error[E0277]: the trait bound `Vec: Poolable` is not satisfied 14 | --> $DIR/database-types.rs:9:10 15 | | 16 | 9 | struct B(Vec); 17 | | ^^^^^^^^ the trait `Poolable` is not implemented for `Vec` 18 | | 19 | note: required by a bound in `rocket_sync_db_pools::Connection` 20 | --> $DIR/connection.rs:44:29 21 | | 22 | 44 | pub struct Connection { 23 | | ^^^^^^^^ required by this bound in `rocket_sync_db_pools::Connection` 24 | -------------------------------------------------------------------------------- /core/lib/build.rs: -------------------------------------------------------------------------------- 1 | //! Ensures Rocket isn't compiled with an incompatible version of Rust. 2 | 3 | use yansi::{Paint, Color::{Red, Yellow}}; 4 | 5 | fn main() { 6 | const MIN_VERSION: &str = "1.46.0"; 7 | 8 | if let Some(version) = version_check::Version::read() { 9 | if !version.at_least(MIN_VERSION) { 10 | let msg = "Rocket requires a more recent version of rustc."; 11 | eprintln!("{} {}", Red.paint("Error:").bold(), Paint::new(msg).bold()); 12 | eprintln!("Installed version: {}", Yellow.paint(version)); 13 | eprintln!("Minimum required: {}", Yellow.paint(MIN_VERSION)); 14 | panic!("Aborting compilation due to incompatible compiler.") 15 | } 16 | } else { 17 | println!("cargo:warning=Rocket was unable to check rustc compiler compatibility."); 18 | println!("cargo:warning=Build may fail due to incompatible rustc version."); 19 | } 20 | 21 | if let Some(true) = version_check::is_feature_flaggable() { 22 | println!("cargo:rustc-cfg=nightly"); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /examples/tls/Rocket.toml: -------------------------------------------------------------------------------- 1 | # The certificate key pairs used here were generated with openssl via the 2 | # 'private/gen_certs.sh' script. 3 | # 4 | # These certificates are self-signed. As such, you will need to trust them 5 | # directly for your browser to show connections as secure. You should NEVER use 6 | # these certificate/key pairs. They are here for DEMONSTRATION PURPOSES ONLY. 7 | 8 | [default.tls] 9 | certs = "private/rsa_sha256_cert.pem" 10 | key = "private/rsa_sha256_key.pem" 11 | 12 | [default.tls.mutual] 13 | ca_certs = "private/ca_cert.pem" 14 | mandatory = false 15 | 16 | [rsa_sha256.tls] 17 | certs = "private/rsa_sha256_cert.pem" 18 | key = "private/rsa_sha256_key.pem" 19 | 20 | [ecdsa_nistp256_sha256.tls] 21 | certs = "private/ecdsa_nistp256_sha256_cert.pem" 22 | key = "private/ecdsa_nistp256_sha256_key_pkcs8.pem" 23 | 24 | [ecdsa_nistp384_sha384.tls] 25 | certs = "private/ecdsa_nistp384_sha384_cert.pem" 26 | key = "private/ecdsa_nistp384_sha384_key_pkcs8.pem" 27 | 28 | [ed25519.tls] 29 | certs = "private/ed25519_cert.pem" 30 | key = "private/ed25519_key.pem" 31 | -------------------------------------------------------------------------------- /core/http/src/uri/error.rs: -------------------------------------------------------------------------------- 1 | //! Errors arising from parsing invalid URIs. 2 | 3 | use std::fmt; 4 | 5 | pub use crate::parse::uri::Error; 6 | 7 | /// The error type returned when a URI conversion fails. 8 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] 9 | pub struct TryFromUriError(pub(crate) ()); 10 | 11 | impl fmt::Display for TryFromUriError { 12 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 13 | "invalid conversion from general to specific URI variant".fmt(f) 14 | } 15 | } 16 | 17 | /// An error interpreting a segment as a [`PathBuf`] component in 18 | /// [`Segments::to_path_buf()`]. 19 | /// 20 | /// [`PathBuf`]: std::path::PathBuf 21 | /// [`Segments::to_path_buf()`]: crate::uri::Segments::to_path_buf() 22 | #[derive(Debug, PartialEq, Eq, Clone)] 23 | pub enum PathError { 24 | /// The segment started with the wrapped invalid character. 25 | BadStart(char), 26 | /// The segment contained the wrapped invalid character. 27 | BadChar(char), 28 | /// The segment ended with the wrapped invalid character. 29 | BadEnd(char), 30 | } 31 | -------------------------------------------------------------------------------- /benchmarks/static/rust-lang.routes: -------------------------------------------------------------------------------- 1 | GET / (index) 2 | GET / (category) 3 | GET /governance (governance) 4 | GET /governance/
/ [2] (team) 5 | GET /production/users (production) 6 | GET /sponsors (sponsors) 7 | GET // [4] (subject) 8 | GET /static/ (files) 9 | GET /robots.txt (robots_txt) 10 | GET /logos/ (logos) 11 | GET /components/<_file..> (components) 12 | GET / [3] (index_locale) 13 | GET // [11] (category_locale) 14 | GET //governance [10] (governance_locale) 15 | GET //governance/
/ [12] (team_locale) 16 | GET //production/users [10] (production_locale) 17 | GET //sponsors [10] (sponsors_locale) 18 | GET /// [14] (subject_locale) 19 | GET //components/<_file..> [12] (components_locale) 20 | GET / [19] (redirect) 21 | GET /pdfs/ (redirect_pdfs) 22 | GET /en-US (redirect_bare_en_us) 23 | GET /<_locale> [20] (redirect_bare_locale) 24 | GET /en-US/ (redirect_en_us) 25 | GET /<_locale>/ [20] (redirect_locale) 26 | -------------------------------------------------------------------------------- /core/lib/tests/route_guard.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] extern crate rocket; 2 | 3 | use std::path::{Path, PathBuf}; 4 | use rocket::http::ext::Normalize; 5 | use rocket::Route; 6 | 7 | #[get("/")] 8 | fn files(route: &Route, path: PathBuf) -> String { 9 | Path::new(route.uri.base()).join(path).normalized_str().to_string() 10 | } 11 | 12 | mod route_guard_tests { 13 | use super::*; 14 | use rocket::local::blocking::Client; 15 | 16 | fn assert_path(client: &Client, path: &str) { 17 | let res = client.get(path).dispatch(); 18 | assert_eq!(res.into_string(), Some(path.into())); 19 | } 20 | 21 | #[test] 22 | fn check_mount_path() { 23 | let rocket = rocket::build() 24 | .mount("/first", routes![files]) 25 | .mount("/second", routes![files]); 26 | 27 | let client = Client::debug(rocket).unwrap(); 28 | assert_path(&client, "/first/some/path"); 29 | assert_path(&client, "/second/some/path"); 30 | assert_path(&client, "/first/second/b/c"); 31 | assert_path(&client, "/second/a/b/c"); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /contrib/dyn_templates/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rocket_dyn_templates" 3 | version = "0.1.0-rc.1" 4 | authors = ["Sergio Benitez "] 5 | description = "Dynamic templating engine integration for Rocket." 6 | documentation = "https://api.rocket.rs/v0.5-rc/rocket_dyn_templates/" 7 | homepage = "https://rocket.rs" 8 | repository = "https://github.com/SergioBenitez/Rocket/tree/master/contrib/dyn_templates" 9 | readme = "README.md" 10 | keywords = ["rocket", "framework", "templates", "templating", "engine"] 11 | license = "MIT OR Apache-2.0" 12 | edition = "2018" 13 | 14 | [features] 15 | tera = ["tera_"] 16 | handlebars = ["handlebars_"] 17 | 18 | [dependencies] 19 | glob = "0.3" 20 | notify = "4.0.6" 21 | normpath = "0.3" 22 | 23 | [dependencies.rocket] 24 | version = "0.5.0-rc.1" 25 | path = "../../core/lib" 26 | default-features = false 27 | 28 | [dependencies.tera_] 29 | package = "tera" 30 | version = "1.10.0" 31 | optional = true 32 | 33 | [dependencies.handlebars_] 34 | package = "handlebars" 35 | version = "4.1" 36 | optional = true 37 | 38 | [package.metadata.docs.rs] 39 | all-features = true 40 | -------------------------------------------------------------------------------- /core/codegen/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rocket_codegen" 3 | version = "0.5.0-rc.1" 4 | authors = ["Sergio Benitez "] 5 | description = "Procedural macros for the Rocket web framework." 6 | documentation = "https://api.rocket.rs/v0.5-rc/rocket_codegen/" 7 | homepage = "https://rocket.rs" 8 | repository = "https://github.com/SergioBenitez/Rocket" 9 | readme = "../../README.md" 10 | keywords = ["rocket", "web", "framework", "code", "generation"] 11 | license = "MIT OR Apache-2.0" 12 | edition = "2018" 13 | 14 | [lib] 15 | proc-macro = true 16 | 17 | [dependencies] 18 | indexmap = "1.0" 19 | quote = "1.0" 20 | syn = { version = "1.0.72", features = ["full", "visit", "visit-mut", "extra-traits"] } 21 | proc-macro2 = "1.0.27" 22 | devise = "0.3.1" 23 | rocket_http = { version = "0.5.0-rc.1", path = "../http/" } 24 | unicode-xid = "0.2" 25 | glob = "0.3" 26 | 27 | [dev-dependencies] 28 | rocket = { version = "0.5.0-rc.1", path = "../lib", features = ["json", "msgpack"] } 29 | time = { version = "0.3", features = ["macros"] } 30 | pretty_assertions = "0.7" 31 | version_check = "0.9" 32 | trybuild = "1.0" 33 | -------------------------------------------------------------------------------- /core/lib/tests/form_value_from_encoded_str-issue-1425.rs: -------------------------------------------------------------------------------- 1 | use std::net::{Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6}; 2 | 3 | use rocket::http::RawStr; 4 | use rocket::form::Form; 5 | 6 | macro_rules! assert_from_form_field_eq { 7 | ($string:literal as $T:ty, $expected:expr) => ( 8 | let value_str = RawStr::new(concat!("=", $string)); 9 | let value = Form::<$T>::parse_encoded(value_str).unwrap(); 10 | assert_eq!(value, $expected); 11 | ) 12 | } 13 | 14 | #[test] 15 | fn test_from_form_value_encoded() { 16 | assert_from_form_field_eq!( 17 | "127.0.0.1%3A80" as SocketAddrV4, 18 | SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 80) 19 | ); 20 | 21 | assert_from_form_field_eq!( 22 | "2001%3A0db8%3A85a3%3A0000%3A0000%3A8a2e%3A0370%3A7334" as Ipv6Addr, 23 | Ipv6Addr::new(0x2001, 0x0db8, 0x85a3, 0, 0, 0x8a2e, 0x0370, 0x7334) 24 | ); 25 | 26 | assert_from_form_field_eq!( 27 | "%5B2001%3Adb8%3A%3A1%5D%3A8080" as SocketAddrV6, 28 | SocketAddrV6::new(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1), 8080, 0, 0) 29 | ); 30 | } 31 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright (c) 2016 Sergio Benitez 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of 5 | this software and associated documentation files (the "Software"), to deal in 6 | the Software without restriction, including without limitation the rights to 7 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 8 | the Software, and to permit persons to whom the Software is furnished to do so, 9 | subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 16 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 17 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 18 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /examples/serialization/src/uuid.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | 3 | use rocket::State; 4 | use rocket::serde::uuid::Uuid; 5 | 6 | // A small people mapping in managed state for the sake of this example. In a 7 | // real application this would be a database. 8 | struct People(HashMap); 9 | 10 | #[get("/people/")] 11 | fn people(id: Uuid, people: &State) -> Result { 12 | people.0.get(&id) 13 | .map(|person| format!("We found: {}", person)) 14 | .ok_or_else(|| format!("Missing person for UUID: {}", id)) 15 | } 16 | 17 | pub fn stage() -> rocket::fairing::AdHoc { 18 | // Seed the "database". 19 | let mut map = HashMap::new(); 20 | map.insert("7f205202-7ba1-4c39-b2fc-3e630722bf9f".parse().unwrap(), "Lacy"); 21 | map.insert("4da34121-bc7d-4fc1-aee6-bf8de0795333".parse().unwrap(), "Bob"); 22 | map.insert("ad962969-4e3d-4de7-ac4a-2d86d6d10839".parse().unwrap(), "George"); 23 | 24 | rocket::fairing::AdHoc::on_ignite("UUID", |rocket| async { 25 | rocket 26 | .manage(People(map)) 27 | .mount("/", routes![people]) 28 | }) 29 | } 30 | -------------------------------------------------------------------------------- /core/lib/tests/scoped-uri.rs: -------------------------------------------------------------------------------- 1 | use rocket::{Rocket, Build}; 2 | use rocket::local::blocking::Client; 3 | 4 | mod inner { 5 | use rocket::uri; 6 | 7 | #[rocket::get("/")] 8 | pub fn hello() -> String { 9 | format!("Hello! Try {}.", uri!(super::hello_name("Rust 2018"))) 10 | } 11 | } 12 | 13 | #[rocket::get("/")] 14 | fn hello_name(name: String) -> String { 15 | format!("Hello, {}! This is {}.", name, rocket::uri!(hello_name(&name))) 16 | } 17 | 18 | fn rocket() -> Rocket { 19 | rocket::build() 20 | .mount("/", rocket::routes![hello_name]) 21 | .mount("/", rocket::routes![inner::hello]) 22 | } 23 | 24 | #[test] 25 | fn test_inner_hello() { 26 | let client = Client::debug(rocket()).unwrap(); 27 | let response = client.get("/").dispatch(); 28 | assert_eq!(response.into_string(), Some("Hello! Try /Rust%202018.".into())); 29 | } 30 | 31 | #[test] 32 | fn test_hello_name() { 33 | let client = Client::debug(rocket()).unwrap(); 34 | let response = client.get("/Rust%202018").dispatch(); 35 | assert_eq!(response.into_string().unwrap(), "Hello, Rust 2018! This is /Rust%202018."); 36 | } 37 | -------------------------------------------------------------------------------- /site/guide/1-quickstart.md: -------------------------------------------------------------------------------- 1 | # Quickstart 2 | 3 | Before you can start writing a Rocket application, you'll need to install the 4 | Rust toolchain. We recommend using [rustup](https://rustup.rs/). If you don't 5 | have Rust installed and would like extra guidance doing so, see the [getting 6 | started](../getting-started) section. 7 | 8 | ## Running Examples 9 | 10 | The absolute fastest way to start experimenting with Rocket is to clone the 11 | Rocket repository and run the included examples in the `examples/` directory. 12 | For instance, the following set of commands runs the `hello` example: 13 | 14 | ```sh 15 | git clone https://github.com/SergioBenitez/Rocket 16 | cd Rocket 17 | git checkout v0.5-rc 18 | cd examples/hello 19 | cargo run 20 | ``` 21 | 22 | There are numerous examples in the `examples/` directory. They can all be run 23 | with `cargo run`. 24 | 25 | ! note 26 | 27 | The examples' `Cargo.toml` files will point to the locally cloned `rocket` 28 | libraries. When copying the examples for your own use, you should modify the 29 | `Cargo.toml` files as explained in the [Getting Started] guide. 30 | 31 | [Getting Started]: ../getting-started 32 | -------------------------------------------------------------------------------- /examples/todo/static/css/style.css: -------------------------------------------------------------------------------- 1 | .field-error { 2 | border: 1px solid #ff0000 !important; 3 | } 4 | 5 | .field-error-msg { 6 | color: #ff0000; 7 | display: block; 8 | margin: -10px 0 10px 0; 9 | } 10 | 11 | .field-success { 12 | border: 1px solid #5AB953 !important; 13 | } 14 | 15 | .field-success-msg { 16 | color: #5AB953; 17 | display: block; 18 | margin: -10px 0 10px 0; 19 | } 20 | 21 | span.completed { 22 | text-decoration: line-through; 23 | } 24 | 25 | form.inline { 26 | display: inline; 27 | } 28 | 29 | form.link, 30 | button.link { 31 | display: inline; 32 | color: #1EAEDB; 33 | border: none; 34 | outline: none; 35 | background: none; 36 | cursor: pointer; 37 | padding: 0; 38 | margin: 0 0 0 0; 39 | height: inherit; 40 | text-decoration: underline; 41 | font-size: inherit; 42 | text-transform: none; 43 | font-weight: normal; 44 | line-height: inherit; 45 | letter-spacing: inherit; 46 | } 47 | 48 | form.link:hover, button.link:hover { 49 | color: #0FA0CE; 50 | } 51 | 52 | button.small { 53 | height: 20px; 54 | padding: 0 10px; 55 | font-size: 10px; 56 | line-height: 20px; 57 | margin: 0 2.5px; 58 | } 59 | -------------------------------------------------------------------------------- /core/lib/tests/form_value_decoding-issue-82.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] extern crate rocket; 2 | 3 | use rocket::form::Form; 4 | 5 | #[post("/", data = "")] 6 | fn bug(form_data: Form) -> String { 7 | form_data.into_inner() 8 | } 9 | 10 | mod tests { 11 | use super::*; 12 | use rocket::local::blocking::Client; 13 | use rocket::http::ContentType; 14 | use rocket::http::Status; 15 | 16 | fn check_decoding(raw: &str, decoded: &str) { 17 | let client = Client::debug_with(routes![bug]).unwrap(); 18 | let response = client.post("/") 19 | .header(ContentType::Form) 20 | .body(format!("form_data={}", raw)) 21 | .dispatch(); 22 | 23 | assert_eq!(response.status(), Status::Ok); 24 | assert_eq!(Some(decoded.to_string()), response.into_string()); 25 | } 26 | 27 | #[test] 28 | fn test_proper_decoding() { 29 | check_decoding("password", "password"); 30 | check_decoding("", ""); 31 | check_decoding("+", " "); 32 | check_decoding("%2B", "+"); 33 | check_decoding("1+1", "1 1"); 34 | check_decoding("1%2B1", "1+1"); 35 | check_decoding("%3Fa%3D1%26b%3D2", "?a=1&b=2"); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /examples/templating/src/tera.rs: -------------------------------------------------------------------------------- 1 | use rocket::Request; 2 | use rocket::response::Redirect; 3 | 4 | use rocket_dyn_templates::{Template, tera::Tera, context}; 5 | 6 | #[get("/")] 7 | pub fn index() -> Redirect { 8 | Redirect::to(uri!("/tera", hello(name = "Your Name"))) 9 | } 10 | 11 | #[get("/hello/")] 12 | pub fn hello(name: &str) -> Template { 13 | Template::render("tera/index", context! { 14 | title: "Hello", 15 | name: Some(name), 16 | items: vec!["One", "Two", "Three"], 17 | }) 18 | } 19 | 20 | #[get("/about")] 21 | pub fn about() -> Template { 22 | Template::render("tera/about.html", context! { 23 | title: "About", 24 | }) 25 | } 26 | 27 | #[catch(404)] 28 | pub fn not_found(req: &Request<'_>) -> Template { 29 | Template::render("tera/error/404", context! { 30 | uri: req.uri() 31 | }) 32 | } 33 | 34 | pub fn customize(tera: &mut Tera) { 35 | tera.add_raw_template("tera/about.html", r#" 36 | {% extends "tera/base" %} 37 | 38 | {% block content %} 39 |
40 |

About - Here's another page!

41 |
42 | {% endblock content %} 43 | "#).expect("valid Tera template"); 44 | } 45 | -------------------------------------------------------------------------------- /core/lib/tests/unsound-local-request-1312.rs: -------------------------------------------------------------------------------- 1 | use rocket::http::Header; 2 | use rocket::local::blocking::Client; 3 | 4 | #[test] 5 | fn test_local_request_clone_soundness() { 6 | let client = Client::debug_with(vec![]).unwrap(); 7 | 8 | // creates two LocalRequest instances that shouldn't share the same req 9 | let r1 = client.get("/").header(Header::new("key", "val1")); 10 | let mut r2 = r1.clone(); 11 | 12 | // save the iterator, which internally holds a slice 13 | let mut iter = r1.inner().headers().get("key"); 14 | 15 | // insert headers to force header map reallocation. 16 | for i in 0..100 { 17 | r2.add_header(Header::new(i.to_string(), i.to_string())); 18 | } 19 | 20 | // Replace the original key/val. 21 | r2.add_header(Header::new("key", "val2")); 22 | 23 | // Heap massage: so we've got crud to print. 24 | let _: Vec = vec![0, 0xcafebabe, 31337, 0]; 25 | 26 | // Ensure we're good. 27 | let s = iter.next().unwrap(); 28 | println!("{}", s); 29 | 30 | // And that we've got the right data. 31 | assert_eq!(r1.inner().headers().get("key").collect::>(), vec!["val1"]); 32 | assert_eq!(r2.inner().headers().get("key").collect::>(), vec!["val1", "val2"]); 33 | } 34 | -------------------------------------------------------------------------------- /examples/tls/private/ed25519_cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDMjCCARqgAwIBAgIUdMGHQoLHGcks+Hnw7dC5dEl0/ogwDQYJKoZIhvcNAQEL 3 | BQAwRzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRIwEAYDVQQKDAlSb2NrZXQg 4 | Q0ExFzAVBgNVBAMMDlJvY2tldCBSb290IENBMB4XDTIxMDcwOTIzMzMzM1oXDTMx 5 | MDcwNzIzMzMzM1owPzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQ8wDQYDVQQK 6 | DAZSb2NrZXQxEjAQBgNVBAMMCWxvY2FsaG9zdDAqMAUGAytlcAMhAP7ORUynwg2q 7 | IbwJwpOThFhc/IhiWxIIACcaiNKPtdEzoxgwFjAUBgNVHREEDTALgglsb2NhbGhv 8 | c3QwDQYJKoZIhvcNAQELBQADggIBAKcrsLA9ijRjE/h8FUNbEz547a8wCy6NskRh 9 | vCLIsC3k3pfhmKatM3BSwrpePFv6iSPIlp6rY9rTYx+vnLGVnT5bjPDA3Q5VwyIF 10 | lAYnbZP7VSQKWr2hLqFd/3sUvg7kSL16nVi4GaRYTAH2W9IQWyx+GKqv6lRmDFwS 11 | TCoPu2YnoboWTYMFdsrxdkzvBkQX+IF45aVTnUbAcLAc7hgZdK6+ZAhIk4ymDDWj 12 | FeGi/hJ5zF9a/zdV+62CHuIwgCT3ETUXeVLKWf6+v2pOMYXmpdPJf5g06zsrpcYY 13 | i+ZdYPXFs4/yzwcUpgYdkpszMJcxgUSn/u2E9/9BFtJa/kwDbHCDItyR2rSeDoUI 14 | 2mQY6Kjm8BucM8hBoNYh9HOHEn1450PHIyWzcSMFkhfqSAKzngVcuSmRkUYhIdHu 15 | bUu29CLJzvOCTFxAWd4uWO2EbH5QFOeD9sQjqzadw0KX5kZl3Oe0wJqLswpKXd7m 16 | uQzcIjGNhY3STk722z0sFuZOvZPoi2d46ZKRBIJ9OYQfUzLDWW1PjqIuX7gWOUfe 17 | PaSs8K2qQlfniPJzHFQ3XHB4KJoWP2BcTUh5mkmpq5st5Buox8JUeAH+SalltR+K 18 | Skvvyv6hIhKyUDrgqV3dhIdTiexRLsmosXdps7ifJdmDtJcuWVp5hCS05X5oHTk/ 19 | 6WWSkctl 20 | -----END CERTIFICATE----- 21 | -------------------------------------------------------------------------------- /core/lib/tests/form_method-issue-45.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] extern crate rocket; 2 | 3 | use rocket::form::Form; 4 | 5 | #[derive(FromForm)] 6 | struct FormData { 7 | form_data: String, 8 | } 9 | 10 | #[patch("/", data = "")] 11 | fn bug(form_data: Form) -> &'static str { 12 | assert_eq!("Form data", form_data.into_inner().form_data); 13 | "OK" 14 | } 15 | 16 | mod tests { 17 | use super::*; 18 | use rocket::local::blocking::Client; 19 | use rocket::http::{Status, ContentType}; 20 | 21 | #[test] 22 | fn method_eval() { 23 | let client = Client::debug_with(routes![bug]).unwrap(); 24 | let response = client.post("/") 25 | .header(ContentType::Form) 26 | .body("_method=patch&form_data=Form+data") 27 | .dispatch(); 28 | 29 | assert_eq!(response.into_string(), Some("OK".into())); 30 | } 31 | 32 | #[test] 33 | fn get_passes_through() { 34 | let client = Client::debug_with(routes![bug]).unwrap(); 35 | let response = client.get("/") 36 | .header(ContentType::Form) 37 | .body("_method=patch&form_data=Form+data") 38 | .dispatch(); 39 | 40 | assert_eq!(response.status(), Status::NotFound); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature-request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature Request 3 | about: Propose a change that introduces new functionality 4 | title: '' 5 | labels: request 6 | assignees: '' 7 | --- 8 | 9 | **Is your feature request motivated by a concrete problem? Please describe.** 10 | 11 | A clear and concise description of what the problem is. Examples: 12 | 13 | - "I frequently want to do X, but Rocket makes it hard. It would be nice if Rocket..." 14 | - "I want to do X but Rocket makes it impossible because..." 15 | - "Feature Z exists, but it has these drawbacks. What if..." 16 | 17 | **Why this feature can't or shouldn't live outside of Rocket** 18 | 19 | Rocket is designed to have a small but pluggable core. Feature requests that can be implemented outside of Rocket are typically declined. Make a case for why this feature can't or shouldn't be implemented outside of Rocket. 20 | 21 | **Ideal Solution** 22 | 23 | If you have an idea for a solution, propose it with a clear and concise description. 24 | 25 | **Alternatives Considered** 26 | 27 | A clear and concise description of any alternative solutions or features you've considered. 28 | 29 | **Additional Context** 30 | 31 | Add any other context here, for example, descriptions of elegant solutions in other software. 32 | -------------------------------------------------------------------------------- /contrib/dyn_templates/src/handlebars_templates.rs: -------------------------------------------------------------------------------- 1 | use std::path::Path; 2 | 3 | use rocket::serde::Serialize; 4 | 5 | use crate::engine::Engine; 6 | pub use crate::handlebars::Handlebars; 7 | 8 | impl Engine for Handlebars<'static> { 9 | const EXT: &'static str = "hbs"; 10 | 11 | fn init<'a>(templates: impl Iterator) -> Option { 12 | let mut hb = Handlebars::new(); 13 | let mut ok = true; 14 | for (name, path) in templates { 15 | if let Err(e) = hb.register_template_file(name, path) { 16 | error!("Handlebars template '{}' failed to register.", name); 17 | error_!("{}", e); 18 | info_!("Template path: '{}'.", path.to_string_lossy()); 19 | ok = false; 20 | } 21 | } 22 | 23 | ok.then(|| hb) 24 | } 25 | 26 | fn render(&self, name: &str, context: C) -> Option { 27 | if self.get_template(name).is_none() { 28 | error_!("Handlebars template '{}' does not exist.", name); 29 | return None; 30 | } 31 | 32 | Handlebars::render(self, name, &context) 33 | .map_err(|e| error_!("Handlebars: {}", e)) 34 | .ok() 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /examples/fairings/src/tests.rs: -------------------------------------------------------------------------------- 1 | use super::rocket; 2 | use rocket::local::blocking::Client; 3 | 4 | #[test] 5 | fn rewrite_get_put() { 6 | let client = Client::tracked(rocket()).unwrap(); 7 | let response = client.get("/").dispatch(); 8 | assert_eq!(response.into_string(), Some("Hello, fairings!".into())); 9 | } 10 | 11 | #[test] 12 | fn counts() { 13 | let client = Client::tracked(rocket()).unwrap(); 14 | 15 | // Issue 1 GET request. 16 | client.get("/").dispatch(); 17 | 18 | // Check the GET count, taking into account _this_ GET request. 19 | let response = client.get("/counts").dispatch(); 20 | assert_eq!(response.into_string(), Some("Get: 2\nPost: 0".into())); 21 | 22 | // Issue 1 more GET request and a POST. 23 | client.get("/").dispatch(); 24 | client.post("/").dispatch(); 25 | 26 | // Check the counts. 27 | let response = client.get("/counts").dispatch(); 28 | assert_eq!(response.into_string(), Some("Get: 4\nPost: 1".into())); 29 | } 30 | 31 | #[test] 32 | fn token() { 33 | let client = Client::tracked(rocket()).unwrap(); 34 | 35 | // Ensure the token is '123', which is what we have in `Rocket.toml`. 36 | let res = client.get("/token").dispatch(); 37 | assert_eq!(res.into_string(), Some("123".into())); 38 | } 39 | -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail/typed-uris-invalid-syntax.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] extern crate rocket; 2 | 3 | #[get("/")] 4 | fn index() { } 5 | 6 | #[post("//")] 7 | fn simple(id: i32, name: String) -> &'static str { "" } 8 | 9 | fn main() { 10 | uri!(simple: id = 100, "Hello"); 11 | uri!(simple(id = 100, "Hello")); 12 | uri!(simple("Hello", id = 100)); 13 | uri!(simple,); 14 | uri!(simple:); 15 | uri!("/mount",); 16 | uri!("mount", simple); 17 | uri!("mount", simple, "http://"); 18 | uri!("/mount", simple, "http://"); 19 | uri!("/mount", simple, "#foo", "?foo"); 20 | uri!("mount", simple(10, "hi"), "http://"); 21 | uri!("/mount", simple(10, "hi"), "http://"); 22 | uri!("/mount?foo", simple(10, "hi"), "foo/bar?foo#bar"); 23 | uri!("/mount", simple(10, "hi"), "a/b"); 24 | uri!("/mount", simple(10, "hi"), "#foo", "?foo"); 25 | uri!("/mount/", simple); 26 | uri!(); 27 | uri!(simple: id = ); 28 | uri!(simple(id = )); 29 | uri!("*", simple(10), "hi"); 30 | uri!("some.host:8088", simple(10), "hi"); 31 | uri!("?foo"); 32 | uri!(""); 33 | uri!("/foo", "bar"); 34 | uri!("/foo" ("bar")); 35 | uri!("ftp:?", index); 36 | uri!("ftp:", index, "foo#bar"); 37 | uri!("ftp:", index, "foo?bar"); 38 | } 39 | -------------------------------------------------------------------------------- /scripts/bump_version.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | 3 | # 4 | # Bumps the version number to ${1}. 5 | # 6 | 7 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 8 | source "${SCRIPT_DIR}/config.sh" 9 | 10 | if [ -z "${1}" ] ; then 11 | echo "Usage: $0 " 12 | echo "Example: $0 0.6.1" 13 | exit 1 14 | fi 15 | 16 | function do_replace_docs() { 17 | sd "${1}" "${2}" $(fd -t f -e toml -E '/news/*' . "${PROJECT_ROOT}") 18 | sd "${1}" "${2}" $(fd -t f -e md -E '/news/*' . "${SITE_ROOT}") 19 | } 20 | 21 | function do_replace_all() { 22 | sd "${1}" "${2}" $(fd -t f -e rs . "${PROJECT_ROOT}") 23 | do_replace_docs "${1}" "${2}" 24 | } 25 | 26 | NEW_VERSION="${1}" 27 | TODAY=$(date "+%b %d, %Y") 28 | 29 | if $PRE_RELEASE; then 30 | do_replace_all "/${PHYSICAL_CODENAME}" "/${CODENAME}" 31 | do_replace_docs "${PHYSICAL_CODENAME}" "${CODENAME}" 32 | else 33 | NEW_CODENAME="v$(echo "${NEW_VERSION}" | cut -d'.' -f1-2)" 34 | do_replace_all "/${VIRTUAL_CODENAME}" "/${CODENAME}" 35 | do_replace_all "/${CODENAME}" "/${NEW_CODENAME}" 36 | do_replace_docs "${VIRTUAL_CODENAME}" "${CODENAME}" 37 | do_replace_docs "${CODENAME}" "${NEW_CODENAME}" 38 | fi 39 | 40 | do_replace_all "${VERSION}" "${NEW_VERSION}" 41 | sd "^date.*" "date = \"${TODAY}\"" "${SITE_ROOT}/index.toml" 42 | -------------------------------------------------------------------------------- /contrib/db_pools/lib/src/error.rs: -------------------------------------------------------------------------------- 1 | use std::fmt; 2 | 3 | /// A general error type for use by [`Pool`](crate::Pool#implementing) 4 | /// implementors and returned by the [`Connection`](crate::Connection) request 5 | /// guard. 6 | #[derive(Debug)] 7 | pub enum Error { 8 | /// An error that occured during database/pool initialization. 9 | Init(A), 10 | 11 | /// An error that ocurred while retrieving a connection from the pool. 12 | Get(B), 13 | 14 | /// A [`Figment`](crate::figment::Figment) configuration error. 15 | Config(crate::figment::Error), 16 | } 17 | 18 | impl fmt::Display for Error { 19 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 20 | match self { 21 | Error::Init(e) => write!(f, "failed to initialize database: {}", e), 22 | Error::Get(e) => write!(f, "failed to get db connection: {}", e), 23 | Error::Config(e) => write!(f, "bad configuration: {}", e), 24 | } 25 | } 26 | } 27 | 28 | impl std::error::Error for Error 29 | where A: fmt::Debug + fmt::Display, B: fmt::Debug + fmt::Display {} 30 | 31 | impl From for Error { 32 | fn from(e: crate::figment::Error) -> Self { 33 | Self::Config(e) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /examples/config/src/tests.rs: -------------------------------------------------------------------------------- 1 | use rocket::config::{Config, LogLevel}; 2 | 3 | async fn test_config(profile: &str) { 4 | let provider = Config::figment().select(profile); 5 | let rocket = rocket::custom(provider).ignite().await.unwrap(); 6 | let config = rocket.config(); 7 | match &*profile { 8 | "debug" => { 9 | assert_eq!(config.address, std::net::Ipv4Addr::LOCALHOST); 10 | assert_eq!(config.port, 8000); 11 | assert_eq!(config.workers, 1); 12 | assert_eq!(config.keep_alive, 0); 13 | assert_eq!(config.log_level, LogLevel::Normal); 14 | } 15 | "release" => { 16 | assert_eq!(config.address, std::net::Ipv4Addr::LOCALHOST); 17 | assert_eq!(config.port, 8000); 18 | assert_eq!(config.workers, 12); 19 | assert_eq!(config.keep_alive, 5); 20 | assert_eq!(config.log_level, LogLevel::Critical); 21 | assert!(!config.secret_key.is_zero()); 22 | } 23 | _ => { 24 | panic!("Unknown profile: {}", profile); 25 | } 26 | } 27 | } 28 | 29 | #[async_test] 30 | async fn test_debug_config() { 31 | test_config("debug").await; 32 | } 33 | 34 | #[async_test] 35 | async fn test_release_config() { 36 | test_config("release").await; 37 | } 38 | -------------------------------------------------------------------------------- /examples/testing/src/async_required.rs: -------------------------------------------------------------------------------- 1 | use rocket::{Rocket, State, Build}; 2 | use rocket::fairing::AdHoc; 3 | use rocket::tokio::sync::Barrier; 4 | 5 | #[get("/barrier")] 6 | async fn rendezvous(barrier: &State) -> &'static str { 7 | println!("Waiting for second task..."); 8 | barrier.wait().await; 9 | "Rendezvous reached." 10 | } 11 | 12 | pub fn rocket() -> Rocket { 13 | rocket::build() 14 | .mount("/", routes![rendezvous]) 15 | .attach(AdHoc::on_ignite("Add Channel", |rocket| async { 16 | rocket.manage(Barrier::new(2)) 17 | })) 18 | } 19 | 20 | #[cfg(test)] 21 | mod test { 22 | use super::rocket; 23 | use rocket::http::Status; 24 | 25 | #[rocket::async_test] 26 | async fn test_rendezvous() { 27 | use rocket::local::asynchronous::Client; 28 | 29 | let client = Client::tracked(rocket()).await.unwrap(); 30 | let req = client.get("/barrier"); 31 | 32 | let (r1, r2) = rocket::tokio::join!(req.clone().dispatch(), req.dispatch()); 33 | assert_eq!(r1.status(), r2.status()); 34 | assert_eq!(r1.status(), Status::Ok); 35 | 36 | let (s1, s2) = (r1.into_string().await, r2.into_string().await); 37 | assert_eq!(s1, s2); 38 | assert_eq!(s1.unwrap(), "Rendezvous reached."); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /examples/tls/private/ecdsa_nistp256_sha256_cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDYTCCAUmgAwIBAgIUWET3Ypdh7TK5UE24E9Smn1r03d0wDQYJKoZIhvcNAQEL 3 | BQAwRzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRIwEAYDVQQKDAlSb2NrZXQg 4 | Q0ExFzAVBgNVBAMMDlJvY2tldCBSb290IENBMB4XDTIxMDcwOTIzMzMzM1oXDTMx 5 | MDcwNzIzMzMzM1owPzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQ8wDQYDVQQK 6 | DAZSb2NrZXQxEjAQBgNVBAMMCWxvY2FsaG9zdDBZMBMGByqGSM49AgEGCCqGSM49 7 | AwEHA0IABDtAvrDALV/ZGurSJdoRFDvB2q7PsdjWWvzFWvQortUzmWXuFO47QJ8v 8 | lqluDtQKK7gHmNm10MrDk2o0ipMkrzSjGDAWMBQGA1UdEQQNMAuCCWxvY2FsaG9z 9 | dDANBgkqhkiG9w0BAQsFAAOCAgEAGJ/mFUyJzomXpYqGHzBRUvBqGmY05F2YOu0a 10 | D620WyWUFYWOnbqSKqqrP2nI1eNQXbmTtcKokuC67I2laIYML/IwBuLj+JcenvaB 11 | TmtmHHFSb0fweXSK3r0m9KEQBvVeoMEFhTZ6NINmXjTZES2xOks47yVo704q3xhS 12 | 7Rm7YGu3Wgjyn4YAb7UQhgnvN0x4UlDHQAU8PB4nLHgKkgaczaERcIa/nhGA1D85 13 | obNkh+QSNsShnrOrDJ4iRt5ZBLjmTX3qcbJTjjzaKwwMuBTOr7f5zh417ahPWq2v 14 | r0GgmMW+8k8D7CjBM5TkNzOTQRjLUUKF1YjX39E4J8E/rtg8/GlHVfKRG8bvGIK8 15 | EIiAaSjUTY00cQltlt9QMFOTGlakF8Id4Dxkke+oP+62EK1pOroQiRvNeopEy+dO 16 | Gee7HN5eC6n548VrMMql1TMoraWMK4kiVy46xlBmwHXq/JPG0GV/I6i24jobYeGt 17 | 8yoeB1DlCX9uiLOKlPctxMeVPkErvVGvVZZKMR2KYNznSj/L22VXSh0xg0L6zVRX 18 | DsW97MZsef1t2RZf7nSz4JkSecuUHNsk12Z/Pe3G7zofz2UtV1o3G9oBHSm91a/j 19 | L/sAlvawy8CwLll8DRk26mg7YLwgxnNfJzG9M0G8Fwi6XPUBx2ywsSTWSO0KQ+5C 20 | p2mcGCY= 21 | -----END CERTIFICATE----- 22 | -------------------------------------------------------------------------------- /examples/tls/private/ecdsa_nistp384_sha384_cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDfjCCAWagAwIBAgIUB+Ff5LDKhcdjusOuaCqjePqScwQwDQYJKoZIhvcNAQEM 3 | BQAwRzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRIwEAYDVQQKDAlSb2NrZXQg 4 | Q0ExFzAVBgNVBAMMDlJvY2tldCBSb290IENBMB4XDTIxMDcwOTIzMzMzM1oXDTMx 5 | MDcwNzIzMzMzM1owPzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQ8wDQYDVQQK 6 | DAZSb2NrZXQxEjAQBgNVBAMMCWxvY2FsaG9zdDB2MBAGByqGSM49AgEGBSuBBAAi 7 | A2IABNkp8NiqSoUc8bwJq0fIRFyvdDN0jUT4+9MdoJ/CJyKHjeVVBcMWXBJbKTmo 8 | rFbkJ6WcUbBU30K0+KTvqX9tFLXOmpwUZDyqmkeU78VV7DJrDKSy5Hgxz5hXJ309 9 | lz+Kr6MYMBYwFAYDVR0RBA0wC4IJbG9jYWxob3N0MA0GCSqGSIb3DQEBDAUAA4IC 10 | AQATXjqJmDfj0/C1KzSoFgvuiDK6NseMJijkKauaGdHUSGf2P06izvwke8xW3P/b 11 | VifOkpKX3K9RxY4R7xDenTXIEDnKYlp2a77djbef8mBL914ZQSXBFF8Lhz1QD/QC 12 | sIM8exCuelgHbfPh/UdLY1CmEcYOlHQYUpIMYkH7U0KbLvqafY3d7WkERuXwzAUd 13 | kYCAV2V23f2HiuOaX616QYW7Ow6jPrhU1RwEW25Y/Ubw+jQKDSRE6NF+inR7WPot 14 | 2GN0ELY+6trxe0w0DL0syOsfF9SVkvgfKhwBKVCsJvCp4HmOIBDlZL40NhrnXK6L 15 | HmUsyckVVMSmPRrvNrIy7m6CoCbdb8wWPlhpygMrOFfhpGJ2fIMzf4JzQnsAKHO9 16 | 1D5mtzaHNNcwBdWNTvVOojy0BRsRrNYcO/Lkf5+VwZ3+AQVPPwG04kk7fA/iONQx 17 | hraiVy6Majl4pFfbWcAOaSDDSMsZ8Joc6AmCiPQGVelrqzZ1wa+a12BBfibqYdm7 18 | ab831J7KrkK2rfCC84ZdUcICcWkPCisMfPeoaQsp2R4Zw7Rcuyfce8UVZYZsmZ9X 19 | rmgp6O3oIWK31iHkgpb+bQM0YXykbK/fp7vxqnfk2kq+IadSlDwOJ/U8sdNMVHdK 20 | mct9ke+F1KFB+J8UU5w/JK/Tn7HtWY8lf9VTuK8pAkyQAg== 21 | -----END CERTIFICATE----- 22 | -------------------------------------------------------------------------------- /core/lib/tests/derive-reexports.rs: -------------------------------------------------------------------------------- 1 | use rocket; 2 | 3 | use rocket::{get, routes}; 4 | use rocket::form::{FromForm, FromFormField}; 5 | use rocket::response::Responder; 6 | 7 | #[derive(FromFormField)] 8 | enum Thing { 9 | A, 10 | B, 11 | C, 12 | } 13 | 14 | impl std::fmt::Display for Thing { 15 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 16 | match *self { 17 | Thing::A => write!(f, "a"), 18 | Thing::B => write!(f, "b"), 19 | Thing::C => write!(f, "c"), 20 | } 21 | } 22 | } 23 | 24 | #[derive(FromForm)] 25 | struct ThingForm { 26 | thing: Thing, 27 | } 28 | 29 | #[derive(Responder)] 30 | struct DerivedResponder { 31 | data: String, 32 | } 33 | 34 | #[get("/")] 35 | fn index() -> DerivedResponder { 36 | DerivedResponder { data: "hello".to_string() } 37 | } 38 | 39 | #[get("/?")] 40 | fn number(params: ThingForm) -> DerivedResponder { 41 | DerivedResponder { data: params.thing.to_string() } 42 | } 43 | 44 | #[test] 45 | fn test_derive_reexports() { 46 | use rocket::local::blocking::Client; 47 | 48 | let client = Client::debug_with(routes![index, number]).unwrap(); 49 | 50 | let response = client.get("/").dispatch(); 51 | assert_eq!(response.into_string().unwrap(), "hello"); 52 | 53 | let response = client.get("/?thing=b").dispatch(); 54 | assert_eq!(response.into_string().unwrap(), "b"); 55 | } 56 | -------------------------------------------------------------------------------- /core/codegen/tests/route-raw.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] extern crate rocket; 2 | 3 | use rocket::local::blocking::Client; 4 | 5 | // Test that raw idents can be used for route parameter names 6 | 7 | #[get("/?")] 8 | fn get(r#enum: String, r#type: i32) -> String { 9 | format!("{} is {}", r#enum, r#type) 10 | } 11 | 12 | #[get("/swap//")] 13 | fn swap(r#raw: String, bare: String) -> String { 14 | format!("{}, {}", raw, bare) 15 | } 16 | 17 | #[catch(400)] 18 | fn catch(r#raw: &rocket::Request) -> String { 19 | format!("{}", raw.method()) 20 | } 21 | 22 | #[test] 23 | fn test_raw_ident() { 24 | let rocket = rocket::build() 25 | .mount("/", routes![get, swap]) 26 | .register("/", catchers![catch]); 27 | 28 | let client = Client::debug(rocket).unwrap(); 29 | 30 | let response = client.get("/example?type=1").dispatch(); 31 | assert_eq!(response.into_string().unwrap(), "example is 1"); 32 | 33 | let uri_named = uri!(get(r#enum = "test_named", r#type = 1)); 34 | assert_eq!(uri_named.to_string(), "/test_named?type=1"); 35 | 36 | let uri_unnamed = uri!(get("test_unnamed", 2)); 37 | assert_eq!(uri_unnamed.to_string(), "/test_unnamed?type=2"); 38 | 39 | let uri_raws = uri!(swap(r#raw = "1", r#bare = "2")); 40 | assert_eq!(uri_raws.to_string(), "/swap/1/2"); 41 | let uri_bare = uri!(swap(raw = "1", bare = "2")); 42 | assert_eq!(uri_bare.to_string(), "/swap/1/2"); 43 | } 44 | -------------------------------------------------------------------------------- /site/guide/11-conclusion.md: -------------------------------------------------------------------------------- 1 | # Conclusion 2 | 3 | We hope you agree that Rocket is a refreshing take on web frameworks. As with 4 | any software project, Rocket is _alive_. There are always things to improve, and 5 | we're happy to take the best ideas. If you have something in mind, please 6 | [submit an issue](https://github.com/SergioBenitez/Rocket/issues). 7 | 8 | ## Getting Help 9 | 10 | If you find yourself having trouble developing Rocket applications, you can get 11 | help via chat at [`#rocket:mozilla.org`] on Matrix or the bridged [`#rocket`] 12 | IRC channel on Libera.Chat at `irc.libera.chat`. We recommend joining us on 13 | [Matrix via Element]. If you prefer IRC, you can join via the [Kiwi IRC client] 14 | or a client of your own. The [FAQ](../faq/) also provides answers to commonly 15 | asked questions. 16 | 17 | [`#rocket:mozilla.org`]: https://chat.mozilla.org/#/room/#rocket:mozilla.org 18 | [`#rocket`]: https://kiwiirc.com/client/irc.libera.chat/#rocket 19 | [Matrix via Element]: https://chat.mozilla.org/#/room/#rocket:mozilla.org 20 | [Kiwi IRC Client]: https://kiwiirc.com/client/irc.libera.chat/#rocket 21 | 22 | ## What's next? 23 | 24 | The best way to learn Rocket is to _build something_. It should be fun and easy, 25 | and there's always someone to help. Alternatively, you can read through the 26 | [Rocket examples](@example) or the [Rocket source code](@github/core/lib/src). 27 | Whatever you decide to do next, we hope you have a blast! 28 | -------------------------------------------------------------------------------- /core/lib/src/response/stream/one.rs: -------------------------------------------------------------------------------- 1 | use std::pin::Pin; 2 | use std::task::{Context, Poll}; 3 | 4 | use futures::stream::Stream; 5 | 6 | /// A stream that yields exactly one value. 7 | /// 8 | /// A `ReaderStream` which wraps this type and yields one `AsyncRead` is 9 | /// returned by [`ReaderStream::one()`]. A `One` can also be constructed via 10 | /// [`One::from()`]. 11 | /// 12 | /// [`ReaderStream::one()`]: crate::response::stream::ReaderStream::one() 13 | /// 14 | /// # Example 15 | /// 16 | /// ```rust 17 | /// use rocket::response::stream::One; 18 | /// use rocket::futures::stream::StreamExt; 19 | /// 20 | /// # rocket::async_test(async { 21 | /// let mut stream = One::from("hello!"); 22 | /// let values: Vec<_> = stream.collect().await; 23 | /// assert_eq!(values, ["hello!"]); 24 | /// # }); 25 | /// ``` 26 | pub struct One(Option); 27 | 28 | /// Returns a `One` stream that will yield `value` exactly once. 29 | /// 30 | /// # Example 31 | /// 32 | /// ```rust 33 | /// use rocket::response::stream::One; 34 | /// 35 | /// let mut stream = One::from("hello!"); 36 | /// ``` 37 | impl From for One { 38 | fn from(value: T) -> Self { 39 | One(Some(value)) 40 | } 41 | } 42 | 43 | impl Stream for One { 44 | type Item = T; 45 | 46 | fn poll_next( 47 | mut self: Pin<&mut Self>, 48 | _: &mut Context<'_>, 49 | ) -> Poll> { 50 | Poll::Ready(self.0.take()) 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /core/lib/tests/local_request_private_cookie-issue-368.rs: -------------------------------------------------------------------------------- 1 | #![cfg(feature = "secrets")] 2 | 3 | use rocket::http::CookieJar; 4 | 5 | #[rocket::get("/")] 6 | fn return_private_cookie(cookies: &CookieJar<'_>) -> Option { 7 | match cookies.get_private("cookie_name") { 8 | Some(cookie) => Some(cookie.value().into()), 9 | None => None, 10 | } 11 | } 12 | 13 | mod tests { 14 | use super::*; 15 | use rocket::routes; 16 | use rocket::local::blocking::Client; 17 | use rocket::http::{Cookie, Status}; 18 | 19 | #[test] 20 | fn private_cookie_is_returned() { 21 | let rocket = rocket::build().mount("/", routes![return_private_cookie]); 22 | 23 | let client = Client::debug(rocket).unwrap(); 24 | let req = client.get("/").private_cookie(Cookie::new("cookie_name", "cookie_value")); 25 | let response = req.dispatch(); 26 | 27 | assert_eq!(response.headers().get_one("Set-Cookie"), None); 28 | assert_eq!(response.into_string(), Some("cookie_value".into())); 29 | } 30 | 31 | #[test] 32 | fn regular_cookie_is_not_returned() { 33 | let rocket = rocket::build().mount("/", routes![return_private_cookie]); 34 | 35 | let client = Client::debug(rocket).unwrap(); 36 | let req = client.get("/").cookie(Cookie::new("cookie_name", "cookie_value")); 37 | let response = req.dispatch(); 38 | 39 | assert_eq!(response.status(), Status::NotFound); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /core/lib/src/response/mod.rs: -------------------------------------------------------------------------------- 1 | //! Types and traits to build and send responses. 2 | //! 3 | //! The return type of a Rocket handler can be any type that implements the 4 | //! [`Responder`](crate::response::Responder) trait, which means that the type knows 5 | //! how to generate a [`Response`]. Among other things, this module contains 6 | //! several such types. 7 | //! 8 | //! # Composing 9 | //! 10 | //! Many of the built-in `Responder` types _chain_ responses: they take in 11 | //! another `Responder` and add, remove, or change information in the response. 12 | //! In other words, many `Responder` types are built to compose well. As a 13 | //! result, you'll often have types of the form `A>` consisting of three 14 | //! `Responder`s `A`, `B`, and `C`. This is normal and encouraged as the type 15 | //! names typically illustrate the intended response. 16 | 17 | mod responder; 18 | mod redirect; 19 | mod response; 20 | mod debug; 21 | mod body; 22 | 23 | pub(crate) mod flash; 24 | 25 | pub mod content; 26 | pub mod status; 27 | pub mod stream; 28 | 29 | #[doc(hidden)] 30 | pub use rocket_codegen::Responder; 31 | 32 | pub use self::response::{Response, Builder}; 33 | pub use self::body::Body; 34 | pub use self::responder::Responder; 35 | pub use self::redirect::Redirect; 36 | pub use self::flash::Flash; 37 | pub use self::debug::Debug; 38 | 39 | /// Type alias for the `Result` of a [`Responder::respond_to()`] call. 40 | pub type Result<'r> = std::result::Result, crate::http::Status>; 41 | -------------------------------------------------------------------------------- /core/lib/tests/untracked-vs-tracked.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] extern crate rocket; 2 | 3 | use rocket::http::{Cookie, CookieJar}; 4 | 5 | #[post("/")] 6 | fn add(jar: &CookieJar<'_>) { 7 | jar.add(Cookie::new("name", "value")); 8 | } 9 | 10 | #[get("/")] 11 | fn get<'a>(jar: &'a CookieJar<'_>) -> Option<&'a str> { 12 | jar.get("name").map(|c| c.value()) 13 | } 14 | 15 | #[cfg(test)] 16 | mod many_cookie_jars_tests { 17 | use super::*; 18 | use rocket::{Rocket, local::blocking::Client, Build}; 19 | use rocket::http::Status; 20 | 21 | fn rocket() -> Rocket { 22 | rocket::custom(rocket::Config::debug_default()) 23 | .mount("/", routes![add, get]) 24 | } 25 | 26 | #[test] 27 | fn test_tracked() { 28 | let client = Client::tracked(rocket()).unwrap(); 29 | 30 | assert_eq!(client.get("/").dispatch().status(), Status::NotFound); 31 | assert_eq!(client.post("/").dispatch().status(), Status::Ok); 32 | 33 | let response = client.get("/").dispatch(); 34 | assert_eq!(response.status(), Status::Ok); 35 | assert_eq!(response.into_string().unwrap(), "value"); 36 | } 37 | 38 | #[test] 39 | fn test_untracked() { 40 | let client = Client::untracked(rocket()).unwrap(); 41 | 42 | assert_eq!(client.get("/").dispatch().status(), Status::NotFound); 43 | assert_eq!(client.post("/").dispatch().status(), Status::Ok); 44 | assert_eq!(client.get("/").dispatch().status(), Status::NotFound); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail-stable/catch_type_errors.stderr: -------------------------------------------------------------------------------- 1 | error[E0277]: the trait bound `usize: Responder<'_, '_>` is not satisfied 2 | --> $DIR/catch_type_errors.rs:6:30 3 | | 4 | 6 | fn f1(_request: &Request) -> usize { 5 | | ^^^^^ the trait `Responder<'_, '_>` is not implemented for `usize` 6 | | 7 | = note: required by `respond_to` 8 | 9 | error[E0277]: the trait bound `bool: Responder<'_, '_>` is not satisfied 10 | --> $DIR/catch_type_errors.rs:11:30 11 | | 12 | 11 | fn f2(_request: &Request) -> bool { 13 | | ^^^^ the trait `Responder<'_, '_>` is not implemented for `bool` 14 | | 15 | = note: required by `respond_to` 16 | 17 | error[E0308]: mismatched types 18 | --> $DIR/catch_type_errors.rs:16:17 19 | | 20 | 16 | fn f3(_request: bool) -> usize { 21 | | ^^^^ expected `bool`, found `&rocket::Request<'_>` 22 | 23 | error[E0277]: the trait bound `usize: Responder<'_, '_>` is not satisfied 24 | --> $DIR/catch_type_errors.rs:16:26 25 | | 26 | 16 | fn f3(_request: bool) -> usize { 27 | | ^^^^^ the trait `Responder<'_, '_>` is not implemented for `usize` 28 | | 29 | = note: required by `respond_to` 30 | 31 | error[E0277]: the trait bound `usize: Responder<'_, '_>` is not satisfied 32 | --> $DIR/catch_type_errors.rs:21:12 33 | | 34 | 21 | fn f4() -> usize { 35 | | ^^^^^ the trait `Responder<'_, '_>` is not implemented for `usize` 36 | | 37 | = note: required by `respond_to` 38 | -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail/responder.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] extern crate rocket; 2 | 3 | #[derive(Responder)] 4 | struct Thing1; 5 | 6 | #[derive(Responder)] 7 | struct Thing2(); 8 | 9 | #[derive(Responder)] 10 | enum Bar { } // NO ERROR 11 | 12 | #[derive(Responder)] 13 | enum Foo { Bark, } 14 | 15 | #[derive(Responder)] 16 | struct Thing4<'a, 'b>(&'a str, &'b str); 17 | 18 | #[derive(Responder)] 19 | struct Thing5(T); // NO ERROR 20 | 21 | #[derive(Responder)] 22 | struct Thing6(T, E); 23 | 24 | #[derive(Responder)] 25 | #[response(content_type = "")] 26 | struct Thing7(()); 27 | 28 | #[derive(Responder)] 29 | #[response(content_type = "idk")] 30 | struct Thing8(()); 31 | 32 | #[derive(Responder)] 33 | #[response(content_type = 100)] 34 | struct Thing9(()); 35 | 36 | #[derive(Responder)] 37 | #[response(status = 8)] 38 | struct Thing10(()); 39 | 40 | #[derive(Responder)] 41 | #[response(status = "404")] 42 | struct Thing11(()); 43 | 44 | #[derive(Responder)] 45 | #[response(status = "404", content_type = "html")] 46 | struct Thing12(()); 47 | 48 | #[derive(Responder)] 49 | #[response(status = 404, content_type = 120)] 50 | struct Thing13(()); 51 | 52 | #[derive(Responder)] // NO ERROR 53 | enum Error<'r, T> { 54 | #[response(status = 400)] 55 | Unauthorized(T), 56 | #[response(status = 404)] 57 | NotFound(rocket::fs::NamedFile), 58 | #[response(status = 500)] 59 | A(&'r str, rocket::http::ContentType), 60 | } 61 | 62 | #[derive(Responder)] // NO ERROR 63 | enum Error2<'r, T> { 64 | Unauthorized(&'r T), 65 | } 66 | 67 | fn main() {} 68 | -------------------------------------------------------------------------------- /examples/pastebin/src/main.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] extern crate rocket; 2 | 3 | mod paste_id; 4 | #[cfg(test)] mod tests; 5 | 6 | use std::io; 7 | 8 | use rocket::data::{Data, ToByteUnit}; 9 | use rocket::http::uri::Absolute; 10 | use rocket::response::content::RawText; 11 | use rocket::tokio::fs::{self, File}; 12 | 13 | use crate::paste_id::PasteId; 14 | 15 | const HOST: Absolute<'static> = uri!("http://localhost:8000"); 16 | 17 | const ID_LENGTH: usize = 3; 18 | 19 | #[post("/", data = "")] 20 | async fn upload(paste: Data<'_>) -> io::Result { 21 | let id = PasteId::new(ID_LENGTH); 22 | paste.open(128.kibibytes()).into_file(id.file_path()).await?; 23 | Ok(uri!(HOST, retrieve(id)).to_string()) 24 | } 25 | 26 | #[get("/")] 27 | async fn retrieve(id: PasteId<'_>) -> Option> { 28 | File::open(id.file_path()).await.map(RawText).ok() 29 | } 30 | 31 | #[delete("/")] 32 | async fn delete(id: PasteId<'_>) -> Option<()> { 33 | fs::remove_file(id.file_path()).await.ok() 34 | } 35 | 36 | #[get("/")] 37 | fn index() -> &'static str { 38 | " 39 | USAGE 40 | 41 | POST / 42 | 43 | accepts raw data in the body of the request and responds with a URL of 44 | a page containing the body's content 45 | 46 | EXAMPLE: curl --data-binary @file.txt http://localhost:8000 47 | 48 | GET / 49 | 50 | retrieves the content for the paste with id `` 51 | " 52 | } 53 | 54 | #[launch] 55 | fn rocket() -> _ { 56 | rocket::build() 57 | .mount("/", routes![index, upload, delete, retrieve]) 58 | } 59 | -------------------------------------------------------------------------------- /core/http/src/hyper.rs: -------------------------------------------------------------------------------- 1 | //! Re-exported hyper HTTP library types. 2 | //! 3 | //! All types that are re-exported from Hyper reside inside of this module. 4 | //! These types will, with certainty, be removed with time, but they reside here 5 | //! while necessary. 6 | 7 | #[doc(hidden)] pub use hyper::*; 8 | #[doc(hidden)] pub use http::*; 9 | 10 | /// Reexported http header types. 11 | pub mod header { 12 | macro_rules! import_http_headers { 13 | ($($name:ident),*) => ($( 14 | pub use hyper::header::$name as $name; 15 | )*) 16 | } 17 | 18 | import_http_headers! { 19 | ACCEPT, ACCEPT_CHARSET, ACCEPT_ENCODING, ACCEPT_LANGUAGE, ACCEPT_RANGES, 20 | ACCESS_CONTROL_ALLOW_CREDENTIALS, ACCESS_CONTROL_ALLOW_HEADERS, 21 | ACCESS_CONTROL_ALLOW_METHODS, ACCESS_CONTROL_ALLOW_ORIGIN, 22 | ACCESS_CONTROL_EXPOSE_HEADERS, ACCESS_CONTROL_MAX_AGE, 23 | ACCESS_CONTROL_REQUEST_HEADERS, ACCESS_CONTROL_REQUEST_METHOD, ALLOW, 24 | AUTHORIZATION, CACHE_CONTROL, CONNECTION, CONTENT_DISPOSITION, 25 | CONTENT_ENCODING, CONTENT_LANGUAGE, CONTENT_LENGTH, CONTENT_LOCATION, 26 | CONTENT_RANGE, CONTENT_SECURITY_POLICY, 27 | CONTENT_SECURITY_POLICY_REPORT_ONLY, CONTENT_TYPE, DATE, ETAG, EXPECT, 28 | EXPIRES, FORWARDED, FROM, HOST, IF_MATCH, IF_MODIFIED_SINCE, 29 | IF_NONE_MATCH, IF_RANGE, IF_UNMODIFIED_SINCE, LAST_MODIFIED, LINK, 30 | LOCATION, ORIGIN, PRAGMA, RANGE, REFERER, REFERRER_POLICY, REFRESH, 31 | STRICT_TRANSPORT_SECURITY, TE, TRANSFER_ENCODING, UPGRADE, USER_AGENT, 32 | VARY 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /core/http/src/parse/uri/mod.rs: -------------------------------------------------------------------------------- 1 | mod parser; 2 | mod error; 3 | pub(crate) mod tables; 4 | 5 | #[cfg(test)] mod tests; 6 | 7 | use crate::uri::{Uri, Origin, Absolute, Authority, Reference, Asterisk}; 8 | 9 | use self::parser::*; 10 | 11 | pub use self::error::Error; 12 | 13 | type RawInput<'a> = pear::input::Pear>; 14 | 15 | #[inline] 16 | pub fn from_str(s: &str) -> Result, Error<'_>> { 17 | Ok(parse!(uri: RawInput::new(s.as_bytes()))?) 18 | } 19 | 20 | #[inline] 21 | pub fn origin_from_str(s: &str) -> Result, Error<'_>> { 22 | Ok(parse!(origin: RawInput::new(s.as_bytes()))?) 23 | } 24 | 25 | #[inline] 26 | pub fn authority_from_str(s: &str) -> Result, Error<'_>> { 27 | Ok(parse!(authority: RawInput::new(s.as_bytes()))?) 28 | } 29 | 30 | #[inline] 31 | pub fn authority_from_bytes(s: &[u8]) -> Result, Error<'_>> { 32 | Ok(parse!(authority: RawInput::new(s))?) 33 | } 34 | 35 | #[inline] 36 | pub fn scheme_from_str(s: &str) -> Result<&str, Error<'_>> { 37 | let _validated = parse!(scheme: RawInput::new(s.as_bytes()))?; 38 | Ok(s) 39 | } 40 | 41 | #[inline] 42 | pub fn absolute_from_str(s: &str) -> Result, Error<'_>> { 43 | Ok(parse!(absolute: RawInput::new(s.as_bytes()))?) 44 | } 45 | 46 | #[inline] 47 | pub fn asterisk_from_str(s: &str) -> Result> { 48 | Ok(parse!(asterisk: RawInput::new(s.as_bytes()))?) 49 | } 50 | 51 | #[inline] 52 | pub fn reference_from_str(s: &str) -> Result, Error<'_>> { 53 | Ok(parse!(reference: RawInput::new(s.as_bytes()))?) 54 | } 55 | -------------------------------------------------------------------------------- /examples/chat/static/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Rocket Rooms 6 | 7 | 8 | 9 | 10 | 11 |
12 | 27 | 28 |
29 | 30 |
31 | 37 |
38 | 39 |
40 | 42 | 44 | 45 |
46 |
47 |
48 | 49 | 50 | -------------------------------------------------------------------------------- /core/codegen/tests/route-data.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] extern crate rocket; 2 | 3 | use rocket::{Request, Data}; 4 | use rocket::local::blocking::Client; 5 | use rocket::data::{self, FromData}; 6 | use rocket::http::ContentType; 7 | use rocket::form::Form; 8 | 9 | // Test that the data parameters works as expected. 10 | 11 | #[derive(FromForm)] 12 | struct Inner<'r> { 13 | field: &'r str 14 | } 15 | 16 | struct Simple<'r>(&'r str); 17 | 18 | #[async_trait] 19 | impl<'r> FromData<'r> for Simple<'r> { 20 | type Error = std::io::Error; 21 | 22 | async fn from_data(req: &'r Request<'_>, data: Data<'r>) -> data::Outcome<'r, Self> { 23 | <&'r str>::from_data(req, data).await.map(Simple) 24 | } 25 | } 26 | 27 | #[post("/f", data = "
")] 28 | fn form<'r>(form: Form>) -> &'r str { form.into_inner().field } 29 | 30 | #[post("/s", data = "")] 31 | fn simple<'r>(simple: Simple<'r>) -> &'r str { simple.0 } 32 | 33 | #[test] 34 | fn test_data() { 35 | let rocket = rocket::build().mount("/", routes![form, simple]); 36 | let client = Client::debug(rocket).unwrap(); 37 | 38 | let response = client.post("/f") 39 | .header(ContentType::Form) 40 | .body("field=this%20is%20here") 41 | .dispatch(); 42 | 43 | assert_eq!(response.into_string().unwrap(), "this is here"); 44 | 45 | let response = client.post("/s").body("this is here").dispatch(); 46 | assert_eq!(response.into_string().unwrap(), "this is here"); 47 | 48 | let response = client.post("/s").body("this%20is%20here").dispatch(); 49 | assert_eq!(response.into_string().unwrap(), "this%20is%20here"); 50 | } 51 | -------------------------------------------------------------------------------- /core/lib/tests/replace-content-type-518.rs: -------------------------------------------------------------------------------- 1 | use rocket::{Rocket, Build}; 2 | use rocket::{fairing::AdHoc, http::ContentType, local::blocking::Client}; 3 | 4 | #[rocket::post("/", data = "<_data>", format = "json")] 5 | fn index(_data: rocket::Data<'_>) -> &'static str { "json" } 6 | 7 | #[rocket::post("/", data = "<_data>", rank = 2)] 8 | fn other_index(_data: rocket::Data<'_>) -> &'static str { "other" } 9 | 10 | fn rocket() -> Rocket { 11 | rocket::build() 12 | .mount("/", rocket::routes![index, other_index]) 13 | .attach(AdHoc::on_request("Change CT", |req, _| Box::pin(async move { 14 | let need_ct = req.content_type().is_none(); 15 | if req.uri().path().starts_with("/add") { 16 | req.set_uri(rocket::uri!(index)); 17 | if need_ct { req.add_header(ContentType::JSON); } 18 | } else if need_ct { 19 | req.replace_header(ContentType::JSON); 20 | } 21 | }))) 22 | } 23 | 24 | #[test] 25 | fn check_fairing_changes_content_type() { 26 | let client = Client::debug(rocket()).unwrap(); 27 | let response = client.post("/").header(ContentType::PNG).dispatch(); 28 | assert_eq!(response.into_string().unwrap(), "other"); 29 | 30 | let response = client.post("/").dispatch(); 31 | assert_eq!(response.into_string().unwrap(), "json"); 32 | 33 | let response = client.post("/add").dispatch(); 34 | assert_eq!(response.into_string().unwrap(), "json"); 35 | 36 | let response = client.post("/add").header(ContentType::HTML).dispatch(); 37 | assert_eq!(response.into_string().unwrap(), "other"); 38 | } 39 | -------------------------------------------------------------------------------- /scripts/publish.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | set -e 3 | 4 | # 5 | # Publishes the current versions of all Rocket crates to crates.io. 6 | # 7 | 8 | # Brings in _ROOT, _DIR, _DIRS globals. 9 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 10 | source "${SCRIPT_DIR}/config.sh" 11 | 12 | function strip_dev_dependencies() { 13 | perl -i.bak -p0e 's/\[dev-dependencies\].*//smg' "${1}/Cargo.toml" 14 | } 15 | 16 | function restore_dev_dependencies() { 17 | mv "${1}/Cargo.toml.bak" "${1}/Cargo.toml" 18 | } 19 | 20 | if ! [ -z "$(git status --porcelain)" ]; then 21 | echo "There are uncommitted changes! Aborting." 22 | exit 1 23 | fi 24 | 25 | # Ensure everything passes before trying to publish. 26 | echo ":::: Running complete test suite..." 27 | cargo clean 28 | bash "${SCRIPT_DIR}/test.sh" +stable --all 29 | bash "${SCRIPT_DIR}/test.sh" +stable --all --release 30 | 31 | # Temporarily remove dev-dependencies so crates.io verifies. 32 | echo ":::: Stripping [dev-dependencies]..." 33 | for dir in "${ALL_CRATE_ROOTS[@]}"; do 34 | strip_dev_dependencies "${dir}" 35 | done 36 | 37 | # Publish all the things. 38 | for dir in "${ALL_CRATE_ROOTS[@]}"; do 39 | pushd "${dir}" 40 | echo ":::: Publishing '${dir}'..." 41 | # We already checked things ourselves. Don't spend time reverifying. 42 | cargo publish --no-verify --allow-dirty ${@:1} 43 | # Give the index some time to update so the deps are there if we need them. 44 | sleep 5 45 | popd 46 | done 47 | 48 | # Restore dev-dependencies. 49 | echo ":::: Restoring [dev-dependencies]..." 50 | for dir in "${ALL_CRATE_ROOTS[@]}"; do 51 | restore_dev_dependencies "${dir}" 52 | done 53 | -------------------------------------------------------------------------------- /contrib/sync_db_pools/lib/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rocket_sync_db_pools" 3 | version = "0.1.0-rc.1" 4 | authors = ["Sergio Benitez "] 5 | description = "Rocket async database pooling support for sync database drivers." 6 | repository = "https://github.com/SergioBenitez/Rocket/tree/v0.5-rc/contrib/sync_db_pools" 7 | readme = "../README.md" 8 | keywords = ["rocket", "framework", "database", "pools"] 9 | license = "MIT OR Apache-2.0" 10 | edition = "2018" 11 | 12 | [features] 13 | diesel_sqlite_pool = ["diesel/sqlite", "diesel/r2d2"] 14 | diesel_postgres_pool = ["diesel/postgres", "diesel/r2d2"] 15 | diesel_mysql_pool = ["diesel/mysql", "diesel/r2d2"] 16 | sqlite_pool = ["rusqlite", "r2d2_sqlite"] 17 | postgres_pool = ["postgres", "r2d2_postgres"] 18 | memcache_pool = ["memcache", "r2d2-memcache"] 19 | 20 | [dependencies] 21 | r2d2 = "0.8" 22 | tokio = { version = "1.6.1", features = ["rt", "rt-multi-thread"] } 23 | serde = { version = "1.0", features = ["derive"] } 24 | 25 | diesel = { version = "1.0", default-features = false, optional = true } 26 | 27 | postgres = { version = "0.19", optional = true } 28 | r2d2_postgres = { version = "0.18", optional = true } 29 | 30 | rusqlite = { version = "0.25", optional = true } 31 | r2d2_sqlite = { version = "0.18", optional = true } 32 | 33 | memcache = { version = "0.15", optional = true } 34 | r2d2-memcache = { version = "0.6", optional = true } 35 | 36 | [dependencies.rocket_sync_db_pools_codegen] 37 | version = "0.1.0-rc.1" 38 | path = "../codegen" 39 | 40 | [dependencies.rocket] 41 | version = "0.5.0-rc.1" 42 | path = "../../../core/lib" 43 | default-features = false 44 | 45 | [package.metadata.docs.rs] 46 | all-features = true 47 | -------------------------------------------------------------------------------- /core/http/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![recursion_limit="512"] 2 | 3 | #![warn(rust_2018_idioms)] 4 | #![warn(missing_docs)] 5 | 6 | //! Types that map to concepts in HTTP. 7 | //! 8 | //! This module exports types that map to HTTP concepts or to the underlying 9 | //! HTTP library when needed. Because the underlying HTTP library is likely to 10 | //! change (see [#17]), types in [`hyper`] should be considered unstable. 11 | //! 12 | //! [#17]: https://github.com/SergioBenitez/Rocket/issues/17 13 | 14 | #[macro_use] 15 | extern crate pear; 16 | 17 | pub mod hyper; 18 | pub mod uri; 19 | pub mod ext; 20 | 21 | #[macro_use] 22 | mod docify; 23 | 24 | #[macro_use] 25 | mod header; 26 | mod method; 27 | mod status; 28 | mod raw_str; 29 | mod parse; 30 | mod listener; 31 | 32 | /// Case-preserving, ASCII case-insensitive string types. 33 | /// 34 | /// An _uncased_ string is case-preserving. That is, the string itself contains 35 | /// cased characters, but comparison (including ordering, equality, and hashing) 36 | /// is ASCII case-insensitive. **Note:** the `alloc` feature _is_ enabled. 37 | pub mod uncased { 38 | #[doc(inline)] pub use uncased::*; 39 | } 40 | 41 | // Types that we expose for use _only_ by core. Please don't use this. 42 | #[doc(hidden)] 43 | #[path = "."] 44 | pub mod private { 45 | pub use crate::parse::Indexed; 46 | pub use smallvec::{SmallVec, Array}; 47 | pub use crate::listener::{bind_tcp, Incoming, Listener, Connection, RawCertificate}; 48 | pub use cookie; 49 | } 50 | 51 | #[doc(hidden)] 52 | #[cfg(feature = "tls")] 53 | pub mod tls; 54 | 55 | pub use crate::method::Method; 56 | pub use crate::status::{Status, StatusClass}; 57 | pub use crate::raw_str::{RawStr, RawStrBuf}; 58 | pub use crate::header::*; 59 | -------------------------------------------------------------------------------- /core/lib/tests/catcher-cookies-1213.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] extern crate rocket; 2 | 3 | use rocket::request::Request; 4 | use rocket::http::{Cookie, CookieJar}; 5 | 6 | #[catch(404)] 7 | fn not_found(request: &Request) -> &'static str { 8 | request.cookies().add(Cookie::new("not_found", "404")); 9 | "404 - Not Found" 10 | } 11 | 12 | #[get("/")] 13 | fn index(cookies: &CookieJar<'_>) -> &'static str { 14 | cookies.add(Cookie::new("index", "hi")); 15 | "Hello, world!" 16 | } 17 | 18 | mod tests { 19 | use super::*; 20 | use rocket::local::blocking::Client; 21 | use rocket::fairing::AdHoc; 22 | 23 | #[test] 24 | fn error_catcher_sets_cookies() { 25 | let rocket = rocket::build() 26 | .mount("/", routes![index]) 27 | .register("/", catchers![not_found]) 28 | .attach(AdHoc::on_request("Add Cookie", |req, _| Box::pin(async move { 29 | req.cookies().add(Cookie::new("fairing", "woo")); 30 | }))); 31 | 32 | let client = Client::debug(rocket).unwrap(); 33 | 34 | // Check that the index returns the `index` and `fairing` cookie. 35 | let response = client.get("/").dispatch(); 36 | let cookies = response.cookies(); 37 | assert_eq!(cookies.iter().count(), 2); 38 | assert_eq!(cookies.get("index").unwrap().value(), "hi"); 39 | assert_eq!(cookies.get("fairing").unwrap().value(), "woo"); 40 | 41 | // Check that the catcher returns only the `not_found` cookie. 42 | let response = client.get("/not-existent").dispatch(); 43 | let cookies = response.cookies(); 44 | assert_eq!(cookies.iter().count(), 1); 45 | assert_eq!(cookies.get("not_found").unwrap().value(), "404"); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /contrib/sync_db_pools/codegen/tests/ui-fail-stable/database-syntax.stderr: -------------------------------------------------------------------------------- 1 | error: unexpected end of input, expected string literal 2 | --> $DIR/database-syntax.rs:6:1 3 | | 4 | 6 | #[database] 5 | | ^^^^^^^^^^^ 6 | | 7 | = note: this error originates in the attribute macro `database` (in Nightly builds, run with -Z macro-backtrace for more info) 8 | 9 | error: expected string literal 10 | --> $DIR/database-syntax.rs:9:12 11 | | 12 | 9 | #[database(1)] 13 | | ^ 14 | 15 | error: expected string literal 16 | --> $DIR/database-syntax.rs:12:12 17 | | 18 | 12 | #[database(123)] 19 | | ^^^ 20 | 21 | error: unexpected token 22 | --> $DIR/database-syntax.rs:15:20 23 | | 24 | 15 | #[database("hello" "hi")] 25 | | ^^^^ 26 | 27 | error: `database` attribute can only be used on structs 28 | --> $DIR/database-syntax.rs:19:1 29 | | 30 | 19 | enum Foo { } 31 | | ^^^^ 32 | 33 | error: `database` attribute can only be applied to structs with exactly one unnamed field 34 | --- help: example: `struct MyDatabase(diesel::SqliteConnection);` 35 | --> $DIR/database-syntax.rs:22:11 36 | | 37 | 22 | struct Bar(diesel::SqliteConnection, diesel::SqliteConnection); 38 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 39 | 40 | error: `database` attribute can only be used on structs 41 | --> $DIR/database-syntax.rs:25:1 42 | | 43 | 25 | union Baz { } 44 | | ^^^^^ 45 | 46 | error: `database` attribute cannot be applied to structs with generics 47 | --> $DIR/database-syntax.rs:28:9 48 | | 49 | 28 | struct E<'r>(&'r str); 50 | | ^ 51 | 52 | error: `database` attribute cannot be applied to structs with generics 53 | --> $DIR/database-syntax.rs:31:9 54 | | 55 | 31 | struct F(T); 56 | | ^ 57 | -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail/typed-uris-bad-params.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] extern crate rocket; 2 | 3 | use rocket::http::CookieJar; 4 | 5 | #[post("/")] 6 | fn has_one(id: i32) { } 7 | 8 | #[post("/")] 9 | fn has_one_guarded(cookies: &CookieJar<'_>, id: i32) { } 10 | 11 | #[post("/?")] 12 | fn has_two(cookies: &CookieJar<'_>, id: i32, name: String) { } 13 | 14 | #[post("//")] 15 | fn optionals(id: Option, name: Result) { } 16 | 17 | #[post("/<_>")] 18 | fn ignored() { } 19 | 20 | fn main() { 21 | uri!(has_one); 22 | uri!(has_one()); 23 | 24 | uri!(has_one(1, 23)); 25 | uri!(has_one("Hello", 23, )); 26 | uri!(has_one_guarded("hi", 100)); 27 | 28 | uri!(has_two(10, "hi", "there")); 29 | uri!(has_two(10)); 30 | 31 | uri!(has_one(id = 100, name = "hi")); 32 | 33 | uri!(has_one(name = 100, id = 100)); 34 | 35 | uri!(has_one(name = 100, age = 50, id = 100)); 36 | 37 | uri!(has_one(name = 100, age = 50, id = 100, id = 50)); 38 | 39 | uri!(has_one(id = 100, id = 100)); 40 | 41 | uri!(has_one(id = 100, id = 100, )); 42 | 43 | uri!(has_one(name = "hi")); 44 | 45 | uri!(has_one_guarded(cookies = "hi", id = 100)); 46 | 47 | uri!(has_one_guarded(id = 100, cookies = "hi")); 48 | 49 | uri!(has_two(id = 100, id = 100, )); 50 | 51 | uri!(has_two(name = "hi")); 52 | 53 | uri!(has_two(cookies = "hi", id = 100, id = 10, id = 10)); 54 | 55 | uri!(has_two(id = 100, cookies = "hi")); 56 | 57 | uri!(optionals(id = _, name = "bob".into())); 58 | 59 | uri!(optionals(id = 10, name = _)); 60 | 61 | uri!(ignored(_)); 62 | 63 | uri!(ignored(_ = 10)); 64 | 65 | uri!(ignored(10, 20)); 66 | 67 | uri!(ignored(num = 10)); 68 | 69 | uri!(ignored(10, "10")); 70 | } 71 | -------------------------------------------------------------------------------- /core/lib/tests/many-cookie-jars-at-once.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] extern crate rocket; 2 | 3 | use rocket::http::{Cookie, CookieJar}; 4 | 5 | #[post("/")] 6 | fn multi_add(jar_a: &CookieJar<'_>, jar_b: &CookieJar<'_>) { 7 | jar_a.add(Cookie::new("a", "v1")); 8 | jar_b.add(Cookie::new("b", "v2")); 9 | } 10 | 11 | #[get("/")] 12 | fn multi_get(jar_a: &CookieJar<'_>, jar_b: &CookieJar<'_>, jar_c: &CookieJar<'_>) -> String { 13 | let (a, a2, a3) = (jar_a.get("a"), jar_b.get("a"), jar_c.get("a")); 14 | let (b, b2, b3) = (jar_a.get("b"), jar_b.get("b"), jar_c.get("b")); 15 | assert_eq!(a, a2); assert_eq!(a2, a3); 16 | assert_eq!(b, b2); assert_eq!(b2, b3); 17 | format!("{}{}", a.unwrap().value(), b.unwrap().value()) 18 | } 19 | 20 | #[cfg(test)] 21 | mod many_cookie_jars_tests { 22 | use super::*; 23 | use rocket::{Rocket, Build}; 24 | use rocket::local::blocking::Client; 25 | 26 | fn rocket() -> Rocket { 27 | rocket::build().mount("/", routes![multi_add, multi_get]) 28 | } 29 | 30 | #[test] 31 | fn test_mutli_add() { 32 | let client = Client::debug(rocket()).unwrap(); 33 | let response = client.post("/").dispatch(); 34 | let cookies = response.cookies(); 35 | assert_eq!(cookies.iter().count(), 2); 36 | assert_eq!(cookies.get("a").unwrap().value(), "v1"); 37 | assert_eq!(cookies.get("b").unwrap().value(), "v2"); 38 | } 39 | 40 | #[test] 41 | fn test_mutli_get() { 42 | let client = Client::debug(rocket()).unwrap(); 43 | let response = client.get("/") 44 | .cookie(Cookie::new("a", "a_val")) 45 | .cookie(Cookie::new("b", "hi!")) 46 | .dispatch(); 47 | 48 | assert_eq!(response.into_string().unwrap(), "a_valhi!"); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /core/codegen/tests/route-ranking.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] extern crate rocket; 2 | 3 | use rocket::local::blocking::Client; 4 | 5 | // Test that manual/auto ranking works as expected. 6 | 7 | #[get("/<_number>")] 8 | fn get0(_number: u8) -> &'static str { "0" } 9 | 10 | #[get("/<_number>", rank = 1)] 11 | fn get1(_number: u16) -> &'static str { "1" } 12 | 13 | #[get("/<_number>", rank = 2)] 14 | fn get2(_number: u32) -> &'static str { "2" } 15 | 16 | #[get("/<_number>", rank = 3)] 17 | fn get3(_number: u64) -> &'static str { "3" } 18 | 19 | #[test] 20 | fn test_ranking() { 21 | let rocket = rocket::build().mount("/", routes![get0, get1, get2, get3]); 22 | let client = Client::debug(rocket).unwrap(); 23 | 24 | let response = client.get("/0").dispatch(); 25 | assert_eq!(response.into_string().unwrap(), "0"); 26 | 27 | let response = client.get(format!("/{}", 1 << 8)).dispatch(); 28 | assert_eq!(response.into_string().unwrap(), "1"); 29 | 30 | let response = client.get(format!("/{}", 1 << 16)).dispatch(); 31 | assert_eq!(response.into_string().unwrap(), "2"); 32 | 33 | let response = client.get(format!("/{}", 1u64 << 32)).dispatch(); 34 | assert_eq!(response.into_string().unwrap(), "3"); 35 | } 36 | 37 | // Test a collision due to same auto rank. 38 | 39 | #[get("/<_n>")] 40 | fn get0b(_n: u8) { } 41 | 42 | #[test] 43 | fn test_rank_collision() { 44 | use rocket::error::ErrorKind; 45 | 46 | let rocket = rocket::build().mount("/", routes![get0, get0b]); 47 | let client_result = Client::debug(rocket); 48 | match client_result.as_ref().map_err(|e| e.kind()) { 49 | Err(ErrorKind::Collisions(..)) => { /* o.k. */ }, 50 | Ok(_) => panic!("client succeeded unexpectedly"), 51 | Err(e) => panic!("expected collision, got {}", e) 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /core/codegen/src/bang/test_guide.rs: -------------------------------------------------------------------------------- 1 | use std::path::Path; 2 | use std::error::Error; 3 | 4 | use syn::{self, Ident, LitStr}; 5 | use devise::ext::SpanDiagnosticExt; 6 | use proc_macro2::TokenStream; 7 | 8 | pub fn _macro(input: proc_macro::TokenStream) -> devise::Result { 9 | let root_glob = syn::parse::(input)?; 10 | let tests = entry_to_tests(&root_glob) 11 | .map_err(|e| root_glob.span().error(format!("failed to read: {}", e)))?; 12 | 13 | Ok(quote!(#(#tests)*)) 14 | } 15 | 16 | fn entry_to_tests(root_glob: &LitStr) -> Result, Box> { 17 | let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").expect("MANIFEST_DIR"); 18 | let full_glob = Path::new(&manifest_dir).join(&root_glob.value()).display().to_string(); 19 | 20 | let mut tests = vec![]; 21 | for path in glob::glob(&full_glob).map_err(Box::new)? { 22 | let path = path.map_err(Box::new)?; 23 | let name = path.file_name() 24 | .and_then(|f| f.to_str()) 25 | .map(|name| name.trim_matches(|c| char::is_numeric(c) || c == '-') 26 | .replace(|c| c == '-' || c == '.', "_")) 27 | .ok_or("invalid file name")?; 28 | 29 | let ident = Ident::new(&name.to_lowercase(), root_glob.span()); 30 | let full_path = Path::new(&manifest_dir).join(&path).display().to_string(); 31 | tests.push(quote_spanned!(root_glob.span() => 32 | mod #ident { 33 | macro_rules! doc_comment { ($x:expr) => (#[doc = $x] extern {}); } 34 | doc_comment!(include_str!(#full_path)); 35 | } 36 | )); 37 | } 38 | 39 | if tests.is_empty() { 40 | return Err(format!("glob '{}' evaluates to 0 files", full_glob).into()); 41 | } 42 | 43 | Ok(tests) 44 | } 45 | -------------------------------------------------------------------------------- /contrib/sync_db_pools/codegen/tests/ui-fail-nightly/database-syntax.stderr: -------------------------------------------------------------------------------- 1 | error: unexpected end of input, expected string literal 2 | --> $DIR/database-syntax.rs:6:1 3 | | 4 | 6 | #[database] 5 | | ^^^^^^^^^^^ 6 | | 7 | = note: this error originates in the attribute macro `database` (in Nightly builds, run with -Z macro-backtrace for more info) 8 | 9 | error: expected string literal 10 | --> $DIR/database-syntax.rs:9:12 11 | | 12 | 9 | #[database(1)] 13 | | ^ 14 | 15 | error: expected string literal 16 | --> $DIR/database-syntax.rs:12:12 17 | | 18 | 12 | #[database(123)] 19 | | ^^^ 20 | 21 | error: unexpected token 22 | --> $DIR/database-syntax.rs:15:20 23 | | 24 | 15 | #[database("hello" "hi")] 25 | | ^^^^ 26 | 27 | error: `database` attribute can only be used on structs 28 | --> $DIR/database-syntax.rs:19:1 29 | | 30 | 19 | enum Foo { } 31 | | ^^^^^^^^^^^^^ 32 | 33 | error: `database` attribute can only be applied to structs with exactly one unnamed field 34 | --> $DIR/database-syntax.rs:22:11 35 | | 36 | 22 | struct Bar(diesel::SqliteConnection, diesel::SqliteConnection); 37 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 38 | | 39 | = help: example: `struct MyDatabase(diesel::SqliteConnection);` 40 | 41 | error: `database` attribute can only be used on structs 42 | --> $DIR/database-syntax.rs:25:1 43 | | 44 | 25 | union Baz { } 45 | | ^^^^^^^^^^^^^^ 46 | 47 | error: `database` attribute cannot be applied to structs with generics 48 | --> $DIR/database-syntax.rs:28:9 49 | | 50 | 28 | struct E<'r>(&'r str); 51 | | ^^^^ 52 | 53 | error: `database` attribute cannot be applied to structs with generics 54 | --> $DIR/database-syntax.rs:31:9 55 | | 56 | 31 | struct F(T); 57 | | ^^^ 58 | -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail-nightly/route-warnings.stderr: -------------------------------------------------------------------------------- 1 | warning: 'application/x-custom' is not a known media type 2 | --> $DIR/route-warnings.rs:7:21 3 | | 4 | 7 | #[get("/", format = "application/x-custom")] 5 | | ^^^^^^^^^^^^^^^^^^^^^^ 6 | 7 | warning: 'x-custom/plain' is not a known media type 8 | --> $DIR/route-warnings.rs:10:21 9 | | 10 | 10 | #[get("/", format = "x-custom/plain")] 11 | | ^^^^^^^^^^^^^^^^ 12 | 13 | warning: 'x-custom/x-custom' is not a known media type 14 | --> $DIR/route-warnings.rs:13:21 15 | | 16 | 13 | #[get("/", format = "x-custom/x-custom")] 17 | | ^^^^^^^^^^^^^^^^^^^ 18 | 19 | warning: `data` used with non-payload-supporting method 20 | --> $DIR/route-warnings.rs:18:12 21 | | 22 | 18 | #[get("/", data = "<_foo>")] 23 | | ^^^^^^^^^^^^^^^ 24 | | 25 | note: 'GET' does not typically support payloads 26 | --> $DIR/route-warnings.rs:18:3 27 | | 28 | 18 | #[get("/", data = "<_foo>")] 29 | | ^^^ 30 | = note: this warning originates in the attribute macro `get` (in Nightly builds, run with -Z macro-backtrace for more info) 31 | 32 | warning: `data` used with non-payload-supporting method 33 | --> $DIR/route-warnings.rs:21:13 34 | | 35 | 21 | #[head("/", data = "<_foo>")] 36 | | ^^^^^^^^^^^^^^^ 37 | | 38 | note: 'HEAD' does not typically support payloads 39 | --> $DIR/route-warnings.rs:21:3 40 | | 41 | 21 | #[head("/", data = "<_foo>")] 42 | | ^^^^ 43 | = note: this warning originates in the attribute macro `head` (in Nightly builds, run with -Z macro-backtrace for more info) 44 | 45 | error: checking for warnings! 46 | --> $DIR/route-warnings.rs:25:5 47 | | 48 | 25 | compile_error!("checking for warnings!") 49 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 50 | -------------------------------------------------------------------------------- /site/README.md: -------------------------------------------------------------------------------- 1 | # Rocket Website Source 2 | 3 | This directory contains the source files for the content on [Rocket's 4 | website](https://rocket.rs). 5 | 6 | ## Contents 7 | 8 | This directory contains the following: 9 | 10 | * `index.toml` - Source data for the index. 11 | * `overview.toml` - Source data for the overview page (`overview/`). 12 | * `news/index.toml` - Source data for the news page (`news/`). 13 | * `news/*.md` - News articles linked to from `news/index.toml`. 14 | * `guide/*.md` - Guide pages linked to from `guide.md`. 15 | 16 | [Rocket Programming Guide]: https://rocket.rs/v0.5-rc/guide/ 17 | 18 | ### Guide Links 19 | 20 | Cross-linking guide pages is accomplished via relative links. Outside of the 21 | index, this is: `../{page}#anchor`. For instance, to link to the **Quickstart > 22 | Running Examples** page, use `../quickstart#running-examples`. 23 | 24 | ### Aliases 25 | 26 | Aliases are shorthand URLs that start with `@` (e.g, `@api`). They are used 27 | throughout the guide to simplify versioning URLs to Rocket's source code and the 28 | Rocket API. They are replaced at build time with a URL prefix. At present, the 29 | following aliases are available, where `${version}` is Rocket's version string 30 | at the time of compilation: 31 | 32 | * `@example`: https://github.com/SergioBenitez/Rocket/tree/${version}/examples 33 | * `@github`: https://github.com/SergioBenitez/Rocket/tree/${version} 34 | * `@api`: https://api.rocket.rs/${version} 35 | 36 | For example, to link to `Rocket::launch()`, you might write: 37 | 38 | ```md 39 | Launch an instance of your application using the [`launch()`] method. 40 | 41 | [`launch()`]: @api/rocket/struct.Rocket.html#method.launch 42 | ``` 43 | 44 | ## License 45 | 46 | The Rocket website source is licensed under the [GNU General Public License v3.0](LICENSE). 47 | -------------------------------------------------------------------------------- /examples/templating/src/hbs.rs: -------------------------------------------------------------------------------- 1 | use rocket::Request; 2 | use rocket::response::Redirect; 3 | 4 | use rocket_dyn_templates::{Template, handlebars, context}; 5 | 6 | use self::handlebars::{Handlebars, JsonRender}; 7 | 8 | #[get("/")] 9 | pub fn index() -> Redirect { 10 | Redirect::to(uri!("/hbs", hello(name = "Your Name"))) 11 | } 12 | 13 | #[get("/hello/")] 14 | pub fn hello(name: &str) -> Template { 15 | Template::render("hbs/index", context! { 16 | title: "Hello", 17 | name: Some(name), 18 | items: vec!["One", "Two", "Three"], 19 | }) 20 | } 21 | 22 | #[get("/about")] 23 | pub fn about() -> Template { 24 | Template::render("hbs/about.html", context! { 25 | title: "About", 26 | parent: "hbs/layout", 27 | }) 28 | } 29 | 30 | #[catch(404)] 31 | pub fn not_found(req: &Request<'_>) -> Template { 32 | Template::render("hbs/error/404", context! { 33 | uri: req.uri() 34 | }) 35 | } 36 | 37 | fn wow_helper( 38 | h: &handlebars::Helper<'_, '_>, 39 | _: &handlebars::Handlebars, 40 | _: &handlebars::Context, 41 | _: &mut handlebars::RenderContext<'_, '_>, 42 | out: &mut dyn handlebars::Output 43 | ) -> handlebars::HelperResult { 44 | if let Some(param) = h.param(0) { 45 | out.write("")?; 46 | out.write(¶m.value().render())?; 47 | out.write("")?; 48 | } 49 | 50 | Ok(()) 51 | } 52 | 53 | pub fn customize(hbs: &mut Handlebars) { 54 | hbs.register_helper("wow", Box::new(wow_helper)); 55 | hbs.register_template_string("hbs/about.html", r#" 56 | {{#*inline "page"}} 57 | 58 |
59 |

About - Here's another page!

60 |
61 | 62 | {{/inline}} 63 | {{> hbs/layout}} 64 | "#).expect("valid HBS template"); 65 | } 66 | -------------------------------------------------------------------------------- /core/lib/tests/segments-issues-41-86.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] extern crate rocket; 2 | 3 | use rocket::http::uri::{Segments, fmt::Path}; 4 | 5 | #[get("/test/")] 6 | fn test(path: Segments<'_, Path>) -> String { 7 | path.collect::>().join("/") 8 | } 9 | 10 | #[get("/two/")] 11 | fn two(path: Segments<'_, Path>) -> String { 12 | path.collect::>().join("/") 13 | } 14 | 15 | #[get("/one/two/")] 16 | fn one_two(path: Segments<'_, Path>) -> String { 17 | path.collect::>().join("/") 18 | } 19 | 20 | #[get("/", rank = 2)] 21 | fn none(path: Segments<'_, Path>) -> String { 22 | path.collect::>().join("/") 23 | } 24 | 25 | #[get("/static//is/")] 26 | fn dual(user: String, path: Segments<'_, Path>) -> String { 27 | user + "/is/" + &path.collect::>().join("/") 28 | } 29 | 30 | mod tests { 31 | use super::*; 32 | use rocket::local::blocking::Client; 33 | 34 | #[test] 35 | fn segments_works() { 36 | let rocket = rocket::build() 37 | .mount("/", routes![test, two, one_two, none, dual]) 38 | .mount("/point", routes![test, two, one_two, dual]); 39 | let client = Client::debug(rocket).unwrap(); 40 | 41 | // We construct a path that matches each of the routes above. We ensure the 42 | // prefix is stripped, confirming that dynamic segments are working. 43 | for prefix in &["", "/test", "/two", "/one/two", 44 | "/point/test", "/point/two", "/point/one/two", 45 | "/static", "/point/static"] 46 | { 47 | let path = "this/is/the/path/we/want"; 48 | let response = client.get(format!("{}/{}", prefix, path)).dispatch(); 49 | assert_eq!(response.into_string(), Some(path.into())); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /core/lib/tests/uri-percent-encoding-issue-808.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] extern crate rocket; 2 | 3 | use rocket::{Rocket, Build}; 4 | use rocket::response::Redirect; 5 | 6 | const NAME: &str = "John[]|\\%@^"; 7 | 8 | #[get("/hello/")] 9 | fn hello(name: String) -> String { 10 | format!("Hello, {}!", name) 11 | } 12 | 13 | #[get("/raw")] 14 | fn raw_redirect() -> Redirect { 15 | Redirect::to(uri!(hello(NAME))) 16 | } 17 | 18 | #[get("/uri")] 19 | fn uri_redirect() -> Redirect { 20 | Redirect::to(uri!(hello(NAME))) 21 | } 22 | 23 | fn rocket() -> Rocket { 24 | rocket::build().mount("/", routes![hello, uri_redirect, raw_redirect]) 25 | } 26 | 27 | mod tests { 28 | use super::*; 29 | use rocket::local::blocking::Client; 30 | use rocket::http::Status; 31 | 32 | #[test] 33 | fn uri_percent_encoding_redirect() { 34 | let expected_location = vec!["/hello/John%5B%5D%7C%5C%25@%5E"]; 35 | let client = Client::debug(rocket()).unwrap(); 36 | 37 | let response = client.get("/raw").dispatch(); 38 | let location: Vec<_> = response.headers().get("location").collect(); 39 | assert_eq!(response.status(), Status::SeeOther); 40 | assert_eq!(&location, &expected_location); 41 | 42 | let response = client.get("/uri").dispatch(); 43 | let location: Vec<_> = response.headers().get("location").collect(); 44 | assert_eq!(response.status(), Status::SeeOther); 45 | assert_eq!(&location, &expected_location); 46 | } 47 | 48 | #[test] 49 | fn uri_percent_encoding_get() { 50 | let client = Client::debug(rocket()).unwrap(); 51 | let response = client.get(uri!(hello(NAME))).dispatch(); 52 | assert_eq!(response.status(), Status::Ok); 53 | assert_eq!(response.into_string().unwrap(), format!("Hello, {}!", NAME)); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /core/lib/tests/conditionally-set-server-header-996.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] extern crate rocket; 2 | 3 | use rocket::http::Header; 4 | 5 | #[derive(Responder)] 6 | struct HeaderOnly((), Header<'static>); 7 | 8 | #[get("/do_not_overwrite")] 9 | fn do_not_overwrite() -> HeaderOnly { 10 | HeaderOnly((), Header::new("Server", "Test")) 11 | } 12 | 13 | #[get("/use_default")] 14 | fn use_default() { } 15 | 16 | mod conditionally_set_server_header { 17 | use super::*; 18 | use rocket::local::blocking::Client; 19 | 20 | #[test] 21 | fn do_not_overwrite_server_header() { 22 | let client = Client::debug_with(routes![do_not_overwrite, use_default]).unwrap(); 23 | 24 | let response = client.get("/do_not_overwrite").dispatch(); 25 | let server = response.headers().get_one("Server"); 26 | assert_eq!(server, Some("Test")); 27 | 28 | let response = client.get("/use_default").dispatch(); 29 | let server = response.headers().get_one("Server"); 30 | assert_eq!(server, Some("Rocket")); 31 | 32 | // Now with a special `Ident`. 33 | 34 | let config = rocket::Config { 35 | ident: rocket::config::Ident::try_new("My Special Server").unwrap(), 36 | ..rocket::Config::debug_default() 37 | }; 38 | 39 | let rocket = rocket::custom(config) 40 | .mount("/", routes![do_not_overwrite, use_default]); 41 | 42 | let client = Client::debug(rocket).unwrap(); 43 | 44 | let response = client.get("/do_not_overwrite").dispatch(); 45 | let server = response.headers().get_one("Server"); 46 | assert_eq!(server, Some("Test")); 47 | 48 | let response = client.get("/use_default").dispatch(); 49 | let server = response.headers().get_one("Server"); 50 | assert_eq!(server, Some("My Special Server")); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /core/codegen/tests/expansion.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] extern crate rocket; 2 | 3 | use rocket::local::blocking::Client; 4 | 5 | #[get("/easy/")] 6 | fn easy(id: i32) -> String { 7 | format!("easy id: {}", id) 8 | } 9 | 10 | macro_rules! make_handler { 11 | () => { 12 | #[get("/hard/")] 13 | fn hard(id: i32) -> String { 14 | format!("hard id: {}", id) 15 | } 16 | } 17 | } 18 | 19 | make_handler!(); 20 | 21 | 22 | macro_rules! foo { 23 | ($addr:expr, $name:ident) => { 24 | #[get($addr)] 25 | fn hi($name: String) -> String { 26 | $name 27 | } 28 | }; 29 | } 30 | 31 | // regression test for `#[get] panicking if used inside a macro 32 | foo!("/hello/", name); 33 | 34 | #[test] 35 | fn test_reexpansion() { 36 | let rocket = rocket::build().mount("/", routes![easy, hard, hi]); 37 | let client = Client::debug(rocket).unwrap(); 38 | 39 | let response = client.get("/easy/327").dispatch(); 40 | assert_eq!(response.into_string().unwrap(), "easy id: 327"); 41 | 42 | let response = client.get("/hard/72").dispatch(); 43 | assert_eq!(response.into_string().unwrap(), "hard id: 72"); 44 | 45 | let response = client.get("/hello/fish").dispatch(); 46 | assert_eq!(response.into_string().unwrap(), "fish"); 47 | } 48 | 49 | macro_rules! index { 50 | ($type:ty) => { 51 | #[get("/")] 52 | fn index(thing: &rocket::State<$type>) -> String { 53 | format!("Thing: {}", thing) 54 | } 55 | } 56 | } 57 | 58 | index!(i32); 59 | 60 | #[test] 61 | fn test_index() { 62 | let rocket = rocket::build().mount("/", routes![index]).manage(100i32); 63 | let client = Client::debug(rocket).unwrap(); 64 | 65 | let response = client.get("/").dispatch(); 66 | assert_eq!(response.into_string().unwrap(), "Thing: 100"); 67 | } 68 | -------------------------------------------------------------------------------- /core/lib/src/request/mod.rs: -------------------------------------------------------------------------------- 1 | //! Types and traits for request parsing and handling. 2 | 3 | mod request; 4 | mod from_param; 5 | mod from_request; 6 | 7 | #[cfg(test)] 8 | mod tests; 9 | 10 | pub use self::request::Request; 11 | pub use self::from_request::{FromRequest, Outcome}; 12 | pub use self::from_param::{FromParam, FromSegments}; 13 | 14 | #[doc(inline)] 15 | pub use crate::response::flash::FlashMessage; 16 | 17 | pub(crate) use self::request::ConnectionMeta; 18 | 19 | crate::export! { 20 | /// Store and immediately retrieve a value `$v` in `$request`'s local cache 21 | /// using a locally generated anonymous type to avoid type conflicts. 22 | /// 23 | /// # Example 24 | /// 25 | /// ```rust 26 | /// use rocket::request::local_cache; 27 | /// # let c = rocket::local::blocking::Client::debug_with(vec![]).unwrap(); 28 | /// # let request = c.get("/"); 29 | /// 30 | /// // The first store into local cache for a given type wins. 31 | /// assert_eq!(request.local_cache(|| String::from("hello")), "hello"); 32 | /// 33 | /// // The following returns the cached, previously stored value for the type. 34 | /// assert_eq!(request.local_cache(|| String::from("goodbye")), "hello"); 35 | /// 36 | /// // This shows that we cannot cache different values of the same type; we 37 | /// // _must_ use a proxy type. To avoid the need to write these manually, use 38 | /// // `local_cache!`, which generates one of the fly. 39 | /// assert_eq!(local_cache!(request, String::from("hello")), "hello"); 40 | /// assert_eq!(local_cache!(request, String::from("goodbye")), "goodbye"); 41 | /// ``` 42 | macro_rules! local_cache { 43 | ($request:expr, $v:expr $(,)?) => ({ 44 | struct Local(T); 45 | &$request.local_cache(move || Local($v)).0 46 | }) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail/async-entry.rs: -------------------------------------------------------------------------------- 1 | #![allow(dead_code)] 2 | 3 | mod main_a { 4 | #[rocket::main] 5 | fn foo() { } 6 | 7 | } 8 | 9 | mod main_b { 10 | #[rocket::main] 11 | async fn foo() { } 12 | 13 | } 14 | 15 | mod main_d { 16 | #[rocket::main] 17 | fn main() { 18 | let _ = rocket::build().launch().await; 19 | } 20 | } 21 | 22 | mod main_f { 23 | #[rocket::main] 24 | async fn main() { 25 | rocket::build() 26 | } 27 | } 28 | 29 | // launch 30 | 31 | mod launch_a { 32 | #[rocket::launch] 33 | async fn rocket() -> String { 34 | let _ = rocket::build().launch().await; 35 | rocket::build() 36 | 37 | } 38 | } 39 | 40 | mod launch_b { 41 | #[rocket::launch] 42 | async fn rocket() -> _ { 43 | let _ = rocket::build().launch().await; 44 | "hi".to_string() 45 | } 46 | } 47 | 48 | mod launch_c { 49 | #[rocket::launch] 50 | fn main() -> rocekt::Rocket { 51 | rocket::build() 52 | } 53 | } 54 | 55 | mod launch_d { 56 | #[rocket::launch] 57 | async fn rocket() { 58 | let _ = rocket::build().launch().await; 59 | rocket::build() 60 | } 61 | } 62 | 63 | mod launch_e { 64 | #[rocket::launch] 65 | fn rocket() { 66 | rocket::build() 67 | } 68 | } 69 | 70 | mod launch_f { 71 | #[rocket::launch] 72 | fn rocket() -> _ { 73 | let _ = rocket::build().launch().await; 74 | rocket::build() 75 | } 76 | } 77 | 78 | mod launch_g { 79 | #[rocket::launch] 80 | fn main() -> &'static str { 81 | let _ = rocket::build().launch().await; 82 | "hi" 83 | } 84 | } 85 | 86 | mod launch_h { 87 | #[rocket::launch] 88 | async fn main() -> _ { 89 | rocket::build() 90 | } 91 | } 92 | 93 | #[rocket::main] 94 | async fn main() -> rocket::Rocket { 95 | rocket::build() 96 | } 97 | -------------------------------------------------------------------------------- /core/lib/tests/mapped-base-issue-1262.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] extern crate rocket; 2 | use rocket::{Rocket, Route, Build}; 3 | 4 | pub fn prepend(prefix: &str, route: Route) -> Route { 5 | route.map_base(|base| format!("{}{}", prefix, base)).unwrap() 6 | } 7 | 8 | pub fn extend_routes(prefix: &str, routes: Vec) -> Vec { 9 | routes.into_iter() 10 | .map(|route| prepend(prefix, route)) 11 | .collect() 12 | } 13 | 14 | mod a { 15 | #[get("/b/")] 16 | fn b(id: u8) -> String { id.to_string() } 17 | 18 | pub fn routes() -> Vec { 19 | super::extend_routes("/a", routes![b]) 20 | } 21 | } 22 | 23 | fn rocket() -> Rocket { 24 | rocket::build().mount("/", a::routes()).mount("/foo", a::routes()) 25 | } 26 | 27 | mod mapped_base_tests { 28 | use rocket::local::blocking::Client; 29 | use rocket::http::Status; 30 | 31 | #[test] 32 | fn only_prefix() { 33 | let client = Client::debug(super::rocket()).unwrap(); 34 | 35 | let response = client.get("/a/b/3").dispatch(); 36 | assert_eq!(response.into_string().unwrap(), "3"); 37 | 38 | let response = client.get("/a/b/239").dispatch(); 39 | assert_eq!(response.into_string().unwrap(), "239"); 40 | 41 | let response = client.get("/b/239").dispatch(); 42 | assert_eq!(response.status(), Status::NotFound); 43 | } 44 | 45 | #[test] 46 | fn prefix_and_base() { 47 | let client = Client::debug(super::rocket()).unwrap(); 48 | 49 | let response = client.get("/foo/a/b/23").dispatch(); 50 | assert_eq!(response.into_string().unwrap(), "23"); 51 | 52 | let response = client.get("/foo/a/b/99").dispatch(); 53 | assert_eq!(response.into_string().unwrap(), "99"); 54 | 55 | let response = client.get("/foo/b/239").dispatch(); 56 | assert_eq!(response.status(), Status::NotFound); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /core/codegen/src/bang/export.rs: -------------------------------------------------------------------------------- 1 | use std::hash::Hash; 2 | 3 | use devise::Spanned; 4 | use devise::ext::SpanDiagnosticExt; 5 | use proc_macro2::{TokenStream, TokenTree, Punct}; 6 | 7 | use crate::syn_ext::IdentExt; 8 | 9 | pub fn _macro(input: proc_macro::TokenStream) -> devise::Result { 10 | let mac: syn::ItemMacro = syn::parse(input)?; 11 | let macro_name = match mac.ident { 12 | Some(ident) => ident, 13 | None => return Err(mac.span().error("expected `macro_rules!`")), 14 | }; 15 | 16 | // We rename the actual `macro_export` macro so we don't accidentally use it 17 | // internally from the auto-imported crate root macro namespace. 18 | let (attrs, def) = (mac.attrs, mac.mac); 19 | let internal_name = macro_name.prepend("___internal_"); 20 | let mod_name = macro_name.uniqueify_with(|mut hasher| def.hash(&mut hasher)); 21 | 22 | let macro_rules_tokens = def.tokens.clone(); 23 | let decl_macro_tokens: TokenStream = def.tokens.into_iter() 24 | .map(|t| match t { 25 | TokenTree::Punct(p) if p.as_char() == ';' => { 26 | let mut token = Punct::new(',', p.spacing()); 27 | token.set_span(p.span()); 28 | TokenTree::Punct(token) 29 | }, 30 | _ => t, 31 | }) 32 | .collect(); 33 | 34 | Ok(quote! { 35 | #[allow(non_snake_case)] 36 | mod #mod_name { 37 | #[doc(hidden)] 38 | #[macro_export] 39 | macro_rules! #internal_name { 40 | #macro_rules_tokens 41 | } 42 | 43 | pub use #internal_name; 44 | } 45 | 46 | #(#attrs)* 47 | #[cfg(all(nightly, doc))] 48 | pub macro #macro_name { 49 | #decl_macro_tokens 50 | } 51 | 52 | #[cfg(not(all(nightly, doc)))] 53 | pub use #mod_name::#internal_name as #macro_name; 54 | }) 55 | } 56 | -------------------------------------------------------------------------------- /examples/pastebin/src/paste_id.rs: -------------------------------------------------------------------------------- 1 | use std::borrow::Cow; 2 | use std::path::{Path, PathBuf}; 3 | 4 | use rocket::http::uri::fmt; 5 | use rocket::request::FromParam; 6 | use rand::{self, Rng}; 7 | 8 | /// Table to retrieve base62 values from. 9 | const BASE62: &[u8] = b"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; 10 | 11 | /// A _probably_ unique paste ID. 12 | #[derive(UriDisplayPath)] 13 | pub struct PasteId<'a>(Cow<'a, str>); 14 | 15 | impl PasteId<'_> { 16 | /// Generate a _probably_ unique ID with `size` characters. For readability, 17 | /// the characters used are from the sets [0-9], [A-Z], [a-z]. The 18 | /// probability of a collision depends on the value of `size` and the number 19 | /// of IDs generated thus far. 20 | pub fn new(size: usize) -> PasteId<'static> { 21 | let mut id = String::with_capacity(size); 22 | let mut rng = rand::thread_rng(); 23 | for _ in 0..size { 24 | id.push(BASE62[rng.gen::() % 62] as char); 25 | } 26 | 27 | PasteId(Cow::Owned(id)) 28 | } 29 | 30 | pub fn file_path(&self) -> PathBuf { 31 | let root = concat!(env!("CARGO_MANIFEST_DIR"), "/", "upload"); 32 | Path::new(root).join(self.0.as_ref()) 33 | } 34 | } 35 | 36 | /// Returns an instance of `PasteId` if the path segment is a valid ID. 37 | /// Otherwise returns the invalid ID as the `Err` value. 38 | impl<'a> FromParam<'a> for PasteId<'a> { 39 | type Error = &'a str; 40 | 41 | fn from_param(param: &'a str) -> Result { 42 | param.chars().all(|c| c.is_ascii_alphanumeric()) 43 | .then(|| PasteId(param.into())) 44 | .ok_or(param) 45 | } 46 | } 47 | 48 | impl<'a> fmt::FromUriParam for PasteId<'_> { 49 | type Target = PasteId<'a>; 50 | 51 | fn from_uri_param(param: &'a str) -> Self::Target { 52 | PasteId(param.into()) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /core/lib/tests/head_handling.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] extern crate rocket; 2 | 3 | use rocket::http::Status; 4 | use rocket::response::content::RawJson; 5 | 6 | #[get("/empty")] 7 | fn empty() -> Status { 8 | Status::NoContent 9 | } 10 | 11 | #[get("/")] 12 | fn index() -> &'static str { 13 | "Hello, world!" 14 | } 15 | 16 | #[head("/other")] 17 | fn other() -> RawJson<&'static str> { 18 | RawJson("{ 'hi': 'hello' }") 19 | } 20 | 21 | mod head_handling_tests { 22 | use super::*; 23 | 24 | use rocket::Route; 25 | use rocket::local::blocking::Client; 26 | use rocket::http::{Status, ContentType}; 27 | 28 | fn routes() -> Vec { 29 | routes![index, empty, other] 30 | } 31 | 32 | #[test] 33 | fn auto_head() { 34 | let client = Client::debug_with(routes()).unwrap(); 35 | let response = client.head("/").dispatch(); 36 | 37 | let content_type: Vec<_> = response.headers().get("Content-Type").collect(); 38 | assert_eq!(content_type, vec![ContentType::Plain.to_string()]); 39 | assert_eq!(response.status(), Status::Ok); 40 | assert_eq!(response.body().preset_size(), Some(13)); 41 | assert!(response.into_bytes().unwrap().is_empty()); 42 | 43 | let response = client.head("/empty").dispatch(); 44 | assert_eq!(response.status(), Status::NoContent); 45 | assert!(response.into_bytes().is_none()); 46 | } 47 | 48 | #[test] 49 | fn user_head() { 50 | let client = Client::debug_with(routes()).unwrap(); 51 | let response = client.head("/other").dispatch(); 52 | 53 | let content_type: Vec<_> = response.headers().get("Content-Type").collect(); 54 | assert_eq!(content_type, vec![ContentType::JSON.to_string()]); 55 | assert_eq!(response.status(), Status::Ok); 56 | assert_eq!(response.body().preset_size(), Some(17)); 57 | assert!(response.into_bytes().unwrap().is_empty()); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /core/codegen/tests/ui-fail/route-path-bad-syntax.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] extern crate rocket; 2 | 3 | // Check that route paths are absolute and normalized. 4 | 5 | #[get("a")] 6 | fn f0() {} 7 | 8 | #[get("")] 9 | fn f1() {} 10 | 11 | #[get("a/b/c")] 12 | fn f2() {} 13 | 14 | #[get("/a///b")] 15 | fn f3() {} 16 | 17 | #[get("/?bat&&")] 18 | fn f4() {} 19 | 20 | #[get("/?bat&&")] 21 | fn f5() {} 22 | 23 | #[get("/a/b//")] 24 | fn f6() {} 25 | 26 | // Check that paths contain only valid URI characters 27 | 28 | #[get("/!@#$%^&*()")] 29 | fn g1() {} 30 | 31 | #[get("/a%20b")] 32 | fn g2() {} 33 | 34 | #[get("/a?a%20b")] 35 | fn g3() {} 36 | 37 | #[get("/a?a+b")] 38 | fn g4() {} 39 | 40 | // Check that all declared parameters are accounted for 41 | 42 | #[get("/")] 43 | fn h0(_name: usize) {} 44 | 45 | #[get("/a?")] 46 | fn h1() {} 47 | 48 | #[post("/a", data = "")] 49 | fn h2() {} 50 | 51 | #[get("/<_r>")] 52 | fn h3() {} 53 | 54 | #[get("/<_r>/")] 55 | fn h4() {} 56 | 57 | 58 | // Check dynamic parameters are valid idents 59 | 60 | #[get("/")] 61 | fn i0() {} 62 | 63 | #[get("/")] 64 | fn i1() {} 65 | 66 | #[get("/")] 67 | fn i2() {} 68 | 69 | #[get("/:")] 70 | fn i3() {} 71 | 72 | // Check that a data parameter is exactly `` 73 | 74 | #[get("/", data = "foo")] 75 | fn j0() {} 76 | 77 | #[get("/", data = "")] 78 | fn j1() {} 79 | 80 | #[get("/", data = "")] 89 | fn k0(_: usize) {} 90 | 91 | // Check that strange dynamic syntax is caught. 92 | 93 | #[get("/<>")] 94 | fn m0() {} 95 | 96 | #[get("/<")] 97 | fn m1() {} 98 | 99 | #[get("/<<<<")] 100 | fn m2() {} 101 | 102 | #[get("/<>name><")] 103 | fn m3() {} 104 | 105 | fn main() { } 106 | -------------------------------------------------------------------------------- /core/lib/tests/flash-lazy-removes-issue-466.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] extern crate rocket; 2 | 3 | use rocket::request::FlashMessage; 4 | use rocket::response::Flash; 5 | 6 | const FLASH_MESSAGE: &str = "Hey! I'm a flash message. :)"; 7 | 8 | #[post("/")] 9 | fn set() -> Flash<&'static str> { 10 | Flash::success("This is the page.", FLASH_MESSAGE) 11 | } 12 | 13 | #[get("/unused")] 14 | fn unused(flash: Option>) -> Option<()> { 15 | flash.map(|_| ()) 16 | } 17 | 18 | #[get("/use")] 19 | fn used(flash: Option>) -> Option { 20 | flash.map(|f| f.message().into()) 21 | } 22 | 23 | mod flash_lazy_remove_tests { 24 | use rocket::local::blocking::Client; 25 | use rocket::http::Status; 26 | 27 | #[test] 28 | fn test() { 29 | use super::*; 30 | 31 | // Ensure the cookie's not there at first. 32 | let client = Client::debug_with(routes![set, unused, used]).unwrap(); 33 | let response = client.get("/unused").dispatch(); 34 | assert_eq!(response.status(), Status::NotFound); 35 | 36 | // Set the flash cookie. 37 | client.post("/").dispatch(); 38 | 39 | // Try once. 40 | let response = client.get("/unused").dispatch(); 41 | assert_eq!(response.status(), Status::Ok); 42 | 43 | // Try again; should still be there. 44 | let response = client.get("/unused").dispatch(); 45 | assert_eq!(response.status(), Status::Ok); 46 | 47 | // Now use it. 48 | let response = client.get("/use").dispatch(); 49 | assert_eq!(response.into_string(), Some(FLASH_MESSAGE.into())); 50 | 51 | // Now it should be gone. 52 | let response = client.get("/unused").dispatch(); 53 | assert_eq!(response.status(), Status::NotFound); 54 | 55 | // Still gone. 56 | let response = client.get("/use").dispatch(); 57 | assert_eq!(response.status(), Status::NotFound); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /site/tests/src/lib.rs: -------------------------------------------------------------------------------- 1 | #[cfg(any(test, doctest))] rocket::internal_guide_tests!("../guide/*.md"); 2 | #[cfg(any(test, doctest))] rocket::internal_guide_tests!("../../README.md"); 3 | 4 | #[macro_export] 5 | macro_rules! map { 6 | ($($key:expr => $value:expr),* $(,)?) => ({ 7 | let mut map = std::collections::HashMap::new(); 8 | $(map.insert($key.into(), $value.into());)* 9 | map 10 | }); 11 | } 12 | 13 | #[macro_export] 14 | macro_rules! bmap { 15 | ($($key:expr => $value:expr),* $(,)?) => ({ 16 | let mut map = std::collections::BTreeMap::new(); 17 | $(map.insert($key.into(), $value.into());)* 18 | map 19 | }); 20 | } 21 | 22 | #[macro_export] 23 | macro_rules! assert_form_parses { 24 | ($T:ty, $form:expr => $value:expr) => ( 25 | match rocket::form::Form::<$T>::parse($form) { 26 | Ok(v) => assert_eq!(v, $value, "{}", $form), 27 | Err(e) => { 28 | eprintln!("form failed to parse\n> form: {:?}\n> error: {:?}", $form, e); 29 | panic!("form parse failure"); 30 | } 31 | } 32 | ); 33 | 34 | ($T:ty, $($form:expr => $value:expr),+ $(,)?) => ( 35 | $(assert_form_parses!($T, $form => $value);)+ 36 | ); 37 | 38 | ($T:ty, $($form:expr),+ $(,)? => $value:expr) => ( 39 | $(assert_form_parses!($T, $form => $value);)+ 40 | ); 41 | } 42 | 43 | #[macro_export] 44 | macro_rules! assert_not_form_parses { 45 | ($T:ty, $($form:expr),* $(,)?) => ($( 46 | rocket::form::Form::<$T>::parse($form).unwrap_err(); 47 | )*); 48 | } 49 | 50 | #[macro_export] 51 | macro_rules! assert_form_parses_ok { 52 | ($T:ty, $($form:expr),* $(,)?) => ($( 53 | rocket::form::Form::<$T>::parse($form).expect("form to parse"); 54 | )*); 55 | } 56 | 57 | pub fn client(routes: Vec) -> rocket::local::blocking::Client { 58 | rocket::local::blocking::Client::debug_with(routes).unwrap() 59 | } 60 | --------------------------------------------------------------------------------