mirror of
https://github.com/actix/actix-website
synced 2024-11-23 16:31:08 +01:00
v3 (#188)
This commit is contained in:
parent
a0ce9f28e2
commit
4d8d53cea5
1
.gitignore
vendored
1
.gitignore
vendored
@ -4,3 +4,4 @@ _site
|
||||
Cargo.lock
|
||||
build/
|
||||
target/
|
||||
.DS_Store
|
||||
|
13
.prettierrc.json
Normal file
13
.prettierrc.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"singleQuote": true,
|
||||
"tabWidth": 2,
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.md"],
|
||||
"options": {
|
||||
"proseWrap": "always",
|
||||
"printWidth": 100
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
21
README.md
21
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.
|
||||
|
||||
<!-- LINKS -->
|
||||
|
||||
[Hugo]: https://gohugo.io
|
||||
[Homebrew]: https://brew.sh
|
||||
[Mermaid CLI]: https://github.com/mermaidjs/mermaid.cli
|
||||
|
16
config.toml
16
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"
|
||||
|
@ -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.
|
||||
---
|
||||
|
@ -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
|
||||
|
@ -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.
|
@ -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/).
|
||||
|
@ -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
|
||||
|
@ -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<T>`][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<T>`][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`.
|
||||
|
||||
<!-- LINKS -->
|
||||
|
||||
[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
|
||||
|
@ -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
|
@ -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<T>` 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
|
||||
|
@ -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<T: Responder, E: Into<Error>> Responder for Result<T, E>
|
||||
```
|
||||
|
||||
`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<NamedFile> {
|
||||
}
|
||||
```
|
||||
|
||||
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
|
||||
|
@ -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/
|
||||
|
@ -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].
|
||||
<!-- LINKS -->
|
||||
|
||||
[rustguide]: https://doc.rust-lang.org/book/ch01-01-installation.html
|
||||
[actix-web-codegen]: https://docs.rs/actix-web-codegen/
|
||||
[autoload]: ../autoreload/
|
||||
|
@ -68,12 +68,12 @@ the stream trait `Stream<Item=Bytes, Error=Error>`, 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
|
||||
|
@ -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].
|
||||
|
||||
<!-- TODO: use rustls example -->
|
||||
> 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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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/
|
||||
|
@ -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.
|
||||
|
||||
<!-- TODO -->
|
||||
<!-- which is built upon the fantastic [Tokio][tokio] asynchronous I/O system -->
|
||||
|
||||
<!-- LINKS -->
|
||||
|
||||
[tokio]: https://tokio.rs
|
||||
|
@ -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"]
|
||||
|
@ -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"
|
||||
|
@ -1,18 +1,23 @@
|
||||
#![allow(dead_code)]
|
||||
|
||||
// <setup>
|
||||
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
|
||||
}
|
||||
|
@ -1,24 +1,27 @@
|
||||
#![allow(dead_code)]
|
||||
|
||||
use actix_web::{web, App, HttpResponse, HttpServer};
|
||||
|
||||
// <combine>
|
||||
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
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
#![allow(dead_code)]
|
||||
|
||||
// <config>
|
||||
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
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ pub mod state;
|
||||
pub mod vh;
|
||||
|
||||
// <multi>
|
||||
#[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
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ async fn index(data: web::Data<AppStateWithCounter>) -> String {
|
||||
// </setup_mutable>
|
||||
|
||||
// <make_app_mutable>
|
||||
#[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
|
||||
}
|
||||
|
@ -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]
|
||||
// <scope>
|
||||
#[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);
|
||||
}
|
||||
// </scope>
|
||||
|
@ -1,12 +1,12 @@
|
||||
// <setup>
|
||||
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<AppState>) -> String {
|
||||
let app_name = &data.app_name; // <- get app_name
|
||||
|
||||
@ -15,16 +15,16 @@ async fn index(data: web::Data<AppState>) -> String {
|
||||
// </setup>
|
||||
|
||||
// <start_app>
|
||||
#[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
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
use actix_web::{guard, web, App, HttpResponse, HttpServer};
|
||||
|
||||
// <vh>
|
||||
#[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
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -1,10 +1,11 @@
|
||||
// <stream>
|
||||
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
|
||||
}
|
||||
|
@ -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"
|
@ -1,22 +0,0 @@
|
||||
// <autoreload>
|
||||
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
|
||||
}
|
||||
// </autoreload>
|
7
examples/databases/Cargo.toml
Normal file
7
examples/databases/Cargo.toml
Normal file
@ -0,0 +1,7 @@
|
||||
[package]
|
||||
name = "databases"
|
||||
version = "1.0.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
actix-web = "3"
|
63
examples/databases/src/main.rs
Normal file
63
examples/databases/src/main.rs
Normal file
@ -0,0 +1,63 @@
|
||||
// <handler>
|
||||
fn insert_new_user(db: &SqliteConnection, user: CreateUser) -> Result<User, Error> {
|
||||
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::<models::User>(&self.0)
|
||||
.expect("Error loading person");
|
||||
|
||||
Ok(items.pop().unwrap())
|
||||
}
|
||||
// </handler>
|
||||
|
||||
// <main>
|
||||
type DbPool = r2d2::Pool<ConnectionManager<SqliteConnection>>;
|
||||
|
||||
#[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
|
||||
}
|
||||
// </main>
|
||||
|
||||
// <index>
|
||||
async fn index(req: web::Data<DbPool>, 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))
|
||||
}
|
||||
// </index>
|
@ -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"
|
||||
|
@ -18,14 +18,14 @@ async fn register(form: web::Form<Register>) -> 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
|
||||
}
|
||||
|
@ -4,5 +4,4 @@ version = "1.0.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
actix-web = "1.0"
|
||||
futures = "0.1"
|
||||
actix-web = "3"
|
||||
|
@ -3,7 +3,7 @@ use actix_web::{Either, Error, HttpResponse};
|
||||
|
||||
type RegisterResult = Either<HttpResponse, Result<&'static str, Error>>;
|
||||
|
||||
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 {
|
||||
}
|
||||
// </either>
|
||||
|
||||
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 {
|
||||
|
@ -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"
|
||||
|
@ -1,12 +1,12 @@
|
||||
use actix_web::{web, App};
|
||||
// <helpers>
|
||||
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> {
|
||||
}
|
||||
// </helpers>
|
||||
|
||||
#[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
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
// <logging>
|
||||
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
|
||||
}
|
||||
// </logging>
|
||||
|
@ -6,10 +6,10 @@ pub mod recommend_two;
|
||||
|
||||
// <response-error>
|
||||
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> {
|
||||
}
|
||||
// </response-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")?
|
||||
.bind("127.0.0.1:8080")?
|
||||
.run()
|
||||
.await
|
||||
}
|
||||
|
@ -1,22 +1,24 @@
|
||||
use actix_web::{web, App};
|
||||
// <override>
|
||||
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)
|
||||
}
|
||||
// </override>
|
||||
|
||||
#[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
|
||||
}
|
||||
|
@ -1,17 +1,19 @@
|
||||
// <recommend-one>
|
||||
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 {
|
||||
}
|
||||
}
|
||||
// </recommend-one>
|
||||
|
||||
#[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
|
||||
}
|
||||
|
@ -1,17 +1,19 @@
|
||||
// <recommend-two>
|
||||
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!")
|
||||
}
|
||||
// </recommend-two>
|
||||
|
||||
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
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -1,5 +1,5 @@
|
||||
// <form>
|
||||
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<FormData>) -> Result<String> {
|
||||
Ok(format!("Welcome {}!", form.username))
|
||||
}
|
||||
// </form>
|
||||
|
||||
#[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
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
// <json-one>
|
||||
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<Info>) -> Result<String> {
|
||||
Ok(format!("Welcome {}!", info.username))
|
||||
}
|
||||
// </json-one>
|
||||
|
||||
#[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
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
#![allow(dead_code)]
|
||||
|
||||
// <json-two>
|
||||
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<Info>) -> 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::<Info>::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
|
||||
}
|
||||
|
@ -18,17 +18,18 @@ struct MyInfo {
|
||||
}
|
||||
|
||||
// <option-one>
|
||||
async fn index(
|
||||
path: web::Path<(String, String)>,
|
||||
json: web::Json<MyInfo>,
|
||||
) -> impl Responder {
|
||||
async fn index(path: web::Path<(String, String)>, json: web::Json<MyInfo>) -> impl Responder {
|
||||
let path = path.into_inner();
|
||||
format!("{} {} {} {}", path.0, path.1, json.id, json.username)
|
||||
}
|
||||
// </option-one>
|
||||
|
||||
// <option-two>
|
||||
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::<MyInfo>::extract(&req)
|
||||
.await
|
||||
@ -38,14 +39,14 @@ async fn extract(req: HttpRequest) -> impl Responder {
|
||||
}
|
||||
// </option-two>
|
||||
|
||||
#[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
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
// <multi>
|
||||
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<Info>),
|
||||
web::Path((user_id, friend)): web::Path<(u32, String)>,
|
||||
query: web::Query<Info>,
|
||||
) -> 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
|
||||
}
|
||||
// </multi>
|
||||
|
@ -1,25 +1,21 @@
|
||||
// <path-one>
|
||||
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<String> {
|
||||
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<String> {
|
||||
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
|
||||
}
|
||||
// </path-one>
|
||||
|
@ -1,26 +1,21 @@
|
||||
use actix_web::{web, HttpRequest, Result};
|
||||
use actix_web::{get, HttpRequest, Result};
|
||||
|
||||
// <path-three>
|
||||
#[get("/users/{userid}/{friend}")] // <- define path parameters
|
||||
async fn index(req: HttpRequest) -> Result<String> {
|
||||
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
|
||||
}
|
||||
// </path-three>
|
||||
|
@ -1,30 +1,29 @@
|
||||
// <path-two>
|
||||
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<Info>) -> Result<String> {
|
||||
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
|
||||
}
|
||||
// </path-two>
|
||||
|
@ -1,5 +1,5 @@
|
||||
// <query>
|
||||
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<Info>) -> String {
|
||||
format!("Welcome {}!", info.username)
|
||||
}
|
||||
// </query>
|
||||
|
||||
#[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
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -5,5 +5,4 @@ edition = "2018"
|
||||
workspace = "../"
|
||||
|
||||
[dependencies]
|
||||
actix-web = "2.0"
|
||||
actix-rt = "1.0.0"
|
||||
actix-web = "3"
|
||||
|
@ -1,33 +1,31 @@
|
||||
// <setup>
|
||||
use actix_web::{web, App, HttpResponse, HttpServer, Responder};
|
||||
// <handlers>
|
||||
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)
|
||||
}
|
||||
// </setup>
|
||||
|
||||
// <macro-attributes>
|
||||
use actix_web::get;
|
||||
|
||||
#[get("/hello")]
|
||||
async fn index3() -> impl Responder {
|
||||
async fn manual_hello() -> impl Responder {
|
||||
HttpResponse::Ok().body("Hey there!")
|
||||
}
|
||||
// </macro-attributes>
|
||||
// </handlers>
|
||||
|
||||
// <main>
|
||||
#[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
|
||||
}
|
||||
|
@ -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"] }
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -4,5 +4,4 @@ version = "1.0.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
actix-web = "2.0"
|
||||
actix-rt = "1.0"
|
||||
actix-web = "3"
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -1,7 +1,7 @@
|
||||
// <default-headers>
|
||||
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
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
#![allow(dead_code)]
|
||||
|
||||
// <error-handler>
|
||||
use actix_web::middleware::errhandlers::{ErrorHandlerResponse, ErrorHandlers};
|
||||
use actix_web::{dev, http, HttpResponse, Result};
|
||||
@ -10,7 +12,7 @@ fn render_500<B>(mut res: dev::ServiceResponse<B>) -> Result<ErrorHandlerRespons
|
||||
Ok(ErrorHandlerResponse::Response(res))
|
||||
}
|
||||
|
||||
#[actix_rt::main]
|
||||
#[actix_web::main]
|
||||
async fn main() -> 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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ where
|
||||
}
|
||||
// </simple>
|
||||
|
||||
#[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
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
#![allow(dead_code)]
|
||||
|
||||
// <user-session>
|
||||
use actix_session::{CookieSession, Session};
|
||||
use actix_web::{web, App, Error, HttpResponse, HttpServer};
|
||||
@ -16,7 +18,7 @@ async fn index(session: Session) -> Result<HttpResponse, Error> {
|
||||
)))
|
||||
}
|
||||
|
||||
#[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
|
||||
}
|
||||
|
@ -1,9 +1,11 @@
|
||||
#![allow(dead_code, unused_variables)]
|
||||
|
||||
// <wrap-fn>
|
||||
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| {
|
||||
|
@ -1,7 +0,0 @@
|
||||
[package]
|
||||
name = "og_databases"
|
||||
version = "0.7.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
actix-web = "0.7"
|
@ -1,98 +0,0 @@
|
||||
// <actor>
|
||||
use actix::prelude::*;
|
||||
|
||||
struct DbExecutor(SqliteConnection);
|
||||
|
||||
impl Actor for DbExecutor {
|
||||
type Context = SyncContext<Self>;
|
||||
}
|
||||
// </actor>
|
||||
|
||||
// <message>
|
||||
struct CreateUser {
|
||||
name: String,
|
||||
}
|
||||
|
||||
impl Message for CreateUser {
|
||||
type Result = Result<User, Error>;
|
||||
}
|
||||
// </message>
|
||||
|
||||
// <handler>
|
||||
impl Handler<CreateUser> for DbExecutor {
|
||||
type Result = Result<User, Error>;
|
||||
|
||||
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::<models::User>(&self.0)
|
||||
.expect("Error loading person");
|
||||
|
||||
Ok(items.pop().unwrap())
|
||||
}
|
||||
}
|
||||
// </handler>
|
||||
|
||||
// <main>
|
||||
/// This is state where we will store *DbExecutor* address.
|
||||
struct State {
|
||||
db: Addr<DbExecutor>,
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
// </main>
|
||||
|
||||
// <index>
|
||||
/// Async handler
|
||||
fn index(req: &HttpRequest<State>) -> Box<Future<Item = HttpResponse, Error = Error>> {
|
||||
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()
|
||||
}
|
||||
// </index>
|
@ -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"
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -18,7 +18,7 @@
|
||||
}
|
||||
|
||||
function submitJson() {
|
||||
fetch('http://localhost:8088/event', {
|
||||
fetch('http://localhost:8080/event', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
|
@ -4,5 +4,4 @@ version = "1.0.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
actix-web = "2.0"
|
||||
actix-rt = "1.0"
|
||||
actix-web = "3"
|
||||
|
@ -1,5 +1,5 @@
|
||||
// <arc>
|
||||
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<AtomicUsize>,
|
||||
}
|
||||
|
||||
#[get("/")]
|
||||
async fn show_count(data: web::Data<AppState>) -> impl Responder {
|
||||
format!("count: {}", data.count.load(Ordering::Relaxed))
|
||||
}
|
||||
|
||||
#[get("/add")]
|
||||
async fn add_one(data: web::Data<AppState>) -> 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
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ async fn add_one(data: web::Data<AppState>) -> 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
|
||||
}
|
||||
|
@ -4,5 +4,4 @@ version = "1.0.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
actix-web = "2.0"
|
||||
actix-rt = "1.0"
|
||||
actix-web = "3"
|
||||
|
@ -9,14 +9,14 @@ async fn hello(path: web::Path<String>) -> 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
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -1,21 +0,0 @@
|
||||
// // <json-two>
|
||||
// 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<Future<Item = HttpResponse, Error = Error>> {
|
||||
// req.json()
|
||||
// .from_err()
|
||||
// .and_then(|val: MyObj| {
|
||||
// println!("model: {:?}", val);
|
||||
// Ok(HttpResponse::Ok().json(val)) // <- send response
|
||||
// })
|
||||
// .responder()
|
||||
// }
|
||||
// // </json-two>
|
@ -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<Info>) -> Result<String> {
|
||||
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
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
// <json-manual>
|
||||
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<HttpResponse, Error> {
|
||||
// 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<HttpResponse, Error>
|
||||
}
|
||||
// </json-manual>
|
||||
|
||||
#[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
|
||||
}
|
||||
|
@ -1,7 +1,8 @@
|
||||
// <streaming>
|
||||
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<HttpResponse, Error> {
|
||||
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<HttpResponse, Error> {
|
||||
}
|
||||
// </streaming>
|
||||
|
||||
#[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
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
// <urlencoded>
|
||||
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<FormData>) -> HttpResponse {
|
||||
HttpResponse::Ok().body(format!("username: {}", form.username))
|
||||
}
|
||||
// </urlencoded>
|
||||
|
||||
#[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
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -28,12 +28,12 @@ async fn index() -> impl Responder {
|
||||
}
|
||||
// </responder-trait>
|
||||
|
||||
#[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
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -1,20 +1,19 @@
|
||||
// <auto>
|
||||
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
|
||||
}
|
||||
|
@ -1,22 +1,23 @@
|
||||
// <brotli>
|
||||
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
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user