diff --git a/.gitignore b/.gitignore index 7db4fd9..f52679b 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ _site Cargo.lock build/ target/ +.DS_Store diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..804f284 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,13 @@ +{ + "singleQuote": true, + "tabWidth": 2, + "overrides": [ + { + "files": ["*.md"], + "options": { + "proseWrap": "always", + "printWidth": 100 + } + } + ] +} diff --git a/README.md b/README.md index 8391a0d..20f2738 100644 --- a/README.md +++ b/README.md @@ -4,11 +4,12 @@ The work in progress website for the actix project based on tokio's website. ## Getting Started -Building the website depends on [Hugo](http://gohugo.io). So, first make sure -that you have it installed. If on OS X and using Homebrew, run the following: +Building the website depends on [Hugo]. So, first make sure +that you have it installed. If on macOS and using [Homebrew], run the following: ```sh -brew update && brew install hugo +brew update +brew install hugo ``` Then, get the website running locally: @@ -16,16 +17,18 @@ Then, get the website running locally: ```sh git clone https://github.com/actix/actix-website.git cd actix-website + hugo server ``` -Then visit [http://localhost:1313](http://localhost:1313). +Then visit http://localhost:1313. ## Updating diagrams -Diagrams are located under [/static/css/img/diagrams/](https://github.com/actix/actix-website/tree/master/static/img/diagrams) and built with [Mermaid CLI](https://github.com/mermaidjs/mermaid.cli). +Diagrams are located under [/static/css/img/diagrams/](https://github.com/actix/actix-website/tree/master/static/img/diagrams) and built with [Mermaid CLI]. For instance to edit `connection_overview` diagram: + ```sh cd static/css/img/diagrams vi connection_overview.mmd @@ -35,5 +38,11 @@ mmdc -i connection_overview.mmd -o connection_overview.svg # License -Pretty murky. Right now a massive clone of the tokio website. Will get this +Pretty murky. Right now a massive clone of the tokio website. Will get this figured out as we go along. + + + +[Hugo]: https://gohugo.io +[Homebrew]: https://brew.sh +[Mermaid CLI]: https://github.com/mermaidjs/mermaid.cli diff --git a/config.toml b/config.toml index 7ee657c..4bc6f2a 100644 --- a/config.toml +++ b/config.toml @@ -10,13 +10,13 @@ DefaultContentLanguage = "en" baseURL = "https://actix.rs" [languages.en] - languageCode = "en-US" - languageName = "English" - weight = 1 +languageCode = "en-US" +languageName = "English" +weight = 1 [params] -actixVersion = "0.9" -actixWebVersion = "2.0" -actixRtVersion = "1.0" -actixWebMinRustVersion = "1.39" -actixMinRustVersion = "1.39" +actixVersion = "0.10" +actixWebVersion = "3" +actixRtVersion = "1.1" +actixWebMinRustVersion = "1.42" +actixMinRustVersion = "1.42" diff --git a/content/_index.md b/content/_index.md index 2c72a1e..210c655 100644 --- a/content/_index.md +++ b/content/_index.md @@ -1,3 +1,3 @@ --- -title: Rust's powerful actor system and most fun web framework +title: Actix Web | A powerful, pragmatic, and extremely fast web framework for Rust. --- diff --git a/content/code/_index.md b/content/code/_index.md index 8ddf1d7..33515e1 100644 --- a/content/code/_index.md +++ b/content/code/_index.md @@ -5,15 +5,19 @@ description: Browse and download the sources # Browse the Code -All of actix is open source and can be found on our github organization: [actix -on github](https://github.com/actix) +The Actix ecosystem is fully open source on our GitHub organization [@actix](https://github.com/actix). Here are the most important projects and the link to their github repositories and related resources: -* [actix](https://github.com/actix/actix) ([issues](https://github.com/actix/actix/issues), [ci](https://travis-ci.org/actix/actix), [crate](https://crates.io/crates/actix), [api docs](https://docs.rs/actix)) -* [actix-web](https://github.com/actix/actix-web) ([issues](https://github.com/actix/actix-web/issues), [ci](https://travis-ci.org/actix/actix-web), [crate](https://crates.io/crates/actix-web), [api docs](https://docs.rs/actix-web)) -* [example code](https://github.com/actix/examples) -* [this website](https://github.com/actix/actix-website) +- [actix-web](https://github.com/actix/actix-web), ([API docs](https://docs.rs/actix-web)) +- [actix-extras crates](https://github.com/actix/actix-extras) +- [actix-net crates](https://github.com/actix/actix-net) +- [actix](https://github.com/actix/actix), ([API docs](https://docs.rs/actix)) +- [examples repo](https://github.com/actix/examples) +- [this website](https://github.com/actix/actix-website) -Actix is dual licensed under the MIT and Apache 2 licenses. [Read license text](license/). +Actix is dual licensed under the [MIT] and [Apache 2] licenses. + +[mit]: https://github.com/actix/actix-web/blob/master/LICENSE-MIT +[apache 2]: https://github.com/actix/actix-web/blob/master/LICENSE-APACHE diff --git a/content/code/license.md b/content/code/license.md deleted file mode 100644 index a99e01a..0000000 --- a/content/code/license.md +++ /dev/null @@ -1,201 +0,0 @@ ---- -title: License ---- - -Actix is dual licensed under MIT and Apache licenses. - -# MIT License - -Copyright (c) 2017 Nikolay Kim - -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. - -# Apache License - -_Version 2.0, January 2004_ -http://www.apache.org/licenses/ - -### Terms and Conditions for use, reproduction, and distribution - -#### 1. Definitions - -“License” shall mean the terms and conditions for use, reproduction, and -distribution as defined by Sections 1 through 9 of this document. - -“Licensor” shall mean the copyright owner or entity authorized by the copyright -owner that is granting the License. - -“Legal Entity” shall mean the union of the acting entity and all other entities -that control, are controlled by, or are under common control with that entity. -For the purposes of this definition, “control” means **(i)** the power, direct or -indirect, to cause the direction or management of such entity, whether by -contract or otherwise, or **(ii)** ownership of fifty percent (50%) or more of the -outstanding shares, or **(iii)** beneficial ownership of such entity. - -“You” (or “Your”) shall mean an individual or Legal Entity exercising -permissions granted by this License. - -“Source” form shall mean the preferred form for making modifications, including -but not limited to software source code, documentation source, and configuration -files. - -“Object” form shall mean any form resulting from mechanical transformation or -translation of a Source form, including but not limited to compiled object code, -generated documentation, and conversions to other media types. - -“Work” shall mean the work of authorship, whether in Source or Object form, made -available under the License, as indicated by a copyright notice that is included -in or attached to the work (an example is provided in the Appendix below). - -“Derivative Works” shall mean any work, whether in Source or Object form, that -is based on (or derived from) the Work and for which the editorial revisions, -annotations, elaborations, or other modifications represent, as a whole, an -original work of authorship. For the purposes of this License, Derivative Works -shall not include works that remain separable from, or merely link (or bind by -name) to the interfaces of, the Work and Derivative Works thereof. - -“Contribution” shall mean any work of authorship, including the original version -of the Work and any modifications or additions to that Work or Derivative Works -thereof, that is intentionally submitted to Licensor for inclusion in the Work -by the copyright owner or by an individual or Legal Entity authorized to submit -on behalf of the copyright owner. For the purposes of this definition, -“submitted” means any form of electronic, verbal, or written communication sent -to the Licensor or its representatives, including but not limited to -communication on electronic mailing lists, source code control systems, and -issue tracking systems that are managed by, or on behalf of, the Licensor for -the purpose of discussing and improving the Work, but excluding communication -that is conspicuously marked or otherwise designated in writing by the copyright -owner as “Not a Contribution.” - -“Contributor” shall mean Licensor and any individual or Legal Entity on behalf -of whom a Contribution has been received by Licensor and subsequently -incorporated within the Work. - -#### 2. Grant of Copyright License - -Subject to the terms and conditions of this License, each Contributor hereby -grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, -irrevocable copyright license to reproduce, prepare Derivative Works of, -publicly display, publicly perform, sublicense, and distribute the Work and such -Derivative Works in Source or Object form. - -#### 3. Grant of Patent License - -Subject to the terms and conditions of this License, each Contributor hereby -grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, -irrevocable (except as stated in this section) patent license to make, have -made, use, offer to sell, sell, import, and otherwise transfer the Work, where -such license applies only to those patent claims licensable by such Contributor -that are necessarily infringed by their Contribution(s) alone or by combination -of their Contribution(s) with the Work to which such Contribution(s) was -submitted. If You institute patent litigation against any entity (including a -cross-claim or counterclaim in a lawsuit) alleging that the Work or a -Contribution incorporated within the Work constitutes direct or contributory -patent infringement, then any patent licenses granted to You under this License -for that Work shall terminate as of the date such litigation is filed. - -#### 4. Redistribution - -You may reproduce and distribute copies of the Work or Derivative Works thereof -in any medium, with or without modifications, and in Source or Object form, -provided that You meet the following conditions: - -* **(a)** You must give any other recipients of the Work or Derivative Works a copy of -this License; and -* **(b)** You must cause any modified files to carry prominent notices stating that You -changed the files; and -* **(c)** You must retain, in the Source form of any Derivative Works that You distribute, -all copyright, patent, trademark, and attribution notices from the Source form -of the Work, excluding those notices that do not pertain to any part of the -Derivative Works; and -* **(d)** If the Work includes a “NOTICE” text file as part of its distribution, then any -Derivative Works that You distribute must include a readable copy of the -attribution notices contained within such NOTICE file, excluding those notices -that do not pertain to any part of the Derivative Works, in at least one of the -following places: within a NOTICE text file distributed as part of the -Derivative Works; within the Source form or documentation, if provided along -with the Derivative Works; or, within a display generated by the Derivative -Works, if and wherever such third-party notices normally appear. The contents of -the NOTICE file are for informational purposes only and do not modify the -License. You may add Your own attribution notices within Derivative Works that -You distribute, alongside or as an addendum to the NOTICE text from the Work, -provided that such additional attribution notices cannot be construed as -modifying the License. - -You may add Your own copyright statement to Your modifications and may provide -additional or different license terms and conditions for use, reproduction, or -distribution of Your modifications, or for any such Derivative Works as a whole, -provided Your use, reproduction, and distribution of the Work otherwise complies -with the conditions stated in this License. - -#### 5. Submission of Contributions - -Unless You explicitly state otherwise, any Contribution intentionally submitted -for inclusion in the Work by You to the Licensor shall be under the terms and -conditions of this License, without any additional terms or conditions. -Notwithstanding the above, nothing herein shall supersede or modify the terms of -any separate license agreement you may have executed with Licensor regarding -such Contributions. - -#### 6. Trademarks - -This License does not grant permission to use the trade names, trademarks, -service marks, or product names of the Licensor, except as required for -reasonable and customary use in describing the origin of the Work and -reproducing the content of the NOTICE file. - -#### 7. Disclaimer of Warranty - -Unless required by applicable law or agreed to in writing, Licensor provides the -Work (and each Contributor provides its Contributions) on an “AS IS” BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, -including, without limitation, any warranties or conditions of TITLE, -NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are -solely responsible for determining the appropriateness of using or -redistributing the Work and assume any risks associated with Your exercise of -permissions under this License. - -#### 8. Limitation of Liability - -In no event and under no legal theory, whether in tort (including negligence), -contract, or otherwise, unless required by applicable law (such as deliberate -and grossly negligent acts) or agreed to in writing, shall any Contributor be -liable to You for damages, including any direct, indirect, special, incidental, -or consequential damages of any character arising as a result of this License or -out of the use or inability to use the Work (including but not limited to -damages for loss of goodwill, work stoppage, computer failure or malfunction, or -any and all other commercial damages or losses), even if such Contributor has -been advised of the possibility of such damages. - -#### 9. Accepting Warranty or Additional Liability - -While redistributing the Work or Derivative Works thereof, You may choose to -offer, and charge a fee for, acceptance of support, warranty, indemnity, or -other liability obligations and/or rights consistent with this License. However, -in accepting such obligations, You may act only on Your own behalf and on Your -sole responsibility, not on behalf of any other Contributor, and only if You -agree to indemnify, defend, and hold each Contributor harmless for any liability -incurred by, or claims asserted against, such Contributor by reason of your -accepting any such warranty or additional liability. diff --git a/content/community/_index.md b/content/community/_index.md index 1cf3509..2e18e00 100644 --- a/content/community/_index.md +++ b/content/community/_index.md @@ -5,16 +5,13 @@ description: The best things in life are to be shared # Join us -Want to talk to others about questions? The [actix gitter -channel](https://gitter.im/actix/actix) or -[reddit community](https://www.reddit.com/r/actix/) -are your best starting point. +Want to talk to others about questions? The Actix [Gitter channel](https://gitter.im/actix/actix) or +[reddit community](https://www.reddit.com/r/actix/) are your best starting point. -If you think you found a bug it's best to go to the -[github](https://github.com/actix) directly. There are two repositories -that you might want to report against. [actix](https://github.com/actix/actix) -for issues with the actor framework or [actix-web](https://github.com/actix/actix-web) -for the high level web framework. +If you think you found a bug it's best to go to the [github](https://github.com/actix) directly. +There are two repositories that you might want to report against. +[actix](https://github.com/actix/actix) for issues with the actor framework or +[actix-web](https://github.com/actix/actix-web) for the web framework. -We're a welcoming community so don't be afraid to engage. Interactions -are [governed by our code of conduct](coc/). +We're a welcoming community so don't be afraid to engage. Interactions are +[governed by our code of conduct](coc/). diff --git a/content/docs/_index.md b/content/docs/_index.md index 603454b..e827e63 100644 --- a/content/docs/_index.md +++ b/content/docs/_index.md @@ -1,6 +1,6 @@ --- title: Documentation -description: Guiding you through building apps with actix +description: Guiding you through building web apps with Actix menu: docs_intro: name: Welcome @@ -9,19 +9,16 @@ weight: 10 # Welcome to Actix -Actix is your door to developing web services with Rust and this documentation -is going to guide you. +Actix Web lets you quickly and confidently develop web services in Rust and this guide get you going +in no time. -This documentation currently covers mostly the `actix-web` part which is the high level -web framework previously built on top of the `actix` actor framework and the [Tokio][tokio] -async IO system. This is the part that is from an API stability point of view the most stable. +The documentation on this website focusses primarily on the Actix Web framework. For information +about the actor framework called Actix, check out the [Actix book][actix-book] (or the lower level +[actix API docs][actix-docs]). Otherwise, head on to the [getting started guide][getting-started]. +If you already know your ways around and you need specific information you might want to read the +[actix-web API docs][actix-web-docs]. -If you haven't used `actix-web` yet it's best to start with the [getting started -guide][gettingstarted]. If you already know your ways around and you need -specific information you might want to read the [actix-web API docs][actixwebdocs] -(or the lower level [actix API docs][actixdocs]). - -[gettingstarted]: ./getting-started -[actixwebdocs]: https://docs.rs/actix-web -[actixdocs]: https://docs.rs/actix -[tokio]: https://tokio.rs +[getting-started]: ./getting-started +[actix-web-docs]: https://docs.rs/actix-web +[actix-docs]: https://docs.rs/actix +[actix-book]: https://actix.rs/book/actix diff --git a/content/docs/application.md b/content/docs/application.md index 57336b4..97dec1d 100644 --- a/content/docs/application.md +++ b/content/docs/application.md @@ -6,35 +6,33 @@ weight: 140 # Writing an Application -`actix-web` provides various primitives to build web servers and applications with Rust. -It provides routing, middlewares, pre-processing of requests, post-processing of -responses, etc. +`actix-web` provides various primitives to build web servers and applications with Rust. It provides +routing, middleware, pre-processing of requests, post-processing of responses, etc. -All `actix-web` servers are built around the [`App`][app] instance. It is used for -registering routes for resources and middlewares. It also stores application -state shared across all handlers within the same scope. +All `actix-web` servers are built around the [`App`][app] instance. It is used for registering +routes for resources and middleware. It also stores application state shared across all handlers +within the same scope. -An application's [`scope`][scope] acts as a namespace for all routes, i.e. all routes for a -specific application scope have the same url path prefix. The application prefix always -contains a leading "/" slash. If a supplied prefix does not contain leading slash, -it is automatically inserted. The prefix should consist of value path segments. +An application's [`scope`][scope] acts as a namespace for all routes, i.e. all routes for a specific +application scope have the same url path prefix. The application prefix always contains a leading +"/" slash. If a supplied prefix does not contain leading slash, it is automatically inserted. The +prefix should consist of value path segments. -> For an application with scope `/app`, -> any request with the paths `/app`, `/app/`, or `/app/test` would match; -> however, the path `/application` would not match. +> For an application with scope `/app`, any request with the paths `/app`, `/app/`, or `/app/test` +> would match; however, the path `/application` would not match. {{< include-example example="application" file="app.rs" section="setup" >}} -In this example, an application with the `/app` prefix and a `index.html` resource -are created. This resource is available through the `/app/index.html` url. +In this example, an application with the `/app` prefix and a `index.html` resource are created. This +resource is available through the `/app/index.html` url. > For more information, check the [URL Dispatch][usingappprefix] section. ## State -Application state is shared with all routes and resources within the same scope. State -can be accessed with the [`web::Data`][data] extractor where `T` is the type of the state. State is -also available for middlewares. +Application state is shared with all routes and resources within the same scope. State can be +accessed with the [`web::Data`][data] extractor where `T` is the type of the state. State is also +accessible for middleware. Let's write a simple application and store the application name in the state: @@ -48,14 +46,16 @@ Any number of state types could be registered within the application. ## Shared Mutable State -`HttpServer` accepts an application factory rather than an application instance. -An `HttpServer` constructs an application instance for each thread. Therefore, application data must be -constructed multiple times. If you want to share data between different threads, a shareable -object should be used, e.g. `Send` + `Sync`. +`HttpServer` accepts an application factory rather than an application instance. An `HttpServer` +constructs an application instance for each thread. Therefore, application data must be constructed +multiple times. If you want to share data between different threads, a shareable object should be +used, e.g. `Send` + `Sync`. -Internally, [`web::Data`][data] uses `Arc`. Thus, in order to avoid creating two `Arc`s, we should create our Data before registering it using [`App::app_data()`][appdata]. +Internally, [`web::Data`][data] uses `Arc`. Thus, in order to avoid creating two `Arc`s, we should +create our Data before registering it using [`App::app_data()`][appdata]. -In the following example, we will write an application with mutable, shared state. First, we define our state and create our handler: +In the following example, we will write an application with mutable, shared state. First, we define +our state and create our handler: {{< include-example example="application" file="mutable_state.rs" section="setup_mutable" >}} @@ -67,37 +67,37 @@ and register the data in an `App`: The [`web::scope()`][webscope] method allows setting a resource group prefix. This scope represents a resource prefix that will be prepended to all resource patterns added by the resource -configuration. This can be used to help mount a set of routes at a different location -than the original author intended while still maintaining the same resource names. +configuration. This can be used to help mount a set of routes at a different location than the +original author intended while still maintaining the same resource names. For example: {{< include-example example="application" file="scope.rs" section="scope" >}} -In the above example, the `show_users` route will have an effective route pattern of -`/users/show` instead of `/show` because the application's scope argument will be prepended -to the pattern. The route will then only match if the URL path is `/users/show`, -and when the [`HttpRequest.url_for()`][urlfor] function is called with the route name `show_users`, -it will generate a URL with that same path. +In the above example, the `show_users` route will have an effective route pattern of `/users/show` +instead of `/show` because the application's scope argument will be prepended to the pattern. The +route will then only match if the URL path is `/users/show`, and when the +[`HttpRequest.url_for()`][urlfor] function is called with the route name `show_users`, it will +generate a URL with that same path. ## Application guards and virtual hosting -You can think of a guard as a simple function that accepts a *request* object reference -and returns *true* or *false*. Formally, a guard is any object that implements the -[`Guard`][guardtrait] trait. Actix-web provides several guards. You can check the -[functions section][guardfuncs] of the API docs. +You can think of a guard as a simple function that accepts a _request_ object reference and returns +_true_ or _false_. Formally, a guard is any object that implements the [`Guard`][guardtrait] trait. +Actix-web provides several guards. You can check the [functions section][guardfuncs] of the API +docs. -One of the provided guards is [`Header`][guardheader]. It can be used as a -filter based on request header information. +One of the provided guards is [`Header`][guardheader]. It can be used as a filter based on request +header information. {{< include-example example="application" file="vh.rs" section="vh" >}} # Configure -For simplicity and reusability both [`App`][appconfig] and [`web::Scope`][webscopeconfig] provide the `configure` method. -This function is useful for moving parts of the configuration to a different module or even -library. For example, some of the resource's configuration could be moved to a different -module. +For simplicity and reusability both [`App`][appconfig] and [`web::Scope`][webscopeconfig] provide +the `configure` method. This function is useful for moving parts of the configuration to a different +module or even library. For example, some of the resource's configuration could be moved to a +different module. {{< include-example example="application" file="config.rs" section="config" >}} @@ -108,19 +108,22 @@ The result of the above example would be: /app -> "app" /api/test -> "test" ``` + Each [`ServiceConfig`][serviceconfig] can have its own `data`, `routes`, and `services`. + + [usingappprefix]: /docs/url-dispatch/index.html#using-an-application-prefix-to-compose-applications [stateexample]: https://github.com/actix/examples/blob/master/state/src/main.rs -[guardtrait]: https://docs.rs/actix-web/2/actix_web/guard/trait.Guard.html -[guardfuncs]: https://docs.rs/actix-web/2/actix_web/guard/index.html#functions -[guardheader]: https://docs.rs/actix-web/2/actix_web/guard/fn.Header.html -[data]: https://docs.rs/actix-web/2/actix_web/web/struct.Data.html -[app]: https://docs.rs/actix-web/2/actix_web/struct.App.html -[appconfig]: https://docs.rs/actix-web/2/actix_web/struct.App.html#method.configure -[appdata]: https://docs.rs/actix-web/2/actix_web/struct.App.html#method.app_data -[scope]: https://docs.rs/actix-web/2/actix_web/struct.Scope.html -[webscopeconfig]: https://docs.rs/actix-web/2/actix_web/struct.Scope.html#method.configure -[webscope]: https://docs.rs/actix-web/2/actix_web/web/fn.scope.html -[urlfor]: https://docs.rs/actix-web/2/actix_web/struct.HttpRequest.html#method.url_for -[serviceconfig]: https://docs.rs/actix-web/2/actix_web/web/struct.ServiceConfig.html +[guardtrait]: https://docs.rs/actix-web/3/actix_web/guard/trait.Guard.html +[guardfuncs]: https://docs.rs/actix-web/3/actix_web/guard/index.html#functions +[guardheader]: https://docs.rs/actix-web/3/actix_web/guard/fn.Header.html +[data]: https://docs.rs/actix-web/3/actix_web/web/struct.Data.html +[app]: https://docs.rs/actix-web/3/actix_web/struct.App.html +[appconfig]: https://docs.rs/actix-web/3/actix_web/struct.App.html#method.configure +[appdata]: https://docs.rs/actix-web/3/actix_web/struct.App.html#method.app_data +[scope]: https://docs.rs/actix-web/3/actix_web/struct.Scope.html +[webscopeconfig]: https://docs.rs/actix-web/3/actix_web/struct.Scope.html#method.configure +[webscope]: https://docs.rs/actix-web/3/actix_web/web/fn.scope.html +[urlfor]: https://docs.rs/actix-web/3/actix_web/struct.HttpRequest.html#method.url_for +[serviceconfig]: https://docs.rs/actix-web/3/actix_web/web/struct.ServiceConfig.html diff --git a/content/docs/autoreload.md b/content/docs/autoreload.md deleted file mode 100644 index 77549fc..0000000 --- a/content/docs/autoreload.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -title: Autoreloading -menu: docs_patterns -weight: 1000 ---- - -# Auto-Reloading Development Server - -During development it can be very handy to have cargo automatically recompile the code -on change. This can be accomplished by using [cargo-watch][cargowatch]. Because an -actix app will typically bind to a port for listening for incoming HTTP requests it makes -sense to combine this with the [listenfd][listenfd] crate and the [systemfd][systemfd] -utility to ensure the socket is kept open while the app is compiling and reloading. - -`systemfd` will open a socket and pass it to `cargo-watch` which will watch for -changes and then invoke the compiler and run your actix app. The actix app -will then use `listenfd` to pick up the socket that `systemfd` opened. - -## Binaries Necessary - -For an automatic reloading experience you need to install `cargo-watch` and -`systemfd`. Both are written in Rust and can be installed with `cargo install`: - -``` -cargo install systemfd cargo-watch -``` - -## Code Changes - -Additionally you need to slightly modify your actix app so that it can pick up -an external socket opened by `systemfd`. Add the listenfd dependency to your app: - -```ini -[dependencies] -listenfd = "0.3" -``` - -Then modify your server code to only invoke `bind` as a fallback: - -{{< include-example example="autoreload" file="main.rs" section="autoreload" >}} - -## Running the Server - -To now run the development server invoke this command: - -``` -systemfd --no-pid -s http::3000 -- cargo watch -x run -``` - -[cargowatch]: https://github.com/passcod/cargo-watch -[listenfd]: https://crates.io/crates/listenfd -[systemfd]: https://github.com/mitsuhiko/systemfd diff --git a/content/docs/databases.md b/content/docs/databases.md index e840768..aca1f2f 100644 --- a/content/docs/databases.md +++ b/content/docs/databases.md @@ -4,51 +4,43 @@ menu: docs_patterns weight: 1010 --- +# Async Options + +We have several example projects showing use of async database adapters: + +- SQLx: https://github.com/actix/examples/tree/master/sqlx_todo +- Postgres: https://github.com/actix/examples/tree/master/async_pg +- SQLite: https://github.com/actix/examples/tree/master/async_db + # Diesel -{{% alert %}} -NOTE: The `actix-web` 1.0 version of this section is still -[being updated](https://github.com/cldershem/actix-website/tree/update1.0-db). Checkout -this [example](https://github.com/actix/examples/tree/master/async_db) until then. -{{% /alert %}} +The current version of Diesel (v1) does not support asynchronous operations, so it is important to +use the [`web::block`][web-block] function to offload your database operations to the Actix runtime +thread-pool. -At the moment, Diesel 1.0 does not support asynchronous operations, -but it's possible to use the `actix` synchronous actor system as a database interface api. +You can create action functions that correspond to all the operations your app will perform on the +database. -Technically, sync actors are worker style actors. Multiple sync actors -can be run in parallel and process messages from same queue. Sync actors work in mpsc mode. +{{< include-example example="databases" file="main.rs" section="handler" >}} -Let's create a simple database api that can insert a new user row into a SQLite table. -We must define a sync actor and a connection that this actor will use. The same approach -can be used for other databases. +Now you should set up the database pool using a crate such as `r2d2`, which makes many DB +connections available to your app. This means that multiple handlers can manipulate the DB at the +same time, and still accept new connections. Simply, the pool in your app state. (In this case, it's +beneficial not to use a state wrapper struct because the pool handles shared access for you.) -{{< include-example example="og_databases" file="main.rs" section="actor" >}} +{{< include-example example="databases" file="main.rs" section="main" >}} -This is the definition of our actor. Now, we must define the *create user* message and response. +Now, in a request handler, use the `Data` extractor to get the pool from app state and get a +connection from it. This provides an owned database connection that can be passed into a +[`web::block`][web-block] closure. Then just call the action function with the necessary arguments +and `.await` the result. -{{< include-example example="og_databases" file="main.rs" section="message" >}} +This example also maps the error to an `HttpResponse` before using the `?` operator but this is not +necessary if your return error type implements [`ResponseError`][response-error]. -We can send a `CreateUser` message to the `DbExecutor` actor, and as a result, we will receive a -`User` model instance. Next, we must define the handler implementation for this message. +{{< include-example example="databases" file="main.rs" section="index" >}} -{{< include-example example="og_databases" file="main.rs" section="handler" >}} +That's it! See the full example here: https://github.com/actix/examples/tree/master/diesel -That's it! Now, we can use the *DbExecutor* actor from any http handler or middleware. -All we need is to start *DbExecutor* actors and store the address in a state where http handler -can access it. - -{{< include-example example="og_databases" file="main.rs" section="main" >}} - -We will use the address in a request handler. The handle returns a future object; -thus, we receive the message response asynchronously. -`Route::a()` must be used for async handler registration. - -{{< include-example example="og_databases" file="main.rs" section="index" >}} - -> A full example is available in the [examples directory][examples]. - -> More information on sync actors can be found in the -> [actix documentation][actixdocs]. - -[examples]: https://github.com/actix/examples/tree/master/diesel/ -[actixdocs]: https://docs.rs/actix/0.7.0/actix/sync/index.html +[web-block]: https://docs.rs/actix-web/3/actix_web/web/fn.block.html +[response-error]: https://docs.rs/actix-web/3/actix_web/trait.ResponseError.html diff --git a/content/docs/errors.md b/content/docs/errors.md index 34e9435..cbdb5c9 100644 --- a/content/docs/errors.md +++ b/content/docs/errors.md @@ -7,12 +7,12 @@ weight: 180 # Errors Actix-web uses its own [`actix_web::error::Error`][actixerror] type and -[`actix_web::error::ResponseError`][responseerror] trait for error handling -from web handlers. +[`actix_web::error::ResponseError`][responseerror] trait for error handling from web handlers. If a handler returns an `Error` (referring to the [general Rust trait -`std::error::Error`][stderror]) in a `Result` that also implements the -`ResponseError` trait, actix-web will render that error as an HTTP response with it's corresponding [`actix_web::http::StatusCode`][status_code]. Internal server error is generated by default: +`std::error::Error`][stderror]) in a `Result` that also implements the `ResponseError` trait, +actix-web will render that error as an HTTP response with it's corresponding +[`actix_web::http::StatusCode`][status_code]. Internal server error is generated by default: ```rust pub trait ResponseError { @@ -27,12 +27,11 @@ A `Responder` coerces compatible `Result`s into HTTP responses: impl> Responder for Result ``` -`Error` in the code above is actix-web's error definition, and any errors that -implement `ResponseError` can be converted to one automatically. +`Error` in the code above is actix-web's error definition, and any errors that implement +`ResponseError` can be converted to one automatically. -Actix-web provides `ResponseError` implementations for some common non-actix -errors. For example, if a handler responds with an `io::Error`, that error is -converted into an `HttpInternalServerError`: +Actix-web provides `ResponseError` implementations for some common non-actix errors. For example, if +a handler responds with an `io::Error`, that error is converted into an `HttpInternalServerError`: ```rust use std::io; @@ -43,18 +42,18 @@ fn index(_req: HttpRequest) -> io::Result { } ``` -See [the actix-web API documentation][responseerrorimpls] for a full list of foreign -implementations for `ResponseError`. +See [the actix-web API documentation][responseerrorimpls] for a full list of foreign implementations +for `ResponseError`. ## An example of a custom error response -Here's an example implementation for `ResponseError`: +Here's an example implementation for `ResponseError`, using the [derive_more] crate +for declarative error enums. {{< include-example example="errors" file="main.rs" section="response-error" >}} -`ResponseError` has a default implementation for `error_response()` that will -render a _500_ (internal server error), and that's what will happen when the -`index` handler executes above. +`ResponseError` has a default implementation for `error_response()` that will render a _500_ +(internal server error), and that's what will happen when the `index` handler executes above. Override `error_response()` to produce more useful results: @@ -62,69 +61,56 @@ Override `error_response()` to produce more useful results: # Error helpers -Actix-web provides a set of error helper functions that are useful for generating -specific HTTP error codes from other errors. Here we convert `MyError`, which -doesn't implement the `ResponseError` trait, to a _400_ (bad request) using -`map_err`: +Actix-web provides a set of error helper functions that are useful for generating specific HTTP +error codes from other errors. Here we convert `MyError`, which doesn't implement the +`ResponseError` trait, to a _400_ (bad request) using `map_err`: {{< include-example example="errors" file="helpers.rs" section="helpers" >}} -See the [API documentation for actix-web's `error` module][actixerror] -for a full list of available error helpers. - -# Compatibility with failure - -Actix-web provides automatic compatibility with the [failure] library so that -errors deriving `fail` will be converted automatically to an actix error. Keep -in mind that those errors will render with the default _500_ status code unless you -also provide your own `error_response()` implementation for them. +See the [API documentation for actix-web's `error` module][actixerror] for a full list of available +error helpers. # Error logging -Actix logs all errors at the `WARN` log level. If an application's log level is -set to `DEBUG` and `RUST_BACKTRACE` is enabled, the backtrace is also logged. -These are configurable with environmental variables: +Actix logs all errors at the `WARN` log level. If an application's log level is set to `DEBUG` and +`RUST_BACKTRACE` is enabled, the backtrace is also logged. These are configurable with environmental +variables: ``` >> RUST_BACKTRACE=1 RUST_LOG=actix_web=debug cargo run ``` -The `Error` type uses the cause's error backtrace if available. If the -underlying failure does not provide a backtrace, a new backtrace is constructed -pointing to the point where the conversion occurred (rather than the origin of -the error). +The `Error` type uses the cause's error backtrace if available. If the underlying failure does not +provide a backtrace, a new backtrace is constructed pointing to the point where the conversion +occurred (rather than the origin of the error). # Recommended practices in error handling -It might be useful to think about dividing the errors an application produces -into two broad groups: those which are intended to be be user-facing, and those -which are not. +It might be useful to think about dividing the errors an application produces into two broad groups: +those which are intended to be be user-facing, and those which are not. -An example of the former is that I might use failure to specify a `UserError` -enum which encapsulates a `ValidationError` to return whenever a user sends bad -input: +An example of the former is that I might use failure to specify a `UserError` enum which +encapsulates a `ValidationError` to return whenever a user sends bad input: {{< include-example example="errors" file="recommend_one.rs" section="recommend-one" >}} -This will behave exactly as intended because the error message defined with -`display` is written with the explicit intent to be read by a user. +This will behave exactly as intended because the error message defined with `display` is written +with the explicit intent to be read by a user. -However, sending back an error's message isn't desirable for all errors -- -there are many failures that occur in a server environment where we'd probably -want the specifics to be hidden from the user. For example, if a database goes -down and client libraries start producing connect timeout errors, or if an HTML -template was improperly formatted and errors when rendered. In these cases, it -might be preferable to map the errors to a generic error suitable for user -consumption. +However, sending back an error's message isn't desirable for all errors -- there are many failures +that occur in a server environment where we'd probably want the specifics to be hidden from the +user. For example, if a database goes down and client libraries start producing connect timeout +errors, or if an HTML template was improperly formatted and errors when rendered. In these cases, it +might be preferable to map the errors to a generic error suitable for user consumption. -Here's an example that maps an internal error to a user-facing `InternalError` -with a custom message: +Here's an example that maps an internal error to a user-facing `InternalError` with a custom +message: {{< include-example example="errors" file="recommend_two.rs" section="recommend-two" >}} -By dividing errors into those which are user facing and those which are not, we -can ensure that we don't accidentally expose users to errors thrown by -application internals which they weren't meant to see. +By dividing errors into those which are user facing and those which are not, we can ensure that we +don't accidentally expose users to errors thrown by application internals which they weren't meant +to see. # Error Logging @@ -132,10 +118,11 @@ This is a basic example using `middleware::Logger`: {{< include-example example="errors" file="logging.rs" section="logging" >}} -[actixerror]: https://docs.rs/actix-web/2/actix_web/error/struct.Error.html -[errorhelpers]: https://docs.rs/actix-web/2/actix_web/trait.ResponseError.html -[failure]: https://github.com/rust-lang-nursery/failure -[responseerror]: https://docs.rs/actix-web/2/actix_web/error/trait.ResponseError.html -[responseerrorimpls]: https://docs.rs/actix-web/2/actix_web/error/trait.ResponseError.html#foreign-impls +[actixerror]: https://docs.rs/actix-web/3/actix_web/error/struct.Error.html +[errorhelpers]: https://docs.rs/actix-web/3/actix_web/trait.ResponseError.html +[derive_more]: https://crates.io/crates/derive_more +[responseerror]: https://docs.rs/actix-web/3/actix_web/error/trait.ResponseError.html +[responseerrorimpls]: + https://docs.rs/actix-web/3/actix_web/error/trait.ResponseError.html#foreign-impls [stderror]: https://doc.rust-lang.org/std/error/trait.Error.html -[status_code]: https://docs.rs/actix-web/2.0.0/actix_web/http/struct.StatusCode.html +[status_code]: https://docs.rs/actix-web/3.0.0/actix_web/http/struct.StatusCode.html diff --git a/content/docs/extractors.md b/content/docs/extractors.md index 16f7022..6857122 100644 --- a/content/docs/extractors.md +++ b/content/docs/extractors.md @@ -19,8 +19,8 @@ up to 10 extractors per handler function. Argument position does not matter. [*Path*][pathstruct] provides information that can be extracted from the Request's path. You can deserialize any variable segment from the path. -For instance, for resource that registered for the `/users/{userid}/{friend}` path, -two segments could be deserialized, `userid` and `friend`. These segments could be +For instance, for resource that registered for the `/users/{user_id}/{friend}` path, +two segments could be deserialized, `user_id` and `friend`. These segments could be extracted into a `tuple`, i.e. `Path<(u32, String)>` or any structure that implements the `Deserialize` trait from the *serde* crate. @@ -109,13 +109,13 @@ number of requests processed per thread. A proper implementation would use `Arc` > request handling processes would block. If you need to share or update some state > from multiple threads, consider using the tokio synchronization primitives. -[pathstruct]: https://docs.rs/actix-web/2/actix_web/dev/struct.Path.html -[querystruct]: https://docs.rs/actix-web/2/actix_web/web/struct.Query.html -[jsonstruct]: https://docs.rs/actix-web/2/actix_web/web/struct.Json.html -[jsonconfig]: https://docs.rs/actix-web/2/actix_web/web/struct.JsonConfig.html -[formconfig]: https://docs.rs/actix-web/2/actix_web/web/struct.FormConfig.html -[datastruct]: https://docs.rs/actix-web/2/actix_web/web/struct.Data.html -[stringexample]: https://docs.rs/actix-web/2/actix_web/trait.FromRequest.html#example-2 -[bytesexample]: https://docs.rs/actix-web/2/actix_web/trait.FromRequest.html#example-4 -[payloadexample]: https://docs.rs/actix-web/2/actix_web/web/struct.Payload.html +[pathstruct]: https://docs.rs/actix-web/3/actix_web/dev/struct.Path.html +[querystruct]: https://docs.rs/actix-web/3/actix_web/web/struct.Query.html +[jsonstruct]: https://docs.rs/actix-web/3/actix_web/web/struct.Json.html +[jsonconfig]: https://docs.rs/actix-web/3/actix_web/web/struct.JsonConfig.html +[formconfig]: https://docs.rs/actix-web/3/actix_web/web/struct.FormConfig.html +[datastruct]: https://docs.rs/actix-web/3/actix_web/web/struct.Data.html +[stringexample]: https://docs.rs/actix-web/3/actix_web/trait.FromRequest.html#example-2 +[bytesexample]: https://docs.rs/actix-web/3/actix_web/trait.FromRequest.html#example-4 +[payloadexample]: https://docs.rs/actix-web/3/actix_web/web/struct.Payload.html [actix]: https://actix.github.io/actix/actix/ diff --git a/content/docs/getting-started.md b/content/docs/getting-started.md index a408686..be72733 100644 --- a/content/docs/getting-started.md +++ b/content/docs/getting-started.md @@ -4,9 +4,14 @@ menu: docs_basics weight: 130 --- -# Getting Started +## Installing Rust -Let’s write our first `actix-web` application! +If you don't have Rust yet, we recommend you use `rustup` to manage your Rust installation. The +[official rust guide][rustguide] has a wonderful section on getting started. + +Actix Web currently has a minimum supported Rust version (MSRV) of {{< rust-version "actix-web" >}}. +Running `rustup update` will ensure you have the latest and greatest Rust version available. As +such, this guide assumes you are running Rust {{< rust-version "actix-web" >}} or later. ## Hello, world! @@ -17,71 +22,35 @@ cargo new hello-world cd hello-world ``` -Now, add `actix-web` as a dependency of your project by ensuring your `Cargo.toml` -contains the following: +Add `actix-web` as a dependency of your project by adding the following to your `Cargo.toml` file. -```ini +```toml [dependencies] actix-web = "{{< actix-version "actix-web" >}}" ``` -If you want to use the `#[actix_rt::main]` macro, you have to add `actix-rt` to your dependency. -Now your `Cargo.toml` should look like following: +Request handlers use an async functions that accept zero or more parameters. These parameters can be +extracted from a request (see `FromRequest` trait) and returns a type that can be converted into an +`HttpResponse` (see `Responder` trait): -```ini -[dependencies] -actix-web = "{{< actix-version "actix-web" >}}" -actix-rt = "{{< actix-version "actix-rt" >}}" -``` +{{< include-example example="getting-started" section="handlers" >}} -In order to implement a web server, we first need to create a request handler. +Notice that some of these handlers have routing information attached directly using the built-in +macros. These allow you to specify the method and path that the handler should respond to. You will +see below how to register the other route that does not use a routing macro. -A request handler is an async function that accepts zero or more parameters that can be -extracted from a request (ie, `impl FromRequest`) and returns a type that can be -converted into an `HttpResponse` (ie, `impl Responder`): - -{{< include-example example="getting-started" section="setup" >}} - -Next, create an `App` instance and register the request handler with the application's -`route` on a _path_ and with a particular _HTTP method_. After that, the application -instance can be used with `HttpServer` to listen for incoming connections. The server -accepts a function that should return an application factory. +Next, create an `App` instance and register the request handlers. Use `App::service` for the +handlers using routing macros and `App::route` for manually routed handlers, declaring the a path +and method. Finally, the app is started inside an `HttpServer` which will serve incoming requests +using your `App` as an "application factory". {{< include-example example="getting-started" section="main" >}} -That's it! Now, compile and run the program with `cargo run`. -Head over to `http://localhost:8088/` to see the results. +That's it! Compile and run the program with `cargo run`. The `#[actix_web::main]` macro executes the +async main function within the actix runtime. Now you can go to `http://localhost:8080/` or any of +the other routes you defined to see the results. -**Note**: You may have noticed the `#[actix_rt::main]` attribute macro. This -macro executes the associated async function within the actix runtime. -Any async function could be marked and executed by this macro. - -### Using Attribute Macros to Define Routes - -Alternatively, you can define routes using macro attributes which -allow you to specify the routes above your functions like so: - -{{< include-example example="getting-started" section="macro-attributes">}} - -You can then register the route using `service()`: - -```rust -App::new() - .service(index3) -``` - -For consistency reasons, this documentation only uses the explicit syntax shown at the -beginning of this page. However, if you prefer this syntax you should feel free to -use it any time you declare a route as it's only syntactic sugar. - -To learn more, see [actix-web-codegen]. - -### Auto-reloading - -If you want, you can have an automatically reloading server during development -that recompiles on demand. This isn't necessary, but it makes rapid prototyping -more convenient as you can see changes instantly upon saving. -To see how this can be accomplished, have a look at the [autoreload pattern][autoload]. + +[rustguide]: https://doc.rust-lang.org/book/ch01-01-installation.html [actix-web-codegen]: https://docs.rs/actix-web-codegen/ -[autoload]: ../autoreload/ diff --git a/content/docs/handlers.md b/content/docs/handlers.md index 04839cd..879d6f9 100644 --- a/content/docs/handlers.md +++ b/content/docs/handlers.md @@ -68,12 +68,12 @@ the stream trait `Stream`, i.e: Sometimes, you need to return different types of responses. For example, you can error check and return errors, return async responses, or any result that requires two different types. -For this case, the [*Either*][either] type can be used. `Either` allows combining two +For this case, the [Either][either] type can be used. `Either` allows combining two different responder types into a single type. {{< include-example example="either" file="main.rs" section="either" >}} -[implfromrequest]: https://docs.rs/actix-web/2/actix_web/trait.FromRequest.html -[respondertrait]: https://docs.rs/actix-web/2/actix_web/trait.Responder.html -[responderimpls]: https://docs.rs/actix-web/2/actix_web/trait.Responder.html#foreign-impls -[either]: https://docs.rs/actix-web/2/actix_web/enum.Either.html +[implfromrequest]: https://docs.rs/actix-web/3/actix_web/trait.FromRequest.html +[respondertrait]: https://docs.rs/actix-web/3/actix_web/trait.Responder.html +[responderimpls]: https://docs.rs/actix-web/3/actix_web/trait.Responder.html#foreign-impls +[either]: https://docs.rs/actix-web/3/actix_web/enum.Either.html diff --git a/content/docs/http2.md b/content/docs/http2.md index bd07d0d..e32c65e 100644 --- a/content/docs/http2.md +++ b/content/docs/http2.md @@ -1,15 +1,16 @@ --- -title: HTTP/2.0 -menu: docs_proto +title: HTTP/2 +menu: docs_protocols weight: 250 --- -`actix-web` automatically upgrades connections to *HTTP/2.0* if possible. +`actix-web` automatically upgrades connections to *HTTP/2* if possible. # Negotiation -*HTTP/2.0* protocol over tls without prior knowledge requires [tls alpn][tlsalpn]. +*HTTP/2* protocol over TLS without prior knowledge requires [TLS ALPN][tlsalpn]. + > Currently, only `rust-openssl` has support. `alpn` negotiation requires enabling the feature. When enabled, `HttpServer` provides the @@ -18,7 +19,6 @@ weight: 250 ```toml [dependencies] actix-web = { version = "{{< actix-version "actix-web" >}}", features = ["openssl"] } -actix-rt = "1.0.0" openssl = { version = "0.10", features = ["v110"] } ``` {{< include-example example="http2" file="main.rs" section="main" >}} @@ -31,6 +31,6 @@ connection and tls connection. [rfc section 3.4][rfcsection34]. [rfcsection32]: https://http2.github.io/http2-spec/#rfc.section.3.2 [rfcsection34]: https://http2.github.io/http2-spec/#rfc.section.3.4 -[bindopenssl]: https://docs.rs/actix-web/2/actix_web/struct.HttpServer.html#method.bind_openssl +[bindopenssl]: https://docs.rs/actix-web/3/actix_web/struct.HttpServer.html#method.bind_openssl [tlsalpn]: https://tools.ietf.org/html/rfc7301 [examples]: https://github.com/actix/examples/tree/master/rustls diff --git a/content/docs/http_server_init.md b/content/docs/http_server_init.md index 684ed97..71385cd 100644 --- a/content/docs/http_server_init.md +++ b/content/docs/http_server_init.md @@ -1,20 +1,21 @@ --- -title: Http Server Initialization +title: HTTP Server Initialization menu: docs_architecture weight: 1020 --- ## Architecture overview -Below is a diagram of HttpServer initalization, which happens on the following code +Below is a diagram of HttpServer initialization, which happens on the following code + ```rust -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { HttpServer::new(|| { App::new() .route("/", web::to(|| HttpResponse::Ok())) }) - .bind("127.0.0.1:8088")? + .bind("127.0.0.1:8080")? .run() .await } diff --git a/content/docs/installation.md b/content/docs/installation.md deleted file mode 100644 index 1b489f0..0000000 --- a/content/docs/installation.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -title: Installation -menu: docs_intro -weight: 110 ---- - -# Installing Rust - -Since `actix-web` is a Rust framework you will need Rust to get started with it. If you -don't have it yet we recommend you use `rustup` to manage your Rust installation. The -[official rust guide][rustguide] has a wonderful section on getting started. - -We currently require at least Rust {{< rust-version "actix-web" >}} so make sure you run -`rustup update` to have the latest and greatest Rust version available. In particular -this guide will assume that you actually run Rust {{< rust-version "actix-web" >}} or later. - -# Installing `actix-web` - -Thanks to Rust's `cargo` package manager you won't need to explicitly install -`actix-web`. Just depend on it and you're ready to go. For the unlikely -case that you want to use the development version of `actix-web` you can -depend on the git repository directly. - -Release version: - -```ini -[dependencies] -actix-web = "{{< actix-version "actix-web" >}}" -``` - -Development version: - -```ini -[dependencies] -actix-web = { git = "https://github.com/actix/actix-web" } -``` - -# Diving In - -There are two paths you can take here. You can follow the guide along or if you are very -impatient you might want to have a look at our [extensive example repository][examples] -and run the included examples. Here for instance is how you run the included `basics` -example: - -``` -git clone https://github.com/actix/examples -cd examples/basics -cargo run -``` - -[rustguide]: https://doc.rust-lang.org/book/ch01-01-installation.html -[examples]: https://github.com/actix/examples diff --git a/content/docs/middleware.md b/content/docs/middleware.md index cdd74b5..0b657cb 100644 --- a/content/docs/middleware.md +++ b/content/docs/middleware.md @@ -1,5 +1,5 @@ --- -title: Middlewares +title: Middleware menu: docs_advanced weight: 220 --- @@ -29,11 +29,11 @@ The following demonstrates creating a simple middleware: {{< include-example example="middleware" file="main.rs" section="simple" >}} -Alternatively, for simple use cases, you can use [*wrap_fn*][wrap_fn] to create small, ad-hoc middlewares: +Alternatively, for simple use cases, you can use [*wrap_fn*][wrap_fn] to create small, ad-hoc middleware: {{< include-example example="middleware" file="wrap_fn.rs" section="wrap-fn" >}} -> Actix-web provides several useful middlewares, such as *logging*, *user sessions*, +> Actix-web provides several useful middleware, such as *logging*, *user sessions*, > *compress*, etc. # Logging @@ -89,8 +89,7 @@ a specified header. ## User sessions Actix-web provides a general solution for session management. The -[**actix-session**][actixsession] middleware can be used with different backend types -to store session data in different backends. +[**actix-session**][actixsession] middleware can use multiple backend types to store session data. > By default, only cookie session backend is implemented. Other backend implementations > can be added. @@ -132,6 +131,6 @@ into a response. [cookiesession]: https://docs.rs/actix-session/0.3.0/actix_session/struct.CookieSession.html [actixsession]: https://docs.rs/actix-session/0.3.0/actix_session/ [envlogger]: https://docs.rs/env_logger/*/env_logger/ -[servicetrait]: https://docs.rs/actix-web/2/actix_web/dev/trait.Service.html -[transformtrait]: https://docs.rs/actix-web/2/actix_web/dev/trait.Transform.html -[wrap_fn]: https://docs.rs/actix-web/2/actix_web/struct.App.html#method.wrap_fn +[servicetrait]: https://docs.rs/actix-web/3/actix_web/dev/trait.Service.html +[transformtrait]: https://docs.rs/actix-web/3/actix_web/dev/trait.Transform.html +[wrap_fn]: https://docs.rs/actix-web/3/actix_web/struct.App.html#method.wrap_fn diff --git a/content/docs/request.md b/content/docs/request.md index 1843bf7..f224df1 100644 --- a/content/docs/request.md +++ b/content/docs/request.md @@ -81,7 +81,7 @@ In the following example, we read and print the request payload chunk by chunk: [multipartstruct]: https://docs.rs/actix-multipart/0.2/actix_multipart/struct.Multipart.html [fieldstruct]: https://docs.rs/actix-multipart/0.2/actix_multipart/struct.Field.html [multipartexample]: https://github.com/actix/examples/tree/master/multipart/ -[urlencoded]: https://docs.rs/actix-web/2/actix_web/dev/struct.UrlEncoded.html -[payloadextractor]: https://docs.rs/actix-web/2/actix_web/web/struct.Payload.html +[urlencoded]: https://docs.rs/actix-web/3/actix_web/dev/struct.UrlEncoded.html +[payloadextractor]: https://docs.rs/actix-web/3/actix_web/web/struct.Payload.html [multipartcrate]: https://crates.io/crates/actix-multipart -[formencoded]:Jhttps://docs.rs/actix-web/2/actix_web/web/struct.Form.html +[formencoded]:Jhttps://docs.rs/actix-web/3/actix_web/web/struct.Form.html diff --git a/content/docs/response.md b/content/docs/response.md index b63445b..53a99b8 100644 --- a/content/docs/response.md +++ b/content/docs/response.md @@ -71,5 +71,5 @@ The type `T` must implement the `Serialize` trait from *serde*. {{< include-example example="responses" file="json_resp.rs" section="json-resp" >}} -[responsebuilder]: https://docs.rs/actix-web/2/actix_web/dev/struct.HttpResponseBuilder.html -[compressmidddleware]: https://docs.rs/actix-web/2/actix_web/middleware/struct.Compress.html +[responsebuilder]: https://docs.rs/actix-web/3/actix_web/dev/struct.HttpResponseBuilder.html +[compressmidddleware]: https://docs.rs/actix-web/3/actix_web/middleware/struct.Compress.html diff --git a/content/docs/server.md b/content/docs/server.md index b5fc919..c07a1c6 100644 --- a/content/docs/server.md +++ b/content/docs/server.md @@ -6,32 +6,32 @@ weight: 150 # The HTTP Server -The [**HttpServer**][httpserverstruct] type is responsible for serving http requests. +The [**HttpServer**][httpserverstruct] type is responsible for serving HTTP requests. `HttpServer` accepts an application factory as a parameter, and the application factory must have `Send` + `Sync` boundaries. More about that in the *multi-threading* section. To bind to a specific socket address, [`bind()`][bindmethod] must be used, and it may be called multiple times. To bind ssl socket, [`bind_openssl()`][bindopensslmethod] or -[`bind_rustls()`][bindrusttls] should be used. To run the http server, use the `HttpServer::run()` +[`bind_rustls()`][bindrusttls] should be used. To run the HTTP server, use the `HttpServer::run()` method. {{< include-example example="server" section="main" >}} The `run()` method returns an instance of the [`Server`][server] type. Methods of server type -could be used for managing the http server +could be used for managing the HTTP server - `pause()` - Pause accepting incoming connections - `resume()` - Resume accepting incoming connections - `stop()` - Stop incoming connection processing, stop all workers and exit -The following example shows how to start the http server in a separate thread. +The following example shows how to start the HTTP server in a separate thread. {{< include-example example="server" file="signals.rs" section="signals" >}} ## Multi-threading -`HttpServer` automatically starts a number of http *workers*, by default this number is +`HttpServer` automatically starts a number of HTTP *workers*, by default this number is equal to the number of logical CPUs in the system. This number can be overridden with the [`HttpServer::workers()`][workers] method. @@ -120,7 +120,7 @@ Actix can wait for requests on a keep-alive connection. If the first option above is selected, then *keep alive* state is calculated based on the response's *connection-type*. By default `HttpResponse::connection_type` is not -defined. In that case *keep alive* is defined by the request's http version. +defined. In that case *keep alive* is defined by the request's HTTP version. > *keep alive* is **off** for *HTTP/1.0* and is **on** for *HTTP/1.1* and *HTTP/2.0*. @@ -149,14 +149,14 @@ are available on unix systems. > It is possible to disable signal handling with [`HttpServer::disable_signals()`][disablesignals] method. -[server]: https://docs.rs/actix-web/2/actix_web/dev/struct.Server.html -[httpserverstruct]: https://docs.rs/actix-web/2/actix_web/struct.HttpServer.html -[bindmethod]: https://docs.rs/actix-web/2/actix_web/struct.HttpServer.html#method.bind -[bindopensslmethod]: https://docs.rs/actix-web/2/actix_web/struct.HttpServer.html#method.bind_openssl -[bindrusttls]: https://docs.rs/actix-web/2/actix_web/struct.HttpServer.html#method.bind_rustls -[startmethod]: https://docs.rs/actix-web/2/actix_web/struct.HttpServer.html#method.start -[workers]: https://docs.rs/actix-web/2/actix_web/struct.HttpServer.html#method.workers +[server]: https://docs.rs/actix-web/3/actix_web/dev/struct.Server.html +[httpserverstruct]: https://docs.rs/actix-web/3/actix_web/struct.HttpServer.html +[bindmethod]: https://docs.rs/actix-web/3/actix_web/struct.HttpServer.html#method.bind +[bindopensslmethod]: https://docs.rs/actix-web/3/actix_web/struct.HttpServer.html#method.bind_openssl +[bindrusttls]: https://docs.rs/actix-web/3/actix_web/struct.HttpServer.html#method.bind_rustls +[startmethod]: https://docs.rs/actix-web/3/actix_web/struct.HttpServer.html#method.start +[workers]: https://docs.rs/actix-web/3/actix_web/struct.HttpServer.html#method.workers [tlsalpn]: https://tools.ietf.org/html/rfc7301 [exampleopenssl]: https://github.com/actix/examples/blob/master/openssl -[shutdowntimeout]: https://docs.rs/actix-web/2/actix_web/struct.HttpServer.html#method.shutdown_timeout -[disablesignals]: https://docs.rs/actix-web/2/actix_web/struct.HttpServer.html#method.disable_signals +[shutdowntimeout]: https://docs.rs/actix-web/3/actix_web/struct.HttpServer.html#method.shutdown_timeout +[disablesignals]: https://docs.rs/actix-web/3/actix_web/struct.HttpServer.html#method.disable_signals diff --git a/content/docs/testing.md b/content/docs/testing.md index 3a8c474..7e5f172 100644 --- a/content/docs/testing.md +++ b/content/docs/testing.md @@ -20,7 +20,7 @@ For unit testing, actix-web provides a request builder type. # Integration tests There are a few methods for testing your application. Actix-web can be used -to run the application with specific handlers in a real http server. +to run the application with specific handlers in a real HTTP server. `TestRequest::get()`, `TestRequest::post()` and other methods can be used to send requests to the test server. @@ -28,7 +28,7 @@ methods can be used to send requests to the test server. To create a `Service` for testing, use the `test::init_service` method which accepts a regular `App` builder. -> Check the [api documentation][actixdocs] for more information. +> Check the [API documentation][actixdocs] for more information. {{< include-example example="testing" file="integration_one.rs" section="integration-one" >}} @@ -47,6 +47,6 @@ resulting [*ResponseBody*][responsebody] into a future and execute it, for examp {{< include-example example="testing" file="stream_response.rs" section="stream-response" >}} [serversentevents]: https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events -[responsebody]: https://docs.rs/actix-web/2/actix_web/body/enum.ResponseBody.html -[actixdocs]: https://docs.rs/actix-web/2/actix_web/test/index.html -[testrequest]: https://docs.rs/actix-web/2/actix_web/test/struct.TestRequest.html +[responsebody]: https://docs.rs/actix-web/3/actix_web/body/enum.ResponseBody.html +[actixdocs]: https://docs.rs/actix-web/3/actix_web/test/index.html +[testrequest]: https://docs.rs/actix-web/3/actix_web/test/struct.TestRequest.html diff --git a/content/docs/url-dispatch.md b/content/docs/url-dispatch.md index 17edd50..8080a45 100644 --- a/content/docs/url-dispatch.md +++ b/content/docs/url-dispatch.md @@ -27,7 +27,7 @@ in *http://localhost:8080/foo/bar?q=value*). The [*App::route()*][approute] method provides simple way of registering routes. This method adds a single route to application routing table. This method accepts a *path pattern*, -*http method* and a handler function. `route()` method could be called multiple times +*HTTP method* and a handler function. `route()` method could be called multiple times for the same path, in that case, multiple routes register for the same resource path. {{< include-example example="url-dispatch" section="main" >}} @@ -40,7 +40,7 @@ adds a single [resource][webresource] to application routing table. This method {{< include-example example="url-dispatch" file="resource.rs" section="resource" >}} If a resource does not contain any route or does not have any matching routes, it -returns *NOT FOUND* http response. +returns *NOT FOUND* HTTP response. ## Configuring a Route @@ -197,7 +197,7 @@ When matching the following URL: http://example.com/foo/La%20Pe%C3%B1a ``` -The matchdict will look like so (the value is URL-decoded): +The match dictionary will look like so (the value is URL-decoded): ``` Params{'bar': 'La Pe\xf1a'} @@ -247,7 +247,7 @@ A scoped layout of these paths would appear as follows {{< include-example example="url-dispatch" file="scope.rs" section="scope" >}} A *scoped* path can contain variable path segments as resources. Consistent with -unscoped paths. +un-scoped paths. You can get variable path segments from `HttpRequest::match_info()`. [`Path` extractor][pathextractor] also is able to extract scope level variable segments. @@ -283,7 +283,7 @@ safe to interpolate within, or use as a suffix of, a path without additional che Actix provides functionality for type safe path information extraction. [*Path*][pathstruct] extracts information, destination type could be defined in several different forms. Simplest -approach is to use `tuple` type. Each element in tuple must correpond to one element from +approach is to use `tuple` type. Each element in tuple must correspond to one element from path pattern. i.e. you can match path pattern `/{id}/{username}/` against `Path<(u32, String)>` type, but `Path<(String, String, String)>` type will always fail. @@ -363,7 +363,7 @@ it will generate a URL with that same path. You can think of a guard as a simple function that accepts a *request* object reference and returns *true* or *false*. Formally, a guard is any object that implements the [`Guard`][guardtrait] trait. Actix provides several predicates, you can check -[functions section][guardfuncs] of api docs. +[functions section][guardfuncs] of API docs. Here is a simple guard that check that a request contains a specific *header*: @@ -407,24 +407,24 @@ with `App::service()` method. {{< include-example example="url-dispatch" file="dhandler.rs" section="default" >}} [handlersection]: ../handlers/ -[approute]: https://docs.rs/actix-web/2/actix_web/struct.App.html#method.route -[appservice]: https://docs.rs/actix-web/2/actix_web/struct.App.html?search=#method.service -[webresource]: https://docs.rs/actix-web/2/actix_web/struct.Resource.html -[resourcehandler]: https://docs.rs/actix-web/2/actix_web/struct.Resource.html#method.route -[route]: https://docs.rs/actix-web/2/actix_web/struct.Route.html -[routeguard]: https://docs.rs/actix-web/2/actix_web/struct.Route.html#method.guard -[routemethod]: https://docs.rs/actix-web/2/actix_web/struct.Route.html#method.method -[routeto]: https://docs.rs/actix-web/2/actix_web/struct.Route.html#method.to -[routetoasync]: https://docs.rs/actix-web/2/actix_web/struct.Route.html#method.to_async -[matchinfo]: https://docs.rs/actix-web/2/actix_web/struct.HttpRequest.html#method.match_info -[pathget]: https://docs.rs/actix-web/2/actix_web/dev/struct.Path.html#method.get -[pathstruct]: https://docs.rs/actix-web/2/actix_web/dev/struct.Path.html -[query]: https://docs.rs/actix-web/2/actix_web/web/struct.Query.html -[urlfor]: https://docs.rs/actix-web/2/actix_web/struct.HttpRequest.html#method.url_for +[approute]: https://docs.rs/actix-web/3/actix_web/struct.App.html#method.route +[appservice]: https://docs.rs/actix-web/3/actix_web/struct.App.html?search=#method.service +[webresource]: https://docs.rs/actix-web/3/actix_web/struct.Resource.html +[resourcehandler]: https://docs.rs/actix-web/3/actix_web/struct.Resource.html#method.route +[route]: https://docs.rs/actix-web/3/actix_web/struct.Route.html +[routeguard]: https://docs.rs/actix-web/3/actix_web/struct.Route.html#method.guard +[routemethod]: https://docs.rs/actix-web/3/actix_web/struct.Route.html#method.method +[routeto]: https://docs.rs/actix-web/3/actix_web/struct.Route.html#method.to +[routetoasync]: https://docs.rs/actix-web/3/actix_web/struct.Route.html#method.to_async +[matchinfo]: https://docs.rs/actix-web/3/actix_web/struct.HttpRequest.html#method.match_info +[pathget]: https://docs.rs/actix-web/3/actix_web/dev/struct.Path.html#method.get +[pathstruct]: https://docs.rs/actix-web/3/actix_web/dev/struct.Path.html +[query]: https://docs.rs/actix-web/3/actix_web/web/struct.Query.html +[urlfor]: https://docs.rs/actix-web/3/actix_web/struct.HttpRequest.html#method.url_for [urlobj]: https://docs.rs/url/1.7.2/url/struct.Url.html -[guardtrait]: https://docs.rs/actix-web/2/actix_web/guard/trait.Guard.html -[guardfuncs]: https://docs.rs/actix-web/2/actix_web/guard/index.html#functions -[requestextensions]: https://docs.rs/actix-web/2/actix_web/struct.HttpRequest.html#method.extensions -[implfromrequest]: https://docs.rs/actix-web/2/actix_web/trait.FromRequest.html -[implresponder]: https://docs.rs/actix-web/2/actix_web/trait.Responder.html +[guardtrait]: https://docs.rs/actix-web/3/actix_web/guard/trait.Guard.html +[guardfuncs]: https://docs.rs/actix-web/3/actix_web/guard/index.html#functions +[requestextensions]: https://docs.rs/actix-web/3/actix_web/struct.HttpRequest.html#method.extensions +[implfromrequest]: https://docs.rs/actix-web/3/actix_web/trait.FromRequest.html +[implresponder]: https://docs.rs/actix-web/3/actix_web/trait.Responder.html [pathextractor]: ../extractors diff --git a/content/docs/websockets.md b/content/docs/websockets.md index 4e200cf..0ac6c3c 100644 --- a/content/docs/websockets.md +++ b/content/docs/websockets.md @@ -1,6 +1,6 @@ --- title: Websockets -menu: docs_proto +menu: docs_protocols weight: 240 --- @@ -15,10 +15,10 @@ The following is an example of a simple websocket echo server: > A simple websocket echo server example is available in the [examples directory][examples]. -> An example chat server with the ability to chat over a websocket or tcp connection +> An example chat server with the ability to chat over a websocket or TCP connection > is available in [websocket-chat directory][chat] [message]: https://docs.rs/actix-web-actors/2/actix_web_actors/ws/enum.Message.html -[payload]: https://docs.rs/actix-web/2/actix_web/web/struct.Payload.html +[payload]: https://docs.rs/actix-web/3/actix_web/web/struct.Payload.html [examples]: https://github.com/actix/examples/tree/master/websocket/ [chat]: https://github.com/actix/examples/tree/master/websocket-chat/ diff --git a/content/docs/whatis.md b/content/docs/whatis.md index 67765d6..02c325e 100644 --- a/content/docs/whatis.md +++ b/content/docs/whatis.md @@ -4,24 +4,29 @@ menu: docs_intro weight: 100 --- -# Actix is Multiple Things +# Actix is an ecosystem of crates -Actix is a few things. The base of it is a powerful actor system for Rust on -top of which the `actix-web` system was originally built. This is what you are most -likely going to work with. What `actix-web` gives you is a fun and very fast web -development framework. +Actix is a few things. The base of it is a powerful actor system for Rust on top of which the +`actix-web` system was originally built. This is what you are most likely going to work with. What +`actix-web` gives you is a powerful and very fast web development framework. -We call `actix-web` a small and pragmatic framework. For all intents and purposes -it's a microframework with a few twists. If you are already a Rust programmer -you will probably find yourself at home quickly, but even if you are coming from -another programming language you should find `actix-web` easy to pick up. +We call `actix-web` a small and pragmatic framework. For all intents and purposes it's a +micro-framework with a few twists. If you are already a Rust programmer you will probably find +yourself at home quickly, but even if you are coming from another programming language you should +find `actix-web` easy to pick up. -An application developed with `actix-web` will expose an HTTP server contained -within a native executable. You can either put this behind another HTTP server like -nginx or serve it up as-is. Even in the complete absence of another HTTP -server `actix-web` is powerful enough to provide HTTP 1 and HTTP 2 support as -well as SSL/TLS. This makes it useful for building small services ready for +An application developed with `actix-web` will expose an HTTP server contained within a native +executable. You can either put this behind another HTTP server like nginx or serve it up as-is. Even +in the complete absence of another HTTP server `actix-web` is powerful enough to provide HTTP/1 and +HTTP/2 support as well as TLS (HTTPS). This makes it useful for building small services ready for distribution. -Most importantly: `actix-web` runs on Rust {{< rust-version "actix-web" >}} or later -and it works with stable releases. +Most importantly: `actix-web` runs on Rust {{< rust-version "actix-web" >}} or later and it works +with stable releases. + + + + + + +[tokio]: https://tokio.rs diff --git a/examples/Cargo.toml b/examples/Cargo.toml index a9d2fb1..2ed682d 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -1,30 +1,26 @@ [workspace] members = [ "application", + "async-handlers", "easy-form-handling", + "either", + "errors", + "extractors", "flexible-responders", "getting-started", - "main-example", - "powerful-extractors", - "request-routing", - "server", - "url-dispatch", - "responder-trait", - "either", - "extractors", - "autoreload", - "errors", - "requests", - "responses", - "middleware", - "static-files", "http2", - "testing", - "async-handlers", - "websockets", + "main-example", + "middleware", + "powerful-extractors", "request-handlers", + "request-routing", + "requests", + "responder-trait", + "responses", + "server", + "static-files", + "testing", + "url-dispatch", + "websockets", ] -exclude = [ - "og_databases", - "sentry", -] +exclude = ["databases", "sentry"] diff --git a/examples/application/Cargo.toml b/examples/application/Cargo.toml index f055c6a..5483f29 100644 --- a/examples/application/Cargo.toml +++ b/examples/application/Cargo.toml @@ -5,6 +5,5 @@ edition = "2018" workspace = "../" [dependencies] -actix-web = "2.0" -actix-rt = "1.0" -actix-service = "1.0" +actix-web = "3" +actix-service = "1" diff --git a/examples/application/src/app.rs b/examples/application/src/app.rs index c31668b..b0c3871 100644 --- a/examples/application/src/app.rs +++ b/examples/application/src/app.rs @@ -1,18 +1,23 @@ +#![allow(dead_code)] + // -use actix_web::{web, App, Responder, HttpServer}; +use actix_web::{web, App, HttpServer, Responder}; async fn index() -> impl Responder { "Hello world!" } -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { HttpServer::new(|| { App::new().service( - web::scope("/app").route("/index.html", web::get().to(index)), + // prefixes all resources and routes attached to it... + web::scope("/app") + // ...so this handles requests for `GET /app/index.html` + .route("/index.html", web::get().to(index)), ) }) - .bind("127.0.0.1:8088")? + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/application/src/combine.rs b/examples/application/src/combine.rs index ce11025..0f7cbc0 100644 --- a/examples/application/src/combine.rs +++ b/examples/application/src/combine.rs @@ -1,24 +1,27 @@ +#![allow(dead_code)] + use actix_web::{web, App, HttpResponse, HttpServer}; // struct State1; struct State2; -#[rustfmt::skip] -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { HttpServer::new(|| { App::new() .service( web::scope("/app1") .data(State1) - .route("/", web::to(|| HttpResponse::Ok()))) + .route("/", web::to(|| HttpResponse::Ok())), + ) .service( web::scope("/app2") .data(State2) - .route("/", web::to(|| HttpResponse::Ok()))) + .route("/", web::to(|| HttpResponse::Ok())), + ) }) - .bind("127.0.0.1:8088")? + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/application/src/config.rs b/examples/application/src/config.rs index 486d64e..8d0571e 100644 --- a/examples/application/src/config.rs +++ b/examples/application/src/config.rs @@ -1,3 +1,5 @@ +#![allow(dead_code)] + // use actix_web::{web, App, HttpResponse, HttpServer}; @@ -19,7 +21,7 @@ fn config(cfg: &mut web::ServiceConfig) { ); } -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { HttpServer::new(|| { App::new() @@ -27,7 +29,7 @@ async fn main() -> std::io::Result<()> { .service(web::scope("/api").configure(scoped_config)) .route("/", web::get().to(|| HttpResponse::Ok().body("/"))) }) - .bind("127.0.0.1:8088")? + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/application/src/main.rs b/examples/application/src/main.rs index d1a7afa..86a1ade 100644 --- a/examples/application/src/main.rs +++ b/examples/application/src/main.rs @@ -8,7 +8,7 @@ pub mod state; pub mod vh; // -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { HttpServer::new(|| { App::new() @@ -20,7 +20,7 @@ async fn main() -> std::io::Result<()> { ) .route("/", web::to(|| HttpResponse::Ok())) }) - .bind("127.0.0.1:8088")? + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/application/src/mutable_state.rs b/examples/application/src/mutable_state.rs index 855545a..fc43cec 100644 --- a/examples/application/src/mutable_state.rs +++ b/examples/application/src/mutable_state.rs @@ -15,7 +15,7 @@ async fn index(data: web::Data) -> String { // // -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { let counter = web::Data::new(AppStateWithCounter { counter: Mutex::new(0), @@ -28,7 +28,7 @@ async fn main() -> std::io::Result<()> { .app_data(counter.clone()) // <- register the created data .route("/", web::get().to(index)) }) - .bind("127.0.0.1:8088")? + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/application/src/scope.rs b/examples/application/src/scope.rs index 84a7087..28364e5 100644 --- a/examples/application/src/scope.rs +++ b/examples/application/src/scope.rs @@ -1,16 +1,14 @@ -use actix_web::{web, App, HttpRequest, Responder}; +use actix_web::{get, web, App, HttpRequest, Responder}; +#[get("/show")] async fn show_users(_req: HttpRequest) -> impl Responder { "unimplemented!" } -#[rustfmt::skip] // -#[actix_rt::main] +#[actix_web::main] async fn main() { - App::new() - .service( - web::scope("/users") - .route("/show", web::get().to(show_users))); + let scope = web::scope("/users").service(show_users); + App::new().service(scope); } // diff --git a/examples/application/src/state.rs b/examples/application/src/state.rs index 2dcf672..c73fbc2 100644 --- a/examples/application/src/state.rs +++ b/examples/application/src/state.rs @@ -1,12 +1,12 @@ // -use actix_web::{web, App, HttpServer}; -use std::sync::Mutex; +use actix_web::{get, web, App, HttpServer}; // This struct represents state struct AppState { app_name: String, } +#[get("/")] async fn index(data: web::Data) -> String { let app_name = &data.app_name; // <- get app_name @@ -15,16 +15,16 @@ async fn index(data: web::Data) -> String { // // -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { HttpServer::new(|| { App::new() .data(AppState { app_name: String::from("Actix-web"), }) - .route("/", web::get().to(index)) + .service(index) }) - .bind("127.0.0.1:8088")? + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/application/src/vh.rs b/examples/application/src/vh.rs index d1d6c82..4ad476f 100644 --- a/examples/application/src/vh.rs +++ b/examples/application/src/vh.rs @@ -1,7 +1,7 @@ use actix_web::{guard, web, App, HttpResponse, HttpServer}; // -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { HttpServer::new(|| { App::new() @@ -17,7 +17,7 @@ async fn main() -> std::io::Result<()> { ) .route("/", web::to(|| HttpResponse::Ok())) }) - .bind("127.0.0.1:8088")? + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/async-handlers/Cargo.toml b/examples/async-handlers/Cargo.toml index c1e24a2..2ba3c07 100644 --- a/examples/async-handlers/Cargo.toml +++ b/examples/async-handlers/Cargo.toml @@ -4,7 +4,6 @@ version = "2.0.0" edition = "2018" [dependencies] -actix-web = "2.0" -actix-rt = "1.0" +actix-web = "3" futures = "0.3.1" bytes = "0.5" diff --git a/examples/async-handlers/src/stream.rs b/examples/async-handlers/src/stream.rs index 3399f33..96f9d86 100644 --- a/examples/async-handlers/src/stream.rs +++ b/examples/async-handlers/src/stream.rs @@ -1,10 +1,11 @@ // -use actix_web::{web, App, HttpServer, Error, HttpResponse}; +use actix_web::{get, App, Error, HttpResponse, HttpServer}; use bytes::Bytes; -use futures::stream::once; use futures::future::ok; +use futures::stream::once; -async fn index() -> HttpResponse { +#[get("/stream")] +async fn stream() -> HttpResponse { let body = once(ok::<_, Error>(Bytes::from_static(b"test"))); HttpResponse::Ok() @@ -12,10 +13,10 @@ async fn index() -> HttpResponse { .streaming(body) } -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { - HttpServer::new(|| App::new().route("/async", web::to(index))) - .bind("127.0.0.1:8088")? + HttpServer::new(|| App::new().service(stream)) + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/autoreload/Cargo.toml b/examples/autoreload/Cargo.toml deleted file mode 100644 index 1561236..0000000 --- a/examples/autoreload/Cargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[package] -name = "autoreload" -version = "1.0.0" -edition = "2018" - -[dependencies] -actix-web = "2.0" -actix-rt = "1.0" -listenfd = "0.3" diff --git a/examples/autoreload/src/main.rs b/examples/autoreload/src/main.rs deleted file mode 100644 index 3ceff63..0000000 --- a/examples/autoreload/src/main.rs +++ /dev/null @@ -1,22 +0,0 @@ -// -use actix_web::{web, App, HttpRequest, HttpServer, Responder}; -use listenfd::ListenFd; - -async fn index(_req: HttpRequest) -> impl Responder { - "Hello World!" -} - -#[actix_rt::main] -async fn main() -> std::io::Result<()> { - let mut listenfd = ListenFd::from_env(); - let mut server = HttpServer::new(|| App::new().route("/", web::get().to(index))); - - server = if let Some(l) = listenfd.take_tcp_listener(0).unwrap() { - server.listen(l)? - } else { - server.bind("127.0.0.1:3000")? - }; - - server.run().await -} -// diff --git a/examples/databases/Cargo.toml b/examples/databases/Cargo.toml new file mode 100644 index 0000000..1fcc13a --- /dev/null +++ b/examples/databases/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "databases" +version = "1.0.0" +edition = "2018" + +[dependencies] +actix-web = "3" diff --git a/examples/databases/src/main.rs b/examples/databases/src/main.rs new file mode 100644 index 0000000..95aa2a4 --- /dev/null +++ b/examples/databases/src/main.rs @@ -0,0 +1,63 @@ +// +fn insert_new_user(db: &SqliteConnection, user: CreateUser) -> Result { + use self::schema::users::dsl::*; + + // Create insertion model + let uuid = format!("{}", uuid::Uuid::new_v4()); + let new_user = models::NewUser { + id: &uuid, + name: &user.name, + }; + + // normal diesel operations + diesel::insert_into(users) + .values(&new_user) + .execute(&self.0) + .expect("Error inserting person"); + + let mut items = users + .filter(id.eq(&uuid)) + .load::(&self.0) + .expect("Error loading person"); + + Ok(items.pop().unwrap()) +} +// + +//
+type DbPool = r2d2::Pool>; + +#[actix_web::main] +async fn main() -> io::Result<()> { + // Create connection pool + let pool = r2d2::Pool::builder() + .build(manager) + .expect("Failed to create pool."); + + // Start HTTP server + HttpServer::new(move || { + App::new::data(pool.clone()) + .resource("/{name}", web::get().to(index)) + }) + .bind("127.0.0.1:8080")? + .run() + .await +} +//
+ +// +async fn index(req: web::Data, name: web::Path<(String)>) -> impl Responder { + let name = name.into_inner(); + + let conn = pool.get().expect("couldn't get db connection from pool"); + + let user = web::block(move || actions::insert_new_user(&conn, &user)) + .await + .map_err(|e| { + eprintln!("{}", e); + HttpResponse::InternalServerError().finish() + })?; + + Ok(HttpResponse::Ok().json(user)) +} +// diff --git a/examples/easy-form-handling/Cargo.toml b/examples/easy-form-handling/Cargo.toml index 1af8b96..737ea4c 100644 --- a/examples/easy-form-handling/Cargo.toml +++ b/examples/easy-form-handling/Cargo.toml @@ -4,6 +4,5 @@ version = "1.0.0" edition = "2018" [dependencies] -actix-web = "2.0" -actix-rt = "1.0" +actix-web = "3" serde = "1.0" diff --git a/examples/easy-form-handling/src/main.rs b/examples/easy-form-handling/src/main.rs index 1bc63f4..bf555b3 100644 --- a/examples/easy-form-handling/src/main.rs +++ b/examples/easy-form-handling/src/main.rs @@ -18,14 +18,14 @@ async fn register(form: web::Form) -> impl Responder { format!("Hello {} from {}!", form.username, form.country) } -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { HttpServer::new(|| { App::new() .route("/", web::get().to(index)) .route("/register", web::post().to(register)) }) - .bind("127.0.0.1:8088")? + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/either/Cargo.toml b/examples/either/Cargo.toml index 9f8a8f8..4f49fc6 100644 --- a/examples/either/Cargo.toml +++ b/examples/either/Cargo.toml @@ -4,5 +4,4 @@ version = "1.0.0" edition = "2018" [dependencies] -actix-web = "1.0" -futures = "0.1" +actix-web = "3" diff --git a/examples/either/src/main.rs b/examples/either/src/main.rs index ab5208c..8b45797 100644 --- a/examples/either/src/main.rs +++ b/examples/either/src/main.rs @@ -3,7 +3,7 @@ use actix_web::{Either, Error, HttpResponse}; type RegisterResult = Either>; -fn index() -> RegisterResult { +async fn index() -> RegisterResult { if is_a_variant() { // <- choose variant A Either::A(HttpResponse::BadRequest().body("Bad data")) @@ -14,14 +14,14 @@ fn index() -> RegisterResult { } // -fn main() { +#[actix_web::main] +async fn main() -> std::io::Result<()> { use actix_web::{web, App, HttpServer}; HttpServer::new(|| App::new().route("/", web::get().to(index))) - .bind("127.0.0.1:8088") - .unwrap() + .bind("127.0.0.1:8080")? .run() - .unwrap(); + .await } fn is_a_variant() -> bool { diff --git a/examples/errors/Cargo.toml b/examples/errors/Cargo.toml index ed0f4f6..45995a3 100644 --- a/examples/errors/Cargo.toml +++ b/examples/errors/Cargo.toml @@ -4,9 +4,8 @@ version = "1.0.0" edition = "2018" [dependencies] -actix-web = "2.0.0" -actix-rt = "1.0.0" -env_logger = "0.7.1" -log = "0.4.8" -failure = "0.1.6" -actix-http = "1.0.1" +actix-web = "3" +derive_more = "0.99" +env_logger = "0.7" +log = "0.4" +# actix-http = "1" diff --git a/examples/errors/src/helpers.rs b/examples/errors/src/helpers.rs index 690a2d2..9807b95 100644 --- a/examples/errors/src/helpers.rs +++ b/examples/errors/src/helpers.rs @@ -1,12 +1,12 @@ -use actix_web::{web, App}; // -use actix_web::{error, Result}; +use actix_web::{error, get, App, HttpServer, Result}; #[derive(Debug)] struct MyError { name: &'static str, } +#[get("/")] async fn index() -> Result<&'static str> { let result: Result<&'static str, MyError> = Err(MyError { name: "test error" }); @@ -14,12 +14,10 @@ async fn index() -> Result<&'static str> { } // -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { - use actix_web::HttpServer; - - HttpServer::new(|| App::new().route("/", web::get().to(index))) - .bind("127.0.0.1:8088")? + HttpServer::new(|| App::new().service(index)) + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/errors/src/logging.rs b/examples/errors/src/logging.rs index 5e4987d..82d299c 100644 --- a/examples/errors/src/logging.rs +++ b/examples/errors/src/logging.rs @@ -1,10 +1,10 @@ // -use actix_web::{error, Result}; -use failure::Fail; +use actix_web::{error, get, middleware::Logger, App, HttpServer, Result}; use log::debug; +use derive_more::{Display, Error}; -#[derive(Fail, Debug)] -#[fail(display = "my error")] +#[derive(Debug, Display, Error)] +#[display(fmt = "my error: {}", name)] pub struct MyError { name: &'static str, } @@ -12,27 +12,22 @@ pub struct MyError { // Use default implementation for `error_response()` method impl error::ResponseError for MyError {} +#[get("/")] async fn index() -> Result<&'static str, MyError> { let err = MyError { name: "test error" }; debug!("{}", err); Err(err) } -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { - use actix_web::{middleware::Logger, web, App, HttpServer}; - std::env::set_var("RUST_LOG", "my_errors=debug,actix_web=info"); std::env::set_var("RUST_BACKTRACE", "1"); env_logger::init(); - HttpServer::new(|| { - App::new() - .wrap(Logger::default()) - .route("/", web::get().to(index)) - }) - .bind("127.0.0.1:8088")? - .run() - .await + HttpServer::new(|| App::new().wrap(Logger::default()).service(index)) + .bind("127.0.0.1:8080")? + .run() + .await } // diff --git a/examples/errors/src/main.rs b/examples/errors/src/main.rs index ac6d13b..31b462f 100644 --- a/examples/errors/src/main.rs +++ b/examples/errors/src/main.rs @@ -6,10 +6,10 @@ pub mod recommend_two; // use actix_web::{error, Result}; -use failure::Fail; +use derive_more::{Display, Error}; -#[derive(Fail, Debug)] -#[fail(display = "my error")] +#[derive(Debug, Display, Error)] +#[display(fmt = "my error: {}", name)] struct MyError { name: &'static str, } @@ -22,12 +22,12 @@ async fn index() -> Result<&'static str, MyError> { } // -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { use actix_web::{web, App, HttpServer}; HttpServer::new(|| App::new().route("/", web::get().to(index))) - .bind("127.0.0.1:8088")? + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/errors/src/override_error.rs b/examples/errors/src/override_error.rs index ad7c786..dd01b1c 100644 --- a/examples/errors/src/override_error.rs +++ b/examples/errors/src/override_error.rs @@ -1,22 +1,24 @@ -use actix_web::{web, App}; // -use actix_http::ResponseBuilder; -use actix_web::{error, http::header, http::StatusCode, HttpResponse}; -use failure::Fail; +use actix_web::{ + dev::HttpResponseBuilder, error, get, http::header, http::StatusCode, App, HttpResponse, +}; +use derive_more::{Display, Error}; -#[derive(Fail, Debug)] +#[derive(Debug, Display, Error)] enum MyError { - #[fail(display = "internal error")] + #[display(fmt = "internal error")] InternalError, - #[fail(display = "bad request")] + + #[display(fmt = "bad request")] BadClientData, - #[fail(display = "timeout")] + + #[display(fmt = "timeout")] Timeout, } impl error::ResponseError for MyError { fn error_response(&self) -> HttpResponse { - ResponseBuilder::new(self.status_code()) + HttpResponseBuilder::new(self.status_code()) .set_header(header::CONTENT_TYPE, "text/html; charset=utf-8") .body(self.to_string()) } @@ -30,30 +32,28 @@ impl error::ResponseError for MyError { } } +#[get("/")] async fn index() -> Result<&'static str, MyError> { Err(MyError::BadClientData) } // +#[get("/e2")] async fn error2() -> Result<&'static str, MyError> { Err(MyError::InternalError) } +#[get("/e3")] async fn error3() -> Result<&'static str, MyError> { Err(MyError::Timeout) } -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { use actix_web::HttpServer; - HttpServer::new(|| { - App::new() - .route("/", web::get().to(index)) - .route("/e2", web::get().to(error2)) - .route("/e3", web::get().to(error3)) - }) - .bind("127.0.0.1:8088")? - .run() - .await + HttpServer::new(|| App::new().service(index).service(error2).service(error3)) + .bind("127.0.0.1:8080")? + .run() + .await } diff --git a/examples/errors/src/recommend_one.rs b/examples/errors/src/recommend_one.rs index 1d42e4e..4946244 100644 --- a/examples/errors/src/recommend_one.rs +++ b/examples/errors/src/recommend_one.rs @@ -1,17 +1,19 @@ // -use actix_http::ResponseBuilder; -use actix_web::{error, http::header, http::StatusCode, HttpResponse}; -use failure::Fail; +use actix_web::{ + dev::HttpResponseBuilder, error, get, http::header, http::StatusCode, App, HttpResponse, + HttpServer, +}; +use derive_more::{Display, Error}; -#[derive(Fail, Debug)] +#[derive(Debug, Display, Error)] enum UserError { - #[fail(display = "Validation error on field: {}", field)] + #[display(fmt = "Validation error on field: {}", field)] ValidationError { field: String }, } impl error::ResponseError for UserError { fn error_response(&self) -> HttpResponse { - ResponseBuilder::new(self.status_code()) + HttpResponseBuilder::new(self.status_code()) .set_header(header::CONTENT_TYPE, "text/html; charset=utf-8") .body(self.to_string()) } @@ -22,18 +24,18 @@ impl error::ResponseError for UserError { } } // + +#[get("/")] async fn index() -> Result<&'static str, UserError> { Err(UserError::ValidationError { field: "bad stuff".to_string(), }) } -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { - use actix_web::{web, App, HttpServer}; - - HttpServer::new(|| App::new().route("/", web::get().to(index))) - .bind("127.0.0.1:8088")? + HttpServer::new(|| App::new().service(index)) + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/errors/src/recommend_two.rs b/examples/errors/src/recommend_two.rs index b189428..5eac113 100644 --- a/examples/errors/src/recommend_two.rs +++ b/examples/errors/src/recommend_two.rs @@ -1,17 +1,19 @@ // -use actix_http::ResponseBuilder; -use actix_web::{error, http::header, http::StatusCode, HttpResponse}; -use failure::Fail; +use actix_web::{ + dev::HttpResponseBuilder, error, get, http::header, http::StatusCode, App, HttpResponse, + HttpServer, +}; +use derive_more::{Display, Error}; -#[derive(Fail, Debug)] +#[derive(Debug, Display, Error)] enum UserError { - #[fail(display = "An internal error occurred. Please try again later.")] + #[display(fmt = "An internal error occurred. Please try again later.")] InternalError, } impl error::ResponseError for UserError { fn error_response(&self) -> HttpResponse { - ResponseBuilder::new(self.status_code()) + HttpResponseBuilder::new(self.status_code()) .set_header(header::CONTENT_TYPE, "text/html; charset=utf-8") .body(self.to_string()) } @@ -22,22 +24,21 @@ impl error::ResponseError for UserError { } } +#[get("/")] async fn index() -> Result<&'static str, UserError> { - do_thing_that_failes().map_err(|_e| UserError::InternalError)?; + do_thing_that_fails().map_err(|_e| UserError::InternalError)?; Ok("success!") } // -fn do_thing_that_failes() -> Result<(), std::io::Error> { +fn do_thing_that_fails() -> Result<(), std::io::Error> { Err(std::io::Error::new(std::io::ErrorKind::Other, "some error")) } -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { - use actix_web::{web, App, HttpServer}; - - HttpServer::new(|| App::new().route("/", web::get().to(index))) - .bind("127.0.0.1:8088")? + HttpServer::new(|| App::new().service(index)) + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/extractors/Cargo.toml b/examples/extractors/Cargo.toml index a455806..4842587 100644 --- a/examples/extractors/Cargo.toml +++ b/examples/extractors/Cargo.toml @@ -4,7 +4,6 @@ version = "1.0.0" edition = "2018" [dependencies] -actix-web = "2.0" -actix-rt = "1.0" +actix-web = "3" serde = "1.0" serde_json = "1.0" diff --git a/examples/extractors/src/form.rs b/examples/extractors/src/form.rs index 43dc763..d03dd28 100644 --- a/examples/extractors/src/form.rs +++ b/examples/extractors/src/form.rs @@ -1,5 +1,5 @@ //
-use actix_web::{web, Result}; +use actix_web::{post, web, App, HttpServer, Result}; use serde::Deserialize; #[derive(Deserialize)] @@ -10,17 +10,16 @@ struct FormData { /// extract form data using serde /// this handler gets called only if the content type is *x-www-form-urlencoded* /// and the content of the request could be deserialized to a `FormData` struct +#[post("/")] async fn index(form: web::Form) -> Result { Ok(format!("Welcome {}!", form.username)) } // -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { - use actix_web::{App, HttpServer}; - - HttpServer::new(|| App::new().route("/", web::post().to(index))) - .bind("127.0.0.1:8088")? + HttpServer::new(|| App::new().service(index)) + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/extractors/src/json_one.rs b/examples/extractors/src/json_one.rs index b5c2675..f38084d 100644 --- a/examples/extractors/src/json_one.rs +++ b/examples/extractors/src/json_one.rs @@ -1,5 +1,5 @@ // -use actix_web::{web, Result}; +use actix_web::{get, web, App, HttpServer, Result}; use serde::Deserialize; #[derive(Deserialize)] @@ -8,17 +8,16 @@ struct Info { } /// deserialize `Info` from request's body +#[get("/")] async fn index(info: web::Json) -> Result { Ok(format!("Welcome {}!", info.username)) } // -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { - use actix_web::{App, HttpServer}; - - HttpServer::new(|| App::new().route("/", web::post().to(index))) - .bind("127.0.0.1:8088")? + HttpServer::new(|| App::new().service(index)) + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/extractors/src/json_two.rs b/examples/extractors/src/json_two.rs index bf7b9f9..30d2090 100644 --- a/examples/extractors/src/json_two.rs +++ b/examples/extractors/src/json_two.rs @@ -1,5 +1,7 @@ +#![allow(dead_code)] + // -use actix_web::{error, web, FromRequest, HttpResponse, Responder}; +use actix_web::{error, web, App, FromRequest, HttpResponse, HttpServer, Responder}; use serde::Deserialize; #[derive(Deserialize)] @@ -12,28 +14,24 @@ async fn index(info: web::Json) -> impl Responder { format!("Welcome {}!", info.username) } -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { - use actix_web::{App, HttpServer}; - HttpServer::new(|| { + let json_config = web::JsonConfig::default() + .limit(4096) + .error_handler(|err, _req| { + // create custom error response + error::InternalError::from_response(err, HttpResponse::Conflict().finish()).into() + }); + App::new().service( web::resource("/") // change json extractor configuration - .app_data(web::Json::::configure(|cfg| { - cfg.limit(4096).error_handler(|err, _req| { - // create custom error response - error::InternalError::from_response( - err, - HttpResponse::Conflict().finish(), - ) - .into() - }) - })) + .app_data(json_config) .route(web::post().to(index)), ) }) - .bind("127.0.0.1:8088")? + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/extractors/src/main.rs b/examples/extractors/src/main.rs index 07f40a2..a5995d3 100644 --- a/examples/extractors/src/main.rs +++ b/examples/extractors/src/main.rs @@ -18,17 +18,18 @@ struct MyInfo { } // -async fn index( - path: web::Path<(String, String)>, - json: web::Json, -) -> impl Responder { +async fn index(path: web::Path<(String, String)>, json: web::Json) -> impl Responder { + let path = path.into_inner(); format!("{} {} {} {}", path.0, path.1, json.id, json.username) } // // async fn extract(req: HttpRequest) -> impl Responder { - let params = web::Path::<(String, String)>::extract(&req).await.unwrap(); + let params = web::Path::<(String, String)>::extract(&req) + .await + .unwrap() + .into_inner(); let info = web::Json::::extract(&req) .await @@ -38,14 +39,14 @@ async fn extract(req: HttpRequest) -> impl Responder { } // -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { HttpServer::new(|| { App::new() .route("/{name}/{id}", web::post().to(index)) .route("/{name}/{id}/extract", web::post().to(extract)) }) - .bind("127.0.0.1:8088")? + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/extractors/src/multiple.rs b/examples/extractors/src/multiple.rs index 76cd0e7..83bee27 100644 --- a/examples/extractors/src/multiple.rs +++ b/examples/extractors/src/multiple.rs @@ -1,5 +1,5 @@ // -use actix_web::web; +use actix_web::{get, web}; use serde::Deserialize; #[derive(Deserialize)] @@ -7,27 +7,24 @@ struct Info { username: String, } +#[get("/users/{user_id}/{friend}")] // <- define path parameters async fn index( - (path, query): (web::Path<(u32, String)>, web::Query), + web::Path((user_id, friend)): web::Path<(u32, String)>, + query: web::Query, ) -> String { format!( - "Welcome {}, friend {}, userid {}!", - query.username, path.1, path.0 + "Welcome {}, friend {}, user_id {}!", + query.username, friend, user_id ) } -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { use actix_web::{App, HttpServer}; - HttpServer::new(|| { - App::new().route( - "/users/{userid}/{friend}", // <- define path parameters - web::get().to(index), - ) - }) - .bind("127.0.0.1:8088")? - .run() - .await + HttpServer::new(|| App::new().service(index)) + .bind("127.0.0.1:8080")? + .run() + .await } // diff --git a/examples/extractors/src/path_one.rs b/examples/extractors/src/path_one.rs index a378ba2..24edc98 100644 --- a/examples/extractors/src/path_one.rs +++ b/examples/extractors/src/path_one.rs @@ -1,25 +1,21 @@ // -use actix_web::{web, Result}; +use actix_web::{get, web, Result}; -/// extract path info from "/users/{userid}/{friend}" url -/// {userid} - - deserializes to a u32 +/// extract path info from "/users/{user_id}/{friend}" url +/// {user_id} - deserializes to a u32 /// {friend} - deserializes to a String -async fn index(info: web::Path<(u32, String)>) -> Result { - Ok(format!("Welcome {}, userid {}!", info.1, info.0)) +#[get("/users/{user_id}/{friend}")] // <- define path parameters +async fn index(web::Path((user_id, friend)): web::Path<(u32, String)>) -> Result { + Ok(format!("Welcome {}, user_id {}!", friend, user_id)) } -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { use actix_web::{App, HttpServer}; - HttpServer::new(|| { - App::new().route( - "/users/{userid}/{friend}", // <- define path parameters - web::get().to(index), - ) - }) - .bind("127.0.0.1:8088")? - .run() - .await + HttpServer::new(|| App::new().service(index)) + .bind("127.0.0.1:8080")? + .run() + .await } // diff --git a/examples/extractors/src/path_three.rs b/examples/extractors/src/path_three.rs index 656e3d5..85819b5 100644 --- a/examples/extractors/src/path_three.rs +++ b/examples/extractors/src/path_three.rs @@ -1,26 +1,21 @@ -use actix_web::{web, HttpRequest, Result}; +use actix_web::{get, HttpRequest, Result}; // +#[get("/users/{userid}/{friend}")] // <- define path parameters async fn index(req: HttpRequest) -> Result { - let name: String = - req.match_info().get("friend").unwrap().parse().unwrap(); + let name: String = req.match_info().get("friend").unwrap().parse().unwrap(); let userid: i32 = req.match_info().query("userid").parse().unwrap(); Ok(format!("Welcome {}, userid {}!", name, userid)) } -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { use actix_web::{App, HttpServer}; - HttpServer::new(|| { - App::new().route( - "/users/{userid}/{friend}", // <- define path parameters - web::get().to(index), - ) - }) - .bind("127.0.0.1:8088")? - .run() - .await + HttpServer::new(|| App::new().service(index)) + .bind("127.0.0.1:8080")? + .run() + .await } // diff --git a/examples/extractors/src/path_two.rs b/examples/extractors/src/path_two.rs index 764ddfe..56663f9 100644 --- a/examples/extractors/src/path_two.rs +++ b/examples/extractors/src/path_two.rs @@ -1,30 +1,29 @@ // -use actix_web::{web, Result}; +use actix_web::{get, web, Result}; use serde::Deserialize; #[derive(Deserialize)] struct Info { - userid: u32, + user_id: u32, friend: String, } /// extract path info using serde +#[get("/users/{user_id}/{friend}")] // <- define path parameters async fn index(info: web::Path) -> Result { - Ok(format!("Welcome {}, userid {}!", info.friend, info.userid)) + Ok(format!( + "Welcome {}, user_id {}!", + info.friend, info.user_id + )) } -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { use actix_web::{App, HttpServer}; - HttpServer::new(|| { - App::new().route( - "/users/{userid}/{friend}", // <- define path parameters - web::get().to(index), - ) - }) - .bind("127.0.0.1:8088")? - .run() - .await + HttpServer::new(|| App::new().service(index)) + .bind("127.0.0.1:8080")? + .run() + .await } // diff --git a/examples/extractors/src/query.rs b/examples/extractors/src/query.rs index 23d4480..f540e80 100644 --- a/examples/extractors/src/query.rs +++ b/examples/extractors/src/query.rs @@ -1,5 +1,5 @@ // -use actix_web::web; +use actix_web::{get, web, App, HttpServer}; use serde::Deserialize; #[derive(Deserialize)] @@ -8,17 +8,16 @@ struct Info { } // this handler get called only if the request's query contains `username` field +#[get("/")] async fn index(info: web::Query) -> String { format!("Welcome {}!", info.username) } // -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { - use actix_web::{App, HttpServer}; - - HttpServer::new(|| App::new().route("/", web::get().to(index))) - .bind("127.0.0.1:8088")? + HttpServer::new(|| App::new().service(index)) + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/flexible-responders/Cargo.toml b/examples/flexible-responders/Cargo.toml index 8a29135..9c0e50b 100644 --- a/examples/flexible-responders/Cargo.toml +++ b/examples/flexible-responders/Cargo.toml @@ -4,6 +4,5 @@ version = "1.0.0" edition = "2018" [dependencies] -actix-web = "2.0" -actix-rt = "1.0" +actix-web = "3" serde = "1.0" diff --git a/examples/flexible-responders/src/main.rs b/examples/flexible-responders/src/main.rs index 0237fc3..7469794 100644 --- a/examples/flexible-responders/src/main.rs +++ b/examples/flexible-responders/src/main.rs @@ -15,14 +15,14 @@ async fn current_temperature() -> impl Responder { web::Json(Measurement { temperature: 42.3 }) } -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { HttpServer::new(|| { App::new() .service(web::resource("/").to(hello_world)) .service(web::resource("/temp").to(current_temperature)) }) - .bind("127.0.0.1:8088")? + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/getting-started/Cargo.toml b/examples/getting-started/Cargo.toml index 2f5db24..757d8bb 100644 --- a/examples/getting-started/Cargo.toml +++ b/examples/getting-started/Cargo.toml @@ -5,5 +5,4 @@ edition = "2018" workspace = "../" [dependencies] -actix-web = "2.0" -actix-rt = "1.0.0" +actix-web = "3" diff --git a/examples/getting-started/src/main.rs b/examples/getting-started/src/main.rs index 107788b..f5888fd 100644 --- a/examples/getting-started/src/main.rs +++ b/examples/getting-started/src/main.rs @@ -1,33 +1,31 @@ -// -use actix_web::{web, App, HttpResponse, HttpServer, Responder}; +// +use actix_web::{get, post, web, App, HttpResponse, HttpServer, Responder}; -async fn index() -> impl Responder { +#[get("/")] +async fn hello() -> impl Responder { HttpResponse::Ok().body("Hello world!") } -async fn index2() -> impl Responder { - HttpResponse::Ok().body("Hello world again!") +#[post("/echo")] +async fn echo(req_body: String) -> impl Responder { + HttpResponse::Ok().body(req_body) } -// -// -use actix_web::get; - -#[get("/hello")] -async fn index3() -> impl Responder { +async fn manual_hello() -> impl Responder { HttpResponse::Ok().body("Hey there!") } -// +// //
-#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { HttpServer::new(|| { App::new() - .route("/", web::get().to(index)) - .route("/again", web::get().to(index2)) + .service(hello) + .service(echo) + .route("/hey", web::get().to(manual_hello)) }) - .bind("127.0.0.1:8088")? + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/http2/Cargo.toml b/examples/http2/Cargo.toml index c9a0d58..40746c5 100644 --- a/examples/http2/Cargo.toml +++ b/examples/http2/Cargo.toml @@ -4,6 +4,5 @@ version = "1.0.0" edition = "2018" [dependencies] -actix-web = { version = "2.0", features = ["openssl"] } -actix-rt = "1.0" +actix-web = { version = "3", features = ["openssl"] } openssl = { version = "0.10", features = ["v110"] } diff --git a/examples/http2/src/main.rs b/examples/http2/src/main.rs index 3dc8599..21a4397 100644 --- a/examples/http2/src/main.rs +++ b/examples/http2/src/main.rs @@ -6,7 +6,7 @@ async fn index(_req: HttpRequest) -> impl Responder { "Hello." } -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { // load ssl keys // to create a self-signed temporary cert for testing: @@ -18,7 +18,7 @@ async fn main() -> std::io::Result<()> { builder.set_certificate_chain_file("cert.pem").unwrap(); HttpServer::new(|| App::new().route("/", web::get().to(index))) - .bind_openssl("127.0.0.1:8088", builder)? + .bind_openssl("127.0.0.1:8080", builder)? .run() .await } diff --git a/examples/main-example/Cargo.toml b/examples/main-example/Cargo.toml index 10e38ec..877dca1 100644 --- a/examples/main-example/Cargo.toml +++ b/examples/main-example/Cargo.toml @@ -4,5 +4,4 @@ version = "1.0.0" edition = "2018" [dependencies] -actix-web = "2.0" -actix-rt = "1.0" +actix-web = "3" diff --git a/examples/main-example/src/main.rs b/examples/main-example/src/main.rs index 004ec57..922aec2 100644 --- a/examples/main-example/src/main.rs +++ b/examples/main-example/src/main.rs @@ -6,14 +6,14 @@ async fn greet(req: HttpRequest) -> impl Responder { format!("Hello {}!", &name) } -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { HttpServer::new(|| { App::new() .route("/", web::get().to(greet)) .route("/{name}", web::get().to(greet)) }) - .bind("127.0.0.1:8088")? + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/middleware/Cargo.toml b/examples/middleware/Cargo.toml index dece5a1..feb08a0 100644 --- a/examples/middleware/Cargo.toml +++ b/examples/middleware/Cargo.toml @@ -4,9 +4,8 @@ version = "1.0.0" edition = "2018" [dependencies] -actix-web = "2.0" -actix-rt = "1.0" -actix-service = "1.0" -actix-session = "0.3" -futures = "0.3.1" -env_logger = "0.6" +actix-web = "3" +actix-service = "1" +actix-session = "0.4" +futures = "0.3" +env_logger = "0.7" diff --git a/examples/middleware/src/default_headers.rs b/examples/middleware/src/default_headers.rs index f71377d..71d438a 100644 --- a/examples/middleware/src/default_headers.rs +++ b/examples/middleware/src/default_headers.rs @@ -1,7 +1,7 @@ // use actix_web::{http, middleware, HttpResponse}; -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { use actix_web::{web, App, HttpServer}; @@ -17,7 +17,7 @@ async fn main() -> std::io::Result<()> { ), ) }) - .bind("127.0.0.1:8088")? + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/middleware/src/errorhandler.rs b/examples/middleware/src/errorhandler.rs index aa16b28..3a510e2 100644 --- a/examples/middleware/src/errorhandler.rs +++ b/examples/middleware/src/errorhandler.rs @@ -1,3 +1,5 @@ +#![allow(dead_code)] + // use actix_web::middleware::errhandlers::{ErrorHandlerResponse, ErrorHandlers}; use actix_web::{dev, http, HttpResponse, Result}; @@ -10,7 +12,7 @@ fn render_500(mut res: dev::ServiceResponse) -> Result std::io::Result<()> { use actix_web::{web, App, HttpServer}; @@ -26,7 +28,7 @@ async fn main() -> std::io::Result<()> { .route(web::head().to(|| HttpResponse::MethodNotAllowed())), ) }) - .bind("127.0.0.1:8088")? + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/middleware/src/logger.rs b/examples/middleware/src/logger.rs index 5ef6228..8f70d9c 100644 --- a/examples/middleware/src/logger.rs +++ b/examples/middleware/src/logger.rs @@ -2,7 +2,7 @@ use actix_web::middleware::Logger; use env_logger::Env; -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { use actix_web::{App, HttpServer}; @@ -13,7 +13,7 @@ async fn main() -> std::io::Result<()> { .wrap(Logger::default()) .wrap(Logger::new("%a %{User-Agent}i")) }) - .bind("127.0.0.1:8088")? + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/middleware/src/main.rs b/examples/middleware/src/main.rs index 50018cd..63b1a5e 100644 --- a/examples/middleware/src/main.rs +++ b/examples/middleware/src/main.rs @@ -74,7 +74,7 @@ where } // -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { use actix_web::{web, App, HttpServer}; @@ -86,7 +86,7 @@ async fn main() -> std::io::Result<()> { }), ) }) - .bind("127.0.0.1:8088")? + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/middleware/src/user_sessions.rs b/examples/middleware/src/user_sessions.rs index 261f5c2..0609b9e 100644 --- a/examples/middleware/src/user_sessions.rs +++ b/examples/middleware/src/user_sessions.rs @@ -1,3 +1,5 @@ +#![allow(dead_code)] + // use actix_session::{CookieSession, Session}; use actix_web::{web, App, Error, HttpResponse, HttpServer}; @@ -16,7 +18,7 @@ async fn index(session: Session) -> Result { ))) } -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { HttpServer::new(|| { App::new() @@ -26,7 +28,7 @@ async fn main() -> std::io::Result<()> { ) .service(web::resource("/").to(index)) }) - .bind("127.0.0.1:8088")? + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/middleware/src/wrap_fn.rs b/examples/middleware/src/wrap_fn.rs index a3f8f0a..c64ace6 100644 --- a/examples/middleware/src/wrap_fn.rs +++ b/examples/middleware/src/wrap_fn.rs @@ -1,9 +1,11 @@ +#![allow(dead_code, unused_variables)] + // use actix_service::Service; use actix_web::{web, App}; use futures::future::FutureExt; -#[actix_rt::main] +#[actix_web::main] async fn main() { let app = App::new() .wrap_fn(|req, srv| { diff --git a/examples/og_databases/Cargo.toml b/examples/og_databases/Cargo.toml deleted file mode 100644 index cdf2ee3..0000000 --- a/examples/og_databases/Cargo.toml +++ /dev/null @@ -1,7 +0,0 @@ -[package] -name = "og_databases" -version = "0.7.0" -edition = "2018" - -[dependencies] -actix-web = "0.7" diff --git a/examples/og_databases/src/main.rs b/examples/og_databases/src/main.rs deleted file mode 100644 index de4a966..0000000 --- a/examples/og_databases/src/main.rs +++ /dev/null @@ -1,98 +0,0 @@ -// -use actix::prelude::*; - -struct DbExecutor(SqliteConnection); - -impl Actor for DbExecutor { - type Context = SyncContext; -} -// - -// -struct CreateUser { - name: String, -} - -impl Message for CreateUser { - type Result = Result; -} -// - -// -impl Handler for DbExecutor { - type Result = Result; - - fn handle(&mut self, msg: CreateUser, _: &mut Self::Context) -> Self::Result { - use self::schema::users::dsl::*; - - // Create insertion model - let uuid = format!("{}", uuid::Uuid::new_v4()); - let new_user = models::NewUser { - id: &uuid, - name: &msg.name, - }; - - // normal diesel operations - diesel::insert_into(users) - .values(&new_user) - .execute(&self.0) - .expect("Error inserting person"); - - let mut items = users - .filter(id.eq(&uuid)) - .load::(&self.0) - .expect("Error loading person"); - - Ok(items.pop().unwrap()) - } -} -// - -//
-/// This is state where we will store *DbExecutor* address. -struct State { - db: Addr, -} - -fn main() { - let sys = actix::System::new("diesel-example"); - - // Start 3 parallel db executors - let addr = SyncArbiter::start(3, || { - DbExecutor(SqliteConnection::establish("test.db").unwrap()) - }); - - // Start http server - HttpServer::new(move || { - App::new::data(State { db: addr.clone() }) - .resource("/{name}", |r| r.method(Method::GET).a(index)) - }) - .bind("127.0.0.1:8080") - .unwrap() - .start() - .unwrap(); - - println!("Started http server: 127.0.0.1:8080"); - let _ = sys.run(); -} -//
- -// -/// Async handler -fn index(req: &HttpRequest) -> Box> { - let name = &req.match_info()["name"]; - - // Send message to `DbExecutor` actor - req.state() - .db - .send(CreateUser { - name: name.to_owned(), - }) - .from_err() - .and_then(|res| match res { - Ok(user) => Ok(HttpResponse::Ok().json(user)), - Err(_) => Ok(HttpResponse::InternalServerError().into()), - }) - .responder() -} -// diff --git a/examples/powerful-extractors/Cargo.toml b/examples/powerful-extractors/Cargo.toml index 1e84b9e..8c5b0a1 100644 --- a/examples/powerful-extractors/Cargo.toml +++ b/examples/powerful-extractors/Cargo.toml @@ -4,6 +4,5 @@ version = "1.0.0" edition = "2018" [dependencies] -actix-web = "2.0" -actix-rt = "1.0" +actix-web = "3" serde = "1.0" diff --git a/examples/powerful-extractors/src/main.rs b/examples/powerful-extractors/src/main.rs index 7005554..9fdfcdc 100644 --- a/examples/powerful-extractors/src/main.rs +++ b/examples/powerful-extractors/src/main.rs @@ -31,14 +31,14 @@ async fn index() -> HttpResponse { .body(include_str!("../static/form.html")) } -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { HttpServer::new(|| { App::new() .route("/", web::get().to(index)) .route("/event", web::post().to(capture_event)) }) - .bind("127.0.0.1:8088")? + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/powerful-extractors/static/form.html b/examples/powerful-extractors/static/form.html index a51229b..768f0af 100644 --- a/examples/powerful-extractors/static/form.html +++ b/examples/powerful-extractors/static/form.html @@ -18,7 +18,7 @@ } function submitJson() { - fetch('http://localhost:8088/event', { + fetch('http://localhost:8080/event', { method: 'POST', headers: { 'Accept': 'application/json', diff --git a/examples/request-handlers/Cargo.toml b/examples/request-handlers/Cargo.toml index 156950c..a0127fc 100644 --- a/examples/request-handlers/Cargo.toml +++ b/examples/request-handlers/Cargo.toml @@ -4,5 +4,4 @@ version = "1.0.0" edition = "2018" [dependencies] -actix-web = "2.0" -actix-rt = "1.0" +actix-web = "3" diff --git a/examples/request-handlers/src/handlers_arc.rs b/examples/request-handlers/src/handlers_arc.rs index 766dd15..f7dbde8 100644 --- a/examples/request-handlers/src/handlers_arc.rs +++ b/examples/request-handlers/src/handlers_arc.rs @@ -1,5 +1,5 @@ // -use actix_web::{web, Responder}; +use actix_web::{get, web, App, HttpServer, Responder}; use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Arc; @@ -8,20 +8,20 @@ struct AppState { count: Arc, } +#[get("/")] async fn show_count(data: web::Data) -> impl Responder { format!("count: {}", data.count.load(Ordering::Relaxed)) } +#[get("/add")] async fn add_one(data: web::Data) -> impl Responder { data.count.fetch_add(1, Ordering::Relaxed); format!("count: {}", data.count.load(Ordering::Relaxed)) } -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { - use actix_web::{App, HttpServer}; - let data = AppState { count: Arc::new(AtomicUsize::new(0)), }; @@ -29,10 +29,10 @@ async fn main() -> std::io::Result<()> { HttpServer::new(move || { App::new() .data(data.clone()) - .route("/", web::to(show_count)) - .route("/add", web::to(add_one)) + .service(show_count) + .service(add_one) }) - .bind("127.0.0.1:8088")? + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/request-handlers/src/main.rs b/examples/request-handlers/src/main.rs index 2d29c5f..d287c92 100644 --- a/examples/request-handlers/src/main.rs +++ b/examples/request-handlers/src/main.rs @@ -19,7 +19,7 @@ async fn add_one(data: web::Data) -> impl Responder { format!("count: {}", data.count.get()) } -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { use actix_web::{App, HttpServer}; @@ -33,7 +33,7 @@ async fn main() -> std::io::Result<()> { .route("/", web::to(show_count)) .route("/add", web::to(add_one)) }) - .bind("127.0.0.1:8088")? + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/request-routing/Cargo.toml b/examples/request-routing/Cargo.toml index df5d1d7..ba55eb9 100644 --- a/examples/request-routing/Cargo.toml +++ b/examples/request-routing/Cargo.toml @@ -4,5 +4,4 @@ version = "1.0.0" edition = "2018" [dependencies] -actix-web = "2.0" -actix-rt = "1.0" +actix-web = "3" diff --git a/examples/request-routing/src/main.rs b/examples/request-routing/src/main.rs index 4e9694a..ef78950 100644 --- a/examples/request-routing/src/main.rs +++ b/examples/request-routing/src/main.rs @@ -9,14 +9,14 @@ async fn hello(path: web::Path) -> impl Responder { format!("Hello {}!", &path) } -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { HttpServer::new(|| { App::new() .service(web::resource("/").to(index)) .service(web::resource("/{name}").to(hello)) }) - .bind("127.0.0.1:8088")? + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/requests/Cargo.toml b/examples/requests/Cargo.toml index 3e3a598..b609b89 100644 --- a/examples/requests/Cargo.toml +++ b/examples/requests/Cargo.toml @@ -6,8 +6,6 @@ edition = "2018" [dependencies] serde = "1.0" serde_json = "1.0" -actix-web = "2.0" -actix-rt = "1.0" +actix-web = "3" futures = "0.3.1" -bytes = "0.4" -actix-multipart = "0.2" +actix-multipart = "0.3" diff --git a/examples/requests/src/json_two.rs b/examples/requests/src/json_two.rs deleted file mode 100644 index 5c0bfa8..0000000 --- a/examples/requests/src/json_two.rs +++ /dev/null @@ -1,21 +0,0 @@ -// // -// use actix_web::{error::Error, HttpRequest, HttpResponse}; -// use futures::Future; -// use serde::{Deserialize, Serialize}; - -// #[derive(Debug, Serialize, Deserialize)] -// struct MyObj { -// name: String, -// number: i32, -// } - -// pub fn index(req: HttpRequest) -> Box> { -// req.json() -// .from_err() -// .and_then(|val: MyObj| { -// println!("model: {:?}", val); -// Ok(HttpResponse::Ok().json(val)) // <- send response -// }) -// .responder() -// } -// // diff --git a/examples/requests/src/main.rs b/examples/requests/src/main.rs index c6a0c1f..cc6c724 100644 --- a/examples/requests/src/main.rs +++ b/examples/requests/src/main.rs @@ -1,4 +1,3 @@ -pub mod json_two; pub mod manual; pub mod multipart; pub mod streaming; @@ -18,10 +17,10 @@ async fn index(info: web::Json) -> Result { Ok(format!("Welcome {}!", info.username)) } -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { HttpServer::new(|| App::new().route("/", web::post().to(index))) - .bind("127.0.0.1:8088")? + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/requests/src/manual.rs b/examples/requests/src/manual.rs index dade24c..e7640c0 100644 --- a/examples/requests/src/manual.rs +++ b/examples/requests/src/manual.rs @@ -1,6 +1,5 @@ // -use actix_web::{error, web, App, Error, HttpResponse}; -use bytes::BytesMut; +use actix_web::{error, post, web, App, Error, HttpResponse}; use futures::StreamExt; use serde::{Deserialize, Serialize}; use serde_json; @@ -13,9 +12,10 @@ struct MyObj { const MAX_SIZE: usize = 262_144; // max payload size is 256k +#[post("/")] async fn index_manual(mut payload: web::Payload) -> Result { // payload is a stream of Bytes objects - let mut body = BytesMut::new(); + let mut body = web::BytesMut::new(); while let Some(chunk) = payload.next().await { let chunk = chunk?; // limit max size of in-memory payload @@ -31,12 +31,12 @@ async fn index_manual(mut payload: web::Payload) -> Result } // -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { use actix_web::HttpServer; - HttpServer::new(|| App::new().route("/", web::post().to(index_manual))) - .bind("127.0.0.1:8088")? + HttpServer::new(|| App::new().service(index_manual)) + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/requests/src/streaming.rs b/examples/requests/src/streaming.rs index 414d34f..eabd453 100644 --- a/examples/requests/src/streaming.rs +++ b/examples/requests/src/streaming.rs @@ -1,7 +1,8 @@ // -use actix_web::{web, Error, HttpResponse}; +use actix_web::{get, web, Error, HttpResponse}; use futures::StreamExt; +#[get("/")] async fn index(mut body: web::Payload) -> Result { let mut bytes = web::BytesMut::new(); while let Some(item) = body.next().await { @@ -14,12 +15,12 @@ async fn index(mut body: web::Payload) -> Result { } // -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { use actix_web::{App, HttpServer}; - HttpServer::new(|| App::new().route("/", web::post().to(index))) - .bind("127.0.0.1:8088")? + HttpServer::new(|| App::new().service(index)) + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/requests/src/urlencoded.rs b/examples/requests/src/urlencoded.rs index 1486308..16881c4 100644 --- a/examples/requests/src/urlencoded.rs +++ b/examples/requests/src/urlencoded.rs @@ -1,5 +1,5 @@ // -use actix_web::{web, HttpResponse}; +use actix_web::{post, web, HttpResponse}; use serde::Deserialize; #[derive(Deserialize)] @@ -7,17 +7,18 @@ struct FormData { username: String, } +#[post("/")] async fn index(form: web::Form) -> HttpResponse { HttpResponse::Ok().body(format!("username: {}", form.username)) } // -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { use actix_web::{App, HttpServer}; - HttpServer::new(|| App::new().route("/", web::post().to(index))) - .bind("127.0.0.1:8088")? + HttpServer::new(|| App::new().service(index)) + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/responder-trait/Cargo.toml b/examples/responder-trait/Cargo.toml index 46bb4bf..5582a6a 100644 --- a/examples/responder-trait/Cargo.toml +++ b/examples/responder-trait/Cargo.toml @@ -4,8 +4,7 @@ version = "1.0.0" edition = "2018" [dependencies] -actix-web = "2.0" -actix-rt = "1.0" +actix-web = "3" futures = "0.3.1" serde = "1.0" serde_json = "1.0" diff --git a/examples/responder-trait/src/main.rs b/examples/responder-trait/src/main.rs index 972e6c2..b494ecc 100644 --- a/examples/responder-trait/src/main.rs +++ b/examples/responder-trait/src/main.rs @@ -28,12 +28,12 @@ async fn index() -> impl Responder { } // -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { use actix_web::{web, App, HttpServer}; HttpServer::new(|| App::new().route("/", web::get().to(index))) - .bind("127.0.0.1:8088")? + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/responses/Cargo.toml b/examples/responses/Cargo.toml index c5366f6..b6e3bbd 100644 --- a/examples/responses/Cargo.toml +++ b/examples/responses/Cargo.toml @@ -4,8 +4,7 @@ version = "1.0.0" edition = "2018" [dependencies] -actix-web = "2.0" -actix-rt = "1.0" +actix-web = "3" serde = "1.0" futures = "0.3.1" bytes = "0.5" diff --git a/examples/responses/src/auto.rs b/examples/responses/src/auto.rs index a1a1f15..99ff453 100644 --- a/examples/responses/src/auto.rs +++ b/examples/responses/src/auto.rs @@ -1,20 +1,19 @@ // -use actix_web::{http::ContentEncoding, middleware, HttpResponse}; +use actix_web::{get, http::ContentEncoding, middleware, App, HttpResponse, HttpServer}; +#[get("/")] async fn index() -> HttpResponse { HttpResponse::Ok().body("data") } -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { - use actix_web::{web, App, HttpServer}; - HttpServer::new(|| { App::new() .wrap(middleware::Compress::new(ContentEncoding::Br)) - .route("/", web::get().to(index)) + .service(index) }) - .bind("127.0.0.1:8088")? + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/responses/src/brotli.rs b/examples/responses/src/brotli.rs index 2f1cab1..b420762 100644 --- a/examples/responses/src/brotli.rs +++ b/examples/responses/src/brotli.rs @@ -1,22 +1,23 @@ // -use actix_web::{http::ContentEncoding, dev::BodyEncoding, HttpResponse}; +use actix_web::{ + dev::BodyEncoding, get, http::ContentEncoding, middleware, App, HttpResponse, HttpServer, +}; +#[get("/")] async fn index_br() -> HttpResponse { HttpResponse::Ok() .encoding(ContentEncoding::Br) .body("data") } -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { - use actix_web::{middleware, web, App, HttpServer}; - HttpServer::new(|| { App::new() .wrap(middleware::Compress::default()) - .route("/", web::get().to(index_br)) + .service(index_br) }) - .bind("127.0.0.1:8088")? + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/responses/src/brotli_two.rs b/examples/responses/src/brotli_two.rs index b7325f9..b827ec1 100644 --- a/examples/responses/src/brotli_two.rs +++ b/examples/responses/src/brotli_two.rs @@ -5,7 +5,7 @@ async fn index_br() -> HttpResponse { HttpResponse::Ok().body("data") } -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { use actix_web::{middleware, web, App, HttpServer}; @@ -14,7 +14,7 @@ async fn main() -> std::io::Result<()> { .wrap(middleware::Compress::new(ContentEncoding::Br)) .route("/", web::get().to(index_br)) }) - .bind("127.0.0.1:8088")? + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/responses/src/chunked.rs b/examples/responses/src/chunked.rs index ac630ba..13278ba 100644 --- a/examples/responses/src/chunked.rs +++ b/examples/responses/src/chunked.rs @@ -1,20 +1,19 @@ // -use actix_web::{HttpRequest, HttpResponse, Error}; +use actix_web::{get, App, Error, HttpRequest, HttpResponse, HttpServer}; use bytes::Bytes; use futures::future::ok; use futures::stream::once; -async fn index(req: HttpRequest) -> HttpResponse { - HttpResponse::Ok() - .streaming(once(ok::<_, Error>(Bytes::from_static(b"data")))) +#[get("/")] +async fn index(_req: HttpRequest) -> HttpResponse { + HttpResponse::Ok().streaming(once(ok::<_, Error>(Bytes::from_static(b"data")))) } // -pub fn main() { - use actix_web::{web, App, HttpServer}; - - HttpServer::new(|| App::new().route("/", web::get().to(index))) - .bind("127.0.0.1:8088") +#[actix_web::main] +async fn main() { + HttpServer::new(|| App::new().service(index)) + .bind("127.0.0.1:8080") .unwrap() .run(); } diff --git a/examples/responses/src/compress.rs b/examples/responses/src/compress.rs index d98799b..1fc9293 100644 --- a/examples/responses/src/compress.rs +++ b/examples/responses/src/compress.rs @@ -1,20 +1,19 @@ // -use actix_web::{middleware, HttpResponse}; +use actix_web::{get, middleware, App, HttpResponse, HttpServer}; +#[get("/")] async fn index_br() -> HttpResponse { HttpResponse::Ok().body("data") } -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { - use actix_web::{web, App, HttpServer}; - HttpServer::new(|| { App::new() .wrap(middleware::Compress::default()) - .route("/", web::get().to(index_br)) + .service(index_br) }) - .bind("127.0.0.1:8088")? + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/responses/src/identity.rs b/examples/responses/src/identity.rs index 0e8980a..f42f758 100644 --- a/examples/responses/src/identity.rs +++ b/examples/responses/src/identity.rs @@ -1,8 +1,9 @@ // use actix_web::{ - http::ContentEncoding, middleware, dev::BodyEncoding, HttpResponse, + dev::BodyEncoding, get, http::ContentEncoding, middleware, App, HttpResponse, HttpServer, }; +#[get("/")] async fn index() -> HttpResponse { HttpResponse::Ok() // v- disable compression @@ -10,16 +11,14 @@ async fn index() -> HttpResponse { .body("data") } -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { - use actix_web::{web, App, HttpServer}; - HttpServer::new(|| { App::new() .wrap(middleware::Compress::default()) - .route("/", web::get().to(index)) + .service(index) }) - .bind("127.0.0.1:8088")? + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/responses/src/identity_two.rs b/examples/responses/src/identity_two.rs index 86ff64f..11ecab3 100644 --- a/examples/responses/src/identity_two.rs +++ b/examples/responses/src/identity_two.rs @@ -1,14 +1,14 @@ // use actix_web::{ - http::ContentEncoding, middleware, dev::BodyEncoding, HttpResponse, + dev::BodyEncoding, get, http::ContentEncoding, middleware, App, HttpResponse, HttpServer, }; static HELLO_WORLD: &[u8] = &[ - 0x1f, 0x8b, 0x08, 0x00, 0xa2, 0x30, 0x10, 0x5c, 0x00, 0x03, 0xcb, 0x48, 0xcd, 0xc9, - 0xc9, 0x57, 0x28, 0xcf, 0x2f, 0xca, 0x49, 0xe1, 0x02, 0x00, 0x2d, 0x3b, 0x08, 0xaf, - 0x0c, 0x00, 0x00, 0x00, + 0x1f, 0x8b, 0x08, 0x00, 0xa2, 0x30, 0x10, 0x5c, 0x00, 0x03, 0xcb, 0x48, 0xcd, 0xc9, 0xc9, 0x57, + 0x28, 0xcf, 0x2f, 0xca, 0x49, 0xe1, 0x02, 0x00, 0x2d, 0x3b, 0x08, 0xaf, 0x0c, 0x00, 0x00, 0x00, ]; +#[get("/")] async fn index() -> HttpResponse { HttpResponse::Ok() .encoding(ContentEncoding::Identity) @@ -17,16 +17,14 @@ async fn index() -> HttpResponse { } // -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { - use actix_web::{web, App, HttpServer}; - HttpServer::new(|| { App::new() .wrap(middleware::Compress::default()) - .route("/", web::get().to(index)) + .service(index) }) - .bind("127.0.0.1:8088")? + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/responses/src/json_resp.rs b/examples/responses/src/json_resp.rs index 7df6796..b460a50 100644 --- a/examples/responses/src/json_resp.rs +++ b/examples/responses/src/json_resp.rs @@ -1,5 +1,5 @@ // -use actix_web::{web, HttpResponse, Result}; +use actix_web::{get, web, HttpResponse, Result}; use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize)] @@ -7,18 +7,19 @@ struct MyObj { name: String, } +#[get("/a/{name}")] async fn index(obj: web::Path) -> Result { Ok(HttpResponse::Ok().json(MyObj { name: obj.name.to_string(), })) } -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { use actix_web::{App, HttpServer}; - HttpServer::new(|| App::new().route(r"/a/{name}", web::get().to(index))) - .bind("127.0.0.1:8088")? + HttpServer::new(|| App::new().service(index)) + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/responses/src/main.rs b/examples/responses/src/main.rs index 9ee7a55..a43754e 100644 --- a/examples/responses/src/main.rs +++ b/examples/responses/src/main.rs @@ -17,12 +17,12 @@ async fn index() -> HttpResponse { } // -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { use actix_web::{web, App, HttpServer}; HttpServer::new(|| App::new().route("/", web::get().to(index))) - .bind("127.0.0.1:8088")? + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/server/Cargo.toml b/examples/server/Cargo.toml index c620da1..8e242df 100644 --- a/examples/server/Cargo.toml +++ b/examples/server/Cargo.toml @@ -5,8 +5,6 @@ workspace = "../" edition = "2018" [dependencies] -actix-rt = "1.0" -actix-web = { version = "2.0", features = ["openssl"] } -futures = "0.3.1" +actix-web = { version = "3", features = ["openssl"] } +futures = "0.3" openssl = "0.10" -actix-http = "1.0" diff --git a/examples/server/src/keep_alive.rs b/examples/server/src/keep_alive.rs index a59b743..8981a26 100644 --- a/examples/server/src/keep_alive.rs +++ b/examples/server/src/keep_alive.rs @@ -1,7 +1,7 @@ // use actix_web::{web, App, HttpResponse, HttpServer}; -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { let one = HttpServer::new(|| { App::new().route("/", web::get().to(|| HttpResponse::Ok())) @@ -18,6 +18,6 @@ async fn main() -> std::io::Result<()> { }) .keep_alive(None); // <- Disable keep-alive - one.bind("127.0.0.1:8088")?.run().await + one.bind("127.0.0.1:8080")?.run().await } // diff --git a/examples/server/src/keep_alive_tp.rs b/examples/server/src/keep_alive_tp.rs index 36ea2b3..003b730 100644 --- a/examples/server/src/keep_alive_tp.rs +++ b/examples/server/src/keep_alive_tp.rs @@ -8,6 +8,7 @@ async fn index(req: HttpRequest) -> HttpResponse { .finish() } // + // ConnectionType::Close // ConnectionType::KeepAlive // ConnectionType::Upgrade diff --git a/examples/server/src/main.rs b/examples/server/src/main.rs index aeb8543..24c35bc 100644 --- a/examples/server/src/main.rs +++ b/examples/server/src/main.rs @@ -7,12 +7,12 @@ pub mod workers; //
use actix_web::{web, App, HttpResponse, HttpServer}; -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { HttpServer::new(|| { App::new().route("/", web::get().to(|| HttpResponse::Ok())) }) - .bind("127.0.0.1:8088")? + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/server/src/signals.rs b/examples/server/src/signals.rs index ea1b1dd..8437b74 100644 --- a/examples/server/src/signals.rs +++ b/examples/server/src/signals.rs @@ -1,10 +1,9 @@ // -use actix_rt::System; -use actix_web::{web, App, HttpResponse, HttpServer}; +use actix_web::{web, App, HttpResponse, HttpServer, rt::System}; use std::sync::mpsc; use std::thread; -#[actix_rt::main] +#[actix_web::main] async fn main() { let (tx, rx) = mpsc::channel(); @@ -14,7 +13,7 @@ async fn main() { let srv = HttpServer::new(|| { App::new().route("/", web::get().to(|| HttpResponse::Ok())) }) - .bind("127.0.0.1:8088")? + .bind("127.0.0.1:8080")? .shutdown_timeout(60) // <- Set shutdown timeout to 60 seconds .run(); diff --git a/examples/server/src/ssl.rs b/examples/server/src/ssl.rs index a21946a..f30a4bc 100644 --- a/examples/server/src/ssl.rs +++ b/examples/server/src/ssl.rs @@ -1,28 +1,28 @@ +#![allow(dead_code)] + // -use actix_web::{web, App, HttpRequest, HttpServer, Responder}; +use actix_web::{get, App, HttpRequest, HttpServer, Responder}; use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod}; +#[get("/")] async fn index(_req: HttpRequest) -> impl Responder { "Welcome!" } -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { // load ssl keys // to create a self-signed temporary cert for testing: // `openssl req -x509 -newkey rsa:4096 -nodes -keyout key.pem -out cert.pem -days 365 -subj '/CN=localhost'` - let mut builder = - SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap(); + let mut builder = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap(); builder .set_private_key_file("key.pem", SslFiletype::PEM) .unwrap(); builder.set_certificate_chain_file("cert.pem").unwrap(); - HttpServer::new(|| App::new().route("/", web::get().to(index))) - .bind_openssl("127.0.0.1:8088", builder)? + HttpServer::new(|| App::new().service(index)) + .bind_openssl("127.0.0.1:8080", builder)? .run() .await } // -// -// sssl rust-tls diff --git a/examples/server/src/workers.rs b/examples/server/src/workers.rs index d2b4649..c8d2565 100644 --- a/examples/server/src/workers.rs +++ b/examples/server/src/workers.rs @@ -1,7 +1,7 @@ // use actix_web::{web, App, HttpResponse, HttpServer}; -#[actix_rt::main] +#[actix_web::main] async fn main() { HttpServer::new(|| { App::new().route("/", web::get().to(|| HttpResponse::Ok())) diff --git a/examples/static-files/Cargo.toml b/examples/static-files/Cargo.toml index e37f205..55f3ee4 100644 --- a/examples/static-files/Cargo.toml +++ b/examples/static-files/Cargo.toml @@ -4,7 +4,6 @@ version = "1.0.0" edition = "2018" [dependencies] -actix-web = "2.0" -actix-rt = "1.0" -actix-files = "0.2" -mime = "*" +actix-web = "3" +actix-files = "0.3" +mime = "0.3" diff --git a/examples/static-files/src/configuration.rs b/examples/static-files/src/configuration.rs index db663d0..a3312b1 100644 --- a/examples/static-files/src/configuration.rs +++ b/examples/static-files/src/configuration.rs @@ -1,8 +1,9 @@ // use actix_files as fs; use actix_web::http::header::{ContentDisposition, DispositionType}; -use actix_web::{web, App, Error, HttpRequest, HttpServer}; +use actix_web::{get, App, Error, HttpRequest, HttpServer}; +#[get("/{filename:.*}")] async fn index(req: HttpRequest) -> Result { let path: std::path::PathBuf = req.match_info().query("filename").parse().unwrap(); let file = fs::NamedFile::open(path)?; @@ -14,10 +15,10 @@ async fn index(req: HttpRequest) -> Result { })) } -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { - HttpServer::new(|| App::new().route("/{filename:.*}", web::get().to(index))) - .bind("127.0.0.1:8088")? + HttpServer::new(|| App::new().service(index)) + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/static-files/src/configuration_two.rs b/examples/static-files/src/configuration_two.rs index 11b01b3..dc88ce6 100644 --- a/examples/static-files/src/configuration_two.rs +++ b/examples/static-files/src/configuration_two.rs @@ -2,7 +2,7 @@ use actix_files as fs; use actix_web::{App, HttpServer}; -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { HttpServer::new(|| { App::new().service( @@ -11,7 +11,7 @@ async fn main() -> std::io::Result<()> { .use_last_modified(true), ) }) - .bind("127.0.0.1:8088")? + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/static-files/src/directory.rs b/examples/static-files/src/directory.rs index db3131b..870e7aa 100644 --- a/examples/static-files/src/directory.rs +++ b/examples/static-files/src/directory.rs @@ -2,12 +2,12 @@ use actix_files as fs; use actix_web::{App, HttpServer}; -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { HttpServer::new(|| { App::new().service(fs::Files::new("/static", ".").show_files_listing()) }) - .bind("127.0.0.1:8088")? + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/static-files/src/main.rs b/examples/static-files/src/main.rs index ae903b0..66bf1f7 100644 --- a/examples/static-files/src/main.rs +++ b/examples/static-files/src/main.rs @@ -12,12 +12,12 @@ async fn index(req: HttpRequest) -> Result { Ok(NamedFile::open(path)?) } -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { use actix_web::{web, App, HttpServer}; HttpServer::new(|| App::new().route("/{filename:.*}", web::get().to(index))) - .bind("127.0.0.1:8088")? + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/testing/Cargo.toml b/examples/testing/Cargo.toml index bc3a0d6..7ebbe3d 100644 --- a/examples/testing/Cargo.toml +++ b/examples/testing/Cargo.toml @@ -4,10 +4,12 @@ version = "1.0.0" edition = "2018" [dependencies] -actix-web = "2.0" -actix-rt = "1.0" +actix-web = "3" futures = "0.3" futures-util = "0.3" bytes = "0.5" serde = "1.0" serde_json = "1.0" + +[dev-dependencies] +actix-rt = "1" diff --git a/examples/testing/src/stream_response.rs b/examples/testing/src/stream_response.rs index 7f608af..e81b8ed 100644 --- a/examples/testing/src/stream_response.rs +++ b/examples/testing/src/stream_response.rs @@ -35,7 +35,6 @@ pub fn main() { #[cfg(test)] mod tests { use super::*; - use actix_rt; use futures_util::stream::StreamExt; use futures_util::stream::TryStreamExt; diff --git a/examples/url-dispatch/Cargo.toml b/examples/url-dispatch/Cargo.toml index dbd9149..3640797 100644 --- a/examples/url-dispatch/Cargo.toml +++ b/examples/url-dispatch/Cargo.toml @@ -5,9 +5,8 @@ edition = "2018" workspace = "../" [dependencies] -actix = "0.9" -actix-rt = "1.0" -actix-web = "2.0" +actix = "0.10" +actix-web = "3" futures = "0.3.1" openssl = "0.10" serde = "1.0" diff --git a/examples/url-dispatch/src/cfg.rs b/examples/url-dispatch/src/cfg.rs index 21381bd..e768f0c 100644 --- a/examples/url-dispatch/src/cfg.rs +++ b/examples/url-dispatch/src/cfg.rs @@ -1,7 +1,7 @@ use actix_web::{guard, web, App, HttpResponse}; #[rustfmt::skip] -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { use actix_web::HttpServer; @@ -17,7 +17,7 @@ App::new().service( ) // }) - .bind("127.0.0.1:8088")? + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/url-dispatch/src/dhandler.rs b/examples/url-dispatch/src/dhandler.rs index dad5c07..7765b0a 100644 --- a/examples/url-dispatch/src/dhandler.rs +++ b/examples/url-dispatch/src/dhandler.rs @@ -1,11 +1,12 @@ use actix_web::{guard, web, App, HttpRequest, HttpResponse, HttpServer, Responder}; +#[allow(dead_code)] async fn index(_req: HttpRequest) -> impl Responder { "Welcome!" } // -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { HttpServer::new(|| { App::new() @@ -16,7 +17,7 @@ async fn main() -> std::io::Result<()> { .to(|| HttpResponse::MethodNotAllowed()), ) }) - .bind("127.0.0.1:8088")? + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/url-dispatch/src/guard.rs b/examples/url-dispatch/src/guard.rs index 48eddbf..405bb55 100644 --- a/examples/url-dispatch/src/guard.rs +++ b/examples/url-dispatch/src/guard.rs @@ -9,7 +9,7 @@ impl Guard for ContentTypeHeader { } } -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { use actix_web::{web, App, HttpServer}; @@ -21,7 +21,7 @@ async fn main() -> std::io::Result<()> { .to(|| HttpResponse::Ok()), ) }) - .bind("127.0.0.1:8088")? + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/url-dispatch/src/guard2.rs b/examples/url-dispatch/src/guard2.rs index bef0407..2b5b790 100644 --- a/examples/url-dispatch/src/guard2.rs +++ b/examples/url-dispatch/src/guard2.rs @@ -1,7 +1,7 @@ // use actix_web::{guard, web, App, HttpResponse, HttpServer}; -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { HttpServer::new(|| { App::new().route( @@ -11,7 +11,7 @@ async fn main() -> std::io::Result<()> { .to(|| HttpResponse::MethodNotAllowed()), ) }) - .bind("127.0.0.1:8088")? + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/url-dispatch/src/main.rs b/examples/url-dispatch/src/main.rs index 85b61e7..0f95fea 100644 --- a/examples/url-dispatch/src/main.rs +++ b/examples/url-dispatch/src/main.rs @@ -20,14 +20,14 @@ async fn index() -> HttpResponse { HttpResponse::Ok().body("Hello") } -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { HttpServer::new(|| { App::new() .route("/", web::get().to(index)) .route("/user", web::post().to(index)) }) - .bind("127.0.0.1:8088")? + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/url-dispatch/src/minfo.rs b/examples/url-dispatch/src/minfo.rs index 16dc037..bd4b503 100644 --- a/examples/url-dispatch/src/minfo.rs +++ b/examples/url-dispatch/src/minfo.rs @@ -1,6 +1,7 @@ // -use actix_web::{HttpRequest, HttpResponse, Result}; +use actix_web::{get, App, HttpRequest, HttpServer, Result}; +#[get("/a/{v1}/{v2}/")] async fn index(req: HttpRequest) -> Result { let v1: u8 = req.match_info().get("v1").unwrap().parse().unwrap(); let v2: u8 = req.match_info().query("v2").parse().unwrap(); @@ -8,17 +9,11 @@ async fn index(req: HttpRequest) -> Result { Ok(format!("Values {} {} {} {}", v1, v2, v3, v4)) } -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { - use actix_web::{web, App, HttpServer}; - - HttpServer::new(|| { - App::new() - .route("/a/{v1}/{v2}/", web::get().to(index)) - .route("", web::get().to(|| HttpResponse::Ok())) - }) - .bind("127.0.0.1:8088")? - .run() - .await + HttpServer::new(|| App::new().service(index)) + .bind("127.0.0.1:8080")? + .run() + .await } // diff --git a/examples/url-dispatch/src/norm.rs b/examples/url-dispatch/src/norm.rs index 12c27aa..cc0e906 100644 --- a/examples/url-dispatch/src/norm.rs +++ b/examples/url-dispatch/src/norm.rs @@ -1,3 +1,5 @@ +#![allow(dead_code)] + // use actix_web::{middleware, HttpResponse}; @@ -5,16 +7,16 @@ async fn index() -> HttpResponse { HttpResponse::Ok().body("Hello") } -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { use actix_web::{web, App, HttpServer}; HttpServer::new(|| { App::new() - .wrap(middleware::NormalizePath) + .wrap(middleware::NormalizePath::default()) .route("/resource/", web::to(index)) }) - .bind("127.0.0.1:8088")? + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/url-dispatch/src/norm2.rs b/examples/url-dispatch/src/norm2.rs index c4cc7d5..de95e8f 100644 --- a/examples/url-dispatch/src/norm2.rs +++ b/examples/url-dispatch/src/norm2.rs @@ -1,21 +1,22 @@ use actix_web::HttpResponse; +#[get("/resource/")] fn index() -> HttpResponse { HttpResponse::Ok().body("Hello") } // -use actix_web::{http::Method, middleware, web, App, HttpServer}; +use actix_web::{get, http::Method, middleware, web, App, HttpServer}; -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { HttpServer::new(|| { App::new() - .wrap(middleware::NormalizePath) - .route("/resource/", web::get().to(index)) + .wrap(middleware::NormalizePath::default()) + .service(index) .default_service(web::route().method(Method::GET)) }) - .bind("127.0.0.1:8088")? + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/url-dispatch/src/path.rs b/examples/url-dispatch/src/path.rs index 81a6359..e5b280f 100644 --- a/examples/url-dispatch/src/path.rs +++ b/examples/url-dispatch/src/path.rs @@ -1,22 +1,17 @@ // -use actix_web::{web, Result}; +use actix_web::{get, web, App, HttpServer, Result}; +#[get("/{username}/{id}/index.html")] // <- define path parameters async fn index(info: web::Path<(String, u32)>) -> Result { + let info = info.into_inner(); Ok(format!("Welcome {}! id: {}", info.0, info.1)) } -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { - use actix_web::{App, HttpServer}; - - HttpServer::new(|| { - App::new().route( - "/{username}/{id}/index.html", // <- define path parameters - web::get().to(index), - ) - }) - .bind("127.0.0.1:8088")? - .run() - .await + HttpServer::new(|| App::new().service(index)) + .bind("127.0.0.1:8080")? + .run() + .await } // diff --git a/examples/url-dispatch/src/path2.rs b/examples/url-dispatch/src/path2.rs index 7cd60a4..1dcc4ff 100644 --- a/examples/url-dispatch/src/path2.rs +++ b/examples/url-dispatch/src/path2.rs @@ -1,5 +1,5 @@ // -use actix_web::{web, Result}; +use actix_web::{get, web, App, HttpServer, Result}; use serde::Deserialize; #[derive(Deserialize)] @@ -8,22 +8,16 @@ struct Info { } // extract path info using serde +#[get("/{username}/index.html")] // <- define path parameters async fn index(info: web::Path) -> Result { Ok(format!("Welcome {}!", info.username)) } -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { - use actix_web::{App, HttpServer}; - - HttpServer::new(|| { - App::new().route( - "/{username}/index.html", // <- define path parameters - web::get().to(index), - ) - }) - .bind("127.0.0.1:8088")? - .run() - .await + HttpServer::new(|| App::new().service(index)) + .bind("127.0.0.1:8080")? + .run() + .await } // diff --git a/examples/url-dispatch/src/pbuf.rs b/examples/url-dispatch/src/pbuf.rs index 5b037bd..d6fdd9c 100644 --- a/examples/url-dispatch/src/pbuf.rs +++ b/examples/url-dispatch/src/pbuf.rs @@ -1,18 +1,17 @@ // -use actix_web::{HttpRequest, Result}; +use actix_web::{get, App, HttpRequest, HttpServer, Result}; use std::path::PathBuf; +#[get("/a/{tail:.*}")] async fn index(req: HttpRequest) -> Result { let path: PathBuf = req.match_info().query("tail").parse().unwrap(); Ok(format!("Path {:?}", path)) } -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { - use actix_web::{web, App, HttpServer}; - - HttpServer::new(|| App::new().route(r"/a/{tail:.*}", web::get().to(index))) - .bind("127.0.0.1:8088")? + HttpServer::new(|| App::new().service(index)) + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/url-dispatch/src/scope.rs b/examples/url-dispatch/src/scope.rs index ba4677e..0c60b58 100644 --- a/examples/url-dispatch/src/scope.rs +++ b/examples/url-dispatch/src/scope.rs @@ -1,24 +1,26 @@ -use actix_web::{web, App, HttpResponse, HttpServer}; +use actix_web::{get, web, App, HttpResponse, HttpServer}; // +#[get("/show")] async fn show_users() -> HttpResponse { HttpResponse::Ok().body("Show users") } +#[get("/show/{id}")] async fn user_detail(path: web::Path<(u32,)>) -> HttpResponse { - HttpResponse::Ok().body(format!("User detail: {}", path.0)) + HttpResponse::Ok().body(format!("User detail: {}", path.into_inner().0)) } -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { HttpServer::new(|| { App::new().service( web::scope("/users") - .route("/show", web::get().to(show_users)) - .route("/show/{id}", web::get().to(user_detail)), + .service(show_users) + .service(user_detail), ) }) - .bind("127.0.0.1:8088")? + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/url-dispatch/src/url_ext.rs b/examples/url-dispatch/src/url_ext.rs index 0d9ec9a..7787b8e 100644 --- a/examples/url-dispatch/src/url_ext.rs +++ b/examples/url-dispatch/src/url_ext.rs @@ -1,6 +1,7 @@ // -use actix_web::{HttpRequest, Responder}; +use actix_web::{get, App, HttpRequest, HttpServer, Responder}; +#[get("/")] async fn index(req: HttpRequest) -> impl Responder { let url = req.url_for("youtube", &["oHg5SJYRHA0"]).unwrap(); assert_eq!(url.as_str(), "https://youtube.com/watch/oHg5SJYRHA0"); @@ -8,17 +9,14 @@ async fn index(req: HttpRequest) -> impl Responder { url.into_string() } -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { - use actix_web::{web, App, HttpServer}; - HttpServer::new(|| { App::new() - .route("/", web::get().to(index)) + .service(index) .external_resource("youtube", "https://youtube.com/watch/{video_id}") - .route("/", actix_web::web::get().to(index)) }) - .bind("127.0.0.1:8088")? + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/url-dispatch/src/urls.rs b/examples/url-dispatch/src/urls.rs index 66ec903..e2f8857 100644 --- a/examples/url-dispatch/src/urls.rs +++ b/examples/url-dispatch/src/urls.rs @@ -1,6 +1,7 @@ // -use actix_web::{guard, http::header, HttpRequest, HttpResponse, Result}; +use actix_web::{get, guard, http::header, HttpRequest, HttpResponse, Result}; +#[get("/test/")] async fn index(req: HttpRequest) -> Result { let url = req.url_for("foo", &["1", "2", "3"])?; // <- generate url for "foo" resource @@ -9,7 +10,7 @@ async fn index(req: HttpRequest) -> Result { .finish()) } -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { use actix_web::{web, App, HttpServer}; @@ -21,9 +22,9 @@ async fn main() -> std::io::Result<()> { .guard(guard::Get()) .to(|| HttpResponse::Ok()), ) - .route("/test/", web::get().to(index)) + .service(index) }) - .bind("127.0.0.1:8088")? + .bind("127.0.0.1:8080")? .run() .await } diff --git a/examples/websockets/Cargo.toml b/examples/websockets/Cargo.toml index 1f58706..d24358b 100644 --- a/examples/websockets/Cargo.toml +++ b/examples/websockets/Cargo.toml @@ -4,7 +4,6 @@ version = "1.0.0" edition = "2018" [dependencies] -actix = "0.9" -actix-rt = "1.0" -actix-web = "2.0" -actix-web-actors = "2.0" +actix = "0.10" +actix-web = "3" +actix-web-actors = "3" diff --git a/examples/websockets/src/main.rs b/examples/websockets/src/main.rs index 8198d34..09381df 100644 --- a/examples/websockets/src/main.rs +++ b/examples/websockets/src/main.rs @@ -3,7 +3,7 @@ use actix::{Actor, StreamHandler}; use actix_web::{web, App, Error, HttpRequest, HttpResponse, HttpServer}; use actix_web_actors::ws; -/// Define http actor +/// Define HTTP actor struct MyWs; impl Actor for MyWs { @@ -32,10 +32,10 @@ async fn index(req: HttpRequest, stream: web::Payload) -> Result std::io::Result<()> { HttpServer::new(|| App::new().route("/ws/", web::get().to(index))) - .bind("127.0.0.1:8088")? + .bind("127.0.0.1:8080")? .run() .await } diff --git a/i18n/en.toml b/i18n/en.toml index 9fddc1f..4e200d2 100644 --- a/i18n/en.toml +++ b/i18n/en.toml @@ -1,8 +1,11 @@ [home] other = "Home" + [docs] other = "Documentation" + [community] other = "Community" + [code] other = "Code" diff --git a/layouts/docs/baseof.html b/layouts/docs/baseof.html index b6131b1..a6203da 100644 --- a/layouts/docs/baseof.html +++ b/layouts/docs/baseof.html @@ -56,7 +56,7 @@
Protocols
@@ -53,14 +53,14 @@ async fn greet(req: HttpRequest) -> impl Responder { format!("Hello {}!", &name) } -#[actix_rt::main] +#[actix_web::main] async fn main() -> std::io::Result<()> { HttpServer::new(|| { App::new() .route("/", web::get().to(greet)) .route("/{name}", web::get().to(greet)) }) - .bind("127.0.0.1:8000")? + .bind("127.0.0.1:8080")? .run() .await }` "rust" "" }} @@ -135,7 +135,8 @@ async fn register(form: web::Form) -> impl Responder { URLs and invoke individual handlers. For extra flexibility, scopes can be used.

- {{ highlight `async fn index(_req: HttpRequest) -> impl Responder { + {{ highlight `#[get("/")] +async fn index(_req: HttpRequest) -> impl Responder { "Hello from the index page!" } @@ -144,8 +145,8 @@ async fn hello(path: web::Path) -> impl Responder { } let app = App::new() - .route("/", web::get().to(index)) - .route("/{name}", web::get().to(hello)); + .service(index) + .route("/{name}", web::get().to(hello)); ` "rust" "" }}
diff --git a/layouts/shortcodes/actix-web-version.html b/layouts/shortcodes/actix-web-version.html deleted file mode 100644 index 5a2a580..0000000 --- a/layouts/shortcodes/actix-web-version.html +++ /dev/null @@ -1 +0,0 @@ -0.6 diff --git a/static/css/actix.css b/static/css/actix.css index 57af572..8e0e2cf 100644 --- a/static/css/actix.css +++ b/static/css/actix.css @@ -1,23 +1,24 @@ @import url('https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600|Roboto+Mono'); body { - font-family: 'Source Sans Pro', sans-serif; + font-family: Source Sans Pro, sans-serif; } a { - color: #156060; + color: #306ebf; } a:hover { - color: #003B3B; + color: #071540; } -table, td { - border: 1px solid black; +table, +td { + border: 1px solid black; } td { - padding: 4px; + padding: 4px; } img { @@ -40,11 +41,13 @@ img { font-size: 2.2rem; } -.actix-content h1:first-child { +.actix-content h1:first-child, +.actix-content h2:first-child { margin-top: 0; } -.actix-content h2, .actix-content h3 { +.actix-content h2, +.actix-content h3 { margin-top: 2rem; margin-bottom: 1rem; } @@ -77,7 +80,7 @@ img { } .github-edit .fa:before { - font-family: "FontAwesome"; + font-family: FontAwesome; display: inline-block; font-style: normal; font-weight: normal; @@ -90,23 +93,22 @@ img { padding-bottom: 1rem; } - /* * * ===== Navbar ===== * */ - .navbar-nav { - display: flex; - } - .navbar-nav img { - width: 100%; - } - .navbar-nav .nav-item { - margin-left: 1rem; - margin-right: 1rem; - } +.navbar-nav { + display: flex; +} +.navbar-nav img { + width: 100%; +} +.navbar-nav .nav-item { + margin-left: 1rem; + margin-right: 1rem; +} .navbar-nav .nav-link { padding-top: 0; @@ -122,7 +124,11 @@ img { height: auto; } -@keyframes spin-logo { 100% { transform: rotate(360deg); } } +@keyframes spin-logo { + 100% { + transform: rotate(360deg); + } +} .navbar-brand img { animation: spin-logo 30s linear infinite; @@ -131,14 +137,14 @@ img { } .navbar-toggle { - padding: .25rem .35rem; + padding: 0.25rem 0.35rem; font-size: 1.25rem; line-height: 1; height: 2.6rem; width: 2.8rem; background: 0 0; border: 1px solid transparent; - border-radius: .25rem; + border-radius: 0.25rem; } .navbar-light .navbar-toggle { @@ -158,7 +164,7 @@ img { width: 1.5em; height: 1.5em; vertical-align: middle; - content: ""; + content: ''; background: no-repeat center center; -webkit-background-size: 100% 100%; background-size: 100% 100%; @@ -205,7 +211,7 @@ img { margin: -1rem 0 2rem 0; display: none; } - + .leftnav { margin: 0 -1rem; padding: 0 1rem; @@ -217,19 +223,19 @@ img { .leftnav li a { color: #888; - width:100%; - height:100%; + width: 100%; + height: 100%; word-wrap: break-word; } .leftnav li.active { - margin: -0.5rem -1rem -.5rem -1rem; + margin: -0.5rem -1rem -0.5rem -1rem; padding: 0.5rem 1rem 0.5rem 1rem; - background: #dceaea; + background-color: #dfe6ee; } .leftnav li.active a { - color: #156060; + color: #163e8c; } .leftnav h5 { @@ -264,10 +270,11 @@ img { * */ -.actix-pageheader, .jumbotron { +.actix-pageheader, +.jumbotron { background-image: url(/img/jumbotron.jpg); background-size: cover; - background-color: #156060; + background-color: #071540; color: #fff; } @@ -304,14 +311,14 @@ img { } .actix-pageheader .lead { - color: #DADADA; + color: #dadada; font-size: 1.5rem; margin-bottom: 0; } .actix-pageheader #blog-title { - width:100%; - height:100%; + width: 100%; + height: 100%; word-wrap: break-word; } @@ -341,7 +348,7 @@ img { .actix-features .fa { margin-right: 0.4rem; - color: #156060; + color: #163e8c; } .actix-features p { @@ -357,7 +364,7 @@ img { margin-top: 2rem; margin-bottom: 2rem; padding: 2rem 1rem 0 1rem; - background: #dceaea; + background-color: #dfe6ee; } .actix-showcase ul { @@ -367,7 +374,7 @@ img { line-height: 2; } -.actix-showcase input[type="radio"] { +.actix-showcase input[type='radio'] { display: none; } @@ -375,41 +382,40 @@ img { display: none; } -.actix-showcase input[type="radio"]:checked + div.feature { +.actix-showcase input[type='radio']:checked + div.feature { display: block; } .actix-showcase label { display: block; font-weight: bold; - color: #156060; + color: #163e8c; cursor: pointer; } .actix-showcase label:hover { - color: #003B3B; + color: #003b3b; } .actix-feature-selectors { - padding-bottom: 2rem; - } - - .actix-feature-selector { - text-align: center; - padding: 0.5rem 1rem; - font-weight: bold; - } - - .actix-feature-selector.active { - background: white; - } - - .actix-feature-selector.active a { - color: #333!important; - text-decoration: none; - } + padding-bottom: 2rem; +} + +.actix-feature-selector { + text-align: center; + padding: 0.5rem 1rem; + font-weight: bold; +} + +.actix-feature-selector.active { + background-color: white; +} + +.actix-feature-selector.active a { + color: #333 !important; + text-decoration: none; +} - /* * * ===== Footer ===== @@ -454,10 +460,11 @@ p.uplink { */ code { - color: #006a70; + color: #163e8c; } -pre, code { +pre, +code { font-family: 'Roboto Mono', monospace; } @@ -466,7 +473,7 @@ pre { overflow-x: auto; margin: 2rem 0rem; padding: 1rem; - background: #f7f7f7; + background-color: #f7f7f7; font-size: 90%; line-height: 1.4rem; } @@ -477,73 +484,72 @@ h2:hover a:after, h3:hover a:after, h4:hover a:after, h5:hover a:after { - content: '\2002\00a7\2002'; + content: '\2002\00a7\2002'; } h2:hover a, h3:hover a, h4:hover a, h5:hover a { - text-decoration: none; + text-decoration: none; } -@media (min-width:520px) { +@media (min-width: 520px) { .jumbotron { padding: 4rem; } } - /* * * ===== Utilities ===== * */ - .d-flex { - display: flex; - } +.d-flex { + display: flex; +} - .justify-content-between { - justify-content: space-between; - } +.justify-content-between { + justify-content: space-between; +} - /* +/* * * ===== Media queries ===== * */ - @media screen and (max-width: 767px) { - .doctoggle { - display: block; - } +@media screen and (max-width: 767px) { + .doctoggle { + display: block; + } } - @media (min-width: 768px) { +@media (min-width: 768px) { .leftnav { display: block; } - .bootstrap-vertical-nav .navbar .navbar-collapse { - padding: 0; - max-height: none; - } - .bootstrap-vertical-nav .navbar ul { - float: none; - } - .bootstrap-vertical-nav .navbar ul:not { - display: block; - } - .bootstrap-vertical-nav .navbar li { - float: none; - display: block; - } + .bootstrap-vertical-nav .navbar .navbar-collapse { + padding: 0; + max-height: none; + } + .bootstrap-vertical-nav .navbar ul { + float: none; + } + .bootstrap-vertical-nav .navbar ul:not { + display: block; + } + .bootstrap-vertical-nav .navbar li { + float: none; + display: block; + } - .bootstrap-vertical-nav .navbar-nav .nav-item+.nav-item { - margin-left: 0; - } + .bootstrap-vertical-nav .navbar-nav .nav-item + .nav-item { + margin-left: 0; + } } - @media screen and (min-width: 480px) { +@media screen and (min-width: 480px) { .hidden-lg-up { display: none !important; } @@ -552,13 +558,13 @@ h5:hover a { } } - @media screen and (max-width: 479px) { +@media screen and (max-width: 479px) { .hd-lg-down { display: none !important; } .navbar-toggleable-md > .container { - padding-right: 0; - padding-left: 0; + padding-right: 0; + padding-left: 0; } .navbar-brand { @@ -605,7 +611,8 @@ h5:hover a { } @media (min-width: 480px) and (max-width: 576px) { - header .nav, #heads-up { + header .nav, + #heads-up { width: 100%; } .hd-lg-down { @@ -613,7 +620,8 @@ h5:hover a { } } @media (min-width: 576px) and (max-width: 768px) { - header .nav, #heads-up { + header .nav, + #heads-up { width: 88%; } .hd-lg-down { @@ -621,7 +629,8 @@ h5:hover a { } } @media (min-width: 768px) and (max-width: 992px) { - header .nav, #heads-up { + header .nav, + #heads-up { width: 90%; } .hd-lg-down { @@ -630,13 +639,15 @@ h5:hover a { } @media (min-width: 992px) { - header .nav, #heads-up { + header .nav, + #heads-up { width: 75%; } .hd-lg-down { width: 60%; } - .actix-pageheader .container, .container{ + .actix-pageheader .container, + .container { width: 72%; } .actix-footer-gray { @@ -644,23 +655,22 @@ h5:hover a { } } - #act-cn-tabs { padding: 2rem 2rem 1rem 2rem; margin: 2rem auto; - background:#dceaea; + background-color: #dfe6ee; } -.act-menu li{ - text-align:center; - line-height:44px; - font-size:15px; - overflow:hidden; +.act-menu li { + text-align: center; + line-height: 44px; + font-size: 15px; + overflow: hidden; } -.act-menu li.off{ +.act-menu li.off { padding: 0 1.5rem; - background:#FFFFFF; - color:#589c9e; - font-weight:bold; + background-color: #ffffff; + color: #589c9e; + font-weight: bold; } @media (min-width: 768px) { @@ -670,7 +680,7 @@ h5:hover a { padding: 2rem 1rem 1rem 2rem; } #act-cn-tabs #content { - width: 77%; + width: 77%; } } diff --git a/static/favicon.ico b/static/favicon.ico index 1eac423..a9fdae2 100644 Binary files a/static/favicon.ico and b/static/favicon.ico differ diff --git a/static/img/jumbotron.jpg b/static/img/jumbotron.jpg index 264fd5b..efc868a 100644 Binary files a/static/img/jumbotron.jpg and b/static/img/jumbotron.jpg differ