mirror of
https://github.com/actix/actix-website
synced 2024-11-24 00:41:07 +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
|
Cargo.lock
|
||||||
build/
|
build/
|
||||||
target/
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
19
README.md
19
README.md
@ -4,11 +4,12 @@ The work in progress website for the actix project based on tokio's website.
|
|||||||
|
|
||||||
## Getting Started
|
## Getting Started
|
||||||
|
|
||||||
Building the website depends on [Hugo](http://gohugo.io). So, first make sure
|
Building the website depends on [Hugo]. So, first make sure
|
||||||
that you have it installed. If on OS X and using Homebrew, run the following:
|
that you have it installed. If on macOS and using [Homebrew], run the following:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
brew update && brew install hugo
|
brew update
|
||||||
|
brew install hugo
|
||||||
```
|
```
|
||||||
|
|
||||||
Then, get the website running locally:
|
Then, get the website running locally:
|
||||||
@ -16,16 +17,18 @@ Then, get the website running locally:
|
|||||||
```sh
|
```sh
|
||||||
git clone https://github.com/actix/actix-website.git
|
git clone https://github.com/actix/actix-website.git
|
||||||
cd actix-website
|
cd actix-website
|
||||||
|
|
||||||
hugo server
|
hugo server
|
||||||
```
|
```
|
||||||
|
|
||||||
Then visit [http://localhost:1313](http://localhost:1313).
|
Then visit http://localhost:1313.
|
||||||
|
|
||||||
## Updating diagrams
|
## 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:
|
For instance to edit `connection_overview` diagram:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
cd static/css/img/diagrams
|
cd static/css/img/diagrams
|
||||||
vi connection_overview.mmd
|
vi connection_overview.mmd
|
||||||
@ -37,3 +40,9 @@ mmdc -i connection_overview.mmd -o connection_overview.svg
|
|||||||
|
|
||||||
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.
|
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"
|
baseURL = "https://actix.rs"
|
||||||
|
|
||||||
[languages.en]
|
[languages.en]
|
||||||
languageCode = "en-US"
|
languageCode = "en-US"
|
||||||
languageName = "English"
|
languageName = "English"
|
||||||
weight = 1
|
weight = 1
|
||||||
|
|
||||||
[params]
|
[params]
|
||||||
actixVersion = "0.9"
|
actixVersion = "0.10"
|
||||||
actixWebVersion = "2.0"
|
actixWebVersion = "3"
|
||||||
actixRtVersion = "1.0"
|
actixRtVersion = "1.1"
|
||||||
actixWebMinRustVersion = "1.39"
|
actixWebMinRustVersion = "1.42"
|
||||||
actixMinRustVersion = "1.39"
|
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
|
# Browse the Code
|
||||||
|
|
||||||
All of actix is open source and can be found on our github organization: [actix
|
The Actix ecosystem is fully open source on our GitHub organization [@actix](https://github.com/actix).
|
||||||
on github](https://github.com/actix)
|
|
||||||
|
|
||||||
Here are the most important projects and the link to their github repositories
|
Here are the most important projects and the link to their github repositories
|
||||||
and related resources:
|
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), ([API docs](https://docs.rs/actix-web))
|
||||||
* [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))
|
- [actix-extras crates](https://github.com/actix/actix-extras)
|
||||||
* [example code](https://github.com/actix/examples)
|
- [actix-net crates](https://github.com/actix/actix-net)
|
||||||
* [this website](https://github.com/actix/actix-website)
|
- [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
|
# Join us
|
||||||
|
|
||||||
Want to talk to others about questions? The [actix gitter
|
Want to talk to others about questions? The Actix [Gitter channel](https://gitter.im/actix/actix) or
|
||||||
channel](https://gitter.im/actix/actix) or
|
[reddit community](https://www.reddit.com/r/actix/) are your best starting point.
|
||||||
[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
|
If you think you found a bug it's best to go to the [github](https://github.com/actix) directly.
|
||||||
[github](https://github.com/actix) directly. There are two repositories
|
There are two repositories that you might want to report against.
|
||||||
that you might want to report against. [actix](https://github.com/actix/actix)
|
[actix](https://github.com/actix/actix) for issues with the actor framework or
|
||||||
for issues with the actor framework or [actix-web](https://github.com/actix/actix-web)
|
[actix-web](https://github.com/actix/actix-web) for the web framework.
|
||||||
for the high level web framework.
|
|
||||||
|
|
||||||
We're a welcoming community so don't be afraid to engage. Interactions
|
We're a welcoming community so don't be afraid to engage. Interactions are
|
||||||
are [governed by our code of conduct](coc/).
|
[governed by our code of conduct](coc/).
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
title: Documentation
|
title: Documentation
|
||||||
description: Guiding you through building apps with actix
|
description: Guiding you through building web apps with Actix
|
||||||
menu:
|
menu:
|
||||||
docs_intro:
|
docs_intro:
|
||||||
name: Welcome
|
name: Welcome
|
||||||
@ -9,19 +9,16 @@ weight: 10
|
|||||||
|
|
||||||
# Welcome to Actix
|
# Welcome to Actix
|
||||||
|
|
||||||
Actix is your door to developing web services with Rust and this documentation
|
Actix Web lets you quickly and confidently develop web services in Rust and this guide get you going
|
||||||
is going to guide you.
|
in no time.
|
||||||
|
|
||||||
This documentation currently covers mostly the `actix-web` part which is the high level
|
The documentation on this website focusses primarily on the Actix Web framework. For information
|
||||||
web framework previously built on top of the `actix` actor framework and the [Tokio][tokio]
|
about the actor framework called Actix, check out the [Actix book][actix-book] (or the lower level
|
||||||
async IO system. This is the part that is from an API stability point of view the most stable.
|
[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
|
[getting-started]: ./getting-started
|
||||||
guide][gettingstarted]. If you already know your ways around and you need
|
[actix-web-docs]: https://docs.rs/actix-web
|
||||||
specific information you might want to read the [actix-web API docs][actixwebdocs]
|
[actix-docs]: https://docs.rs/actix
|
||||||
(or the lower level [actix API docs][actixdocs]).
|
[actix-book]: https://actix.rs/book/actix
|
||||||
|
|
||||||
[gettingstarted]: ./getting-started
|
|
||||||
[actixwebdocs]: https://docs.rs/actix-web
|
|
||||||
[actixdocs]: https://docs.rs/actix
|
|
||||||
[tokio]: https://tokio.rs
|
|
||||||
|
@ -6,35 +6,33 @@ weight: 140
|
|||||||
|
|
||||||
# Writing an Application
|
# Writing an Application
|
||||||
|
|
||||||
`actix-web` provides various primitives to build web servers and applications with Rust.
|
`actix-web` provides various primitives to build web servers and applications with Rust. It provides
|
||||||
It provides routing, middlewares, pre-processing of requests, post-processing of
|
routing, middleware, pre-processing of requests, post-processing of responses, etc.
|
||||||
responses, etc.
|
|
||||||
|
|
||||||
All `actix-web` servers are built around the [`App`][app] instance. It is used for
|
All `actix-web` servers are built around the [`App`][app] instance. It is used for registering
|
||||||
registering routes for resources and middlewares. It also stores application
|
routes for resources and middleware. It also stores application state shared across all handlers
|
||||||
state shared across all handlers within the same scope.
|
within the same scope.
|
||||||
|
|
||||||
An application's [`scope`][scope] acts as a namespace for all routes, i.e. all routes for a
|
An application's [`scope`][scope] acts as a namespace for all routes, i.e. all routes for a specific
|
||||||
specific application scope have the same url path prefix. The application prefix always
|
application scope have the same url path prefix. The application prefix always contains a leading
|
||||||
contains a leading "/" slash. If a supplied prefix does not contain leading slash,
|
"/" slash. If a supplied prefix does not contain leading slash, it is automatically inserted. The
|
||||||
it is automatically inserted. The prefix should consist of value path segments.
|
prefix should consist of value path segments.
|
||||||
|
|
||||||
> For an application with scope `/app`,
|
> For an application with scope `/app`, any request with the paths `/app`, `/app/`, or `/app/test`
|
||||||
> any request with the paths `/app`, `/app/`, or `/app/test` would match;
|
> would match; however, the path `/application` would not match.
|
||||||
> however, the path `/application` would not match.
|
|
||||||
|
|
||||||
{{< include-example example="application" file="app.rs" section="setup" >}}
|
{{< include-example example="application" file="app.rs" section="setup" >}}
|
||||||
|
|
||||||
In this example, an application with the `/app` prefix and a `index.html` resource
|
In this example, an application with the `/app` prefix and a `index.html` resource are created. This
|
||||||
are created. This resource is available through the `/app/index.html` url.
|
resource is available through the `/app/index.html` url.
|
||||||
|
|
||||||
> For more information, check the [URL Dispatch][usingappprefix] section.
|
> For more information, check the [URL Dispatch][usingappprefix] section.
|
||||||
|
|
||||||
## State
|
## State
|
||||||
|
|
||||||
Application state is shared with all routes and resources within the same scope. State
|
Application state is shared with all routes and resources within the same scope. State can be
|
||||||
can be accessed with the [`web::Data<T>`][data] extractor where `T` is the type of the state. State is
|
accessed with the [`web::Data<T>`][data] extractor where `T` is the type of the state. State is also
|
||||||
also available for middlewares.
|
accessible for middleware.
|
||||||
|
|
||||||
Let's write a simple application and store the application name in the state:
|
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
|
## Shared Mutable State
|
||||||
|
|
||||||
`HttpServer` accepts an application factory rather than an application instance.
|
`HttpServer` accepts an application factory rather than an application instance. An `HttpServer`
|
||||||
An `HttpServer` constructs an application instance for each thread. Therefore, application data must be
|
constructs an application instance for each thread. Therefore, application data must be constructed
|
||||||
constructed multiple times. If you want to share data between different threads, a shareable
|
multiple times. If you want to share data between different threads, a shareable object should be
|
||||||
object should be used, e.g. `Send` + `Sync`.
|
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" >}}
|
{{< 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
|
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
|
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
|
configuration. This can be used to help mount a set of routes at a different location than the
|
||||||
than the original author intended while still maintaining the same resource names.
|
original author intended while still maintaining the same resource names.
|
||||||
|
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
{{< include-example example="application" file="scope.rs" section="scope" >}}
|
{{< include-example example="application" file="scope.rs" section="scope" >}}
|
||||||
|
|
||||||
In the above example, the `show_users` route will have an effective route pattern of
|
In the above example, the `show_users` route will have an effective route pattern of `/users/show`
|
||||||
`/users/show` instead of `/show` because the application's scope argument will be prepended
|
instead of `/show` because the application's scope argument will be prepended to the pattern. The
|
||||||
to the pattern. The route will then only match if the URL path is `/users/show`,
|
route will then only match if the URL path is `/users/show`, and when the
|
||||||
and when the [`HttpRequest.url_for()`][urlfor] function is called with the route name `show_users`,
|
[`HttpRequest.url_for()`][urlfor] function is called with the route name `show_users`, it will
|
||||||
it will generate a URL with that same path.
|
generate a URL with that same path.
|
||||||
|
|
||||||
## Application guards and virtual hosting
|
## Application guards and virtual hosting
|
||||||
|
|
||||||
You can think of a guard as a simple function that accepts a *request* object reference
|
You can think of a guard as a simple function that accepts a _request_ object reference and returns
|
||||||
and returns *true* or *false*. Formally, a guard is any object that implements the
|
_true_ or _false_. Formally, a guard is any object that implements the [`Guard`][guardtrait] trait.
|
||||||
[`Guard`][guardtrait] trait. Actix-web provides several guards. You can check the
|
Actix-web provides several guards. You can check the [functions section][guardfuncs] of the API
|
||||||
[functions section][guardfuncs] of the API docs.
|
docs.
|
||||||
|
|
||||||
One of the provided guards is [`Header`][guardheader]. It can be used as a
|
One of the provided guards is [`Header`][guardheader]. It can be used as a filter based on request
|
||||||
filter based on request header information.
|
header information.
|
||||||
|
|
||||||
{{< include-example example="application" file="vh.rs" section="vh" >}}
|
{{< include-example example="application" file="vh.rs" section="vh" >}}
|
||||||
|
|
||||||
# Configure
|
# Configure
|
||||||
|
|
||||||
For simplicity and reusability both [`App`][appconfig] and [`web::Scope`][webscopeconfig] provide the `configure` method.
|
For simplicity and reusability both [`App`][appconfig] and [`web::Scope`][webscopeconfig] provide
|
||||||
This function is useful for moving parts of the configuration to a different module or even
|
the `configure` method. This function is useful for moving parts of the configuration to a different
|
||||||
library. For example, some of the resource's configuration could be moved to a different
|
module or even library. For example, some of the resource's configuration could be moved to a
|
||||||
module.
|
different module.
|
||||||
|
|
||||||
{{< include-example example="application" file="config.rs" section="config" >}}
|
{{< include-example example="application" file="config.rs" section="config" >}}
|
||||||
|
|
||||||
@ -108,19 +108,22 @@ The result of the above example would be:
|
|||||||
/app -> "app"
|
/app -> "app"
|
||||||
/api/test -> "test"
|
/api/test -> "test"
|
||||||
```
|
```
|
||||||
|
|
||||||
Each [`ServiceConfig`][serviceconfig] can have its own `data`, `routes`, and `services`.
|
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
|
[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
|
[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
|
[guardtrait]: https://docs.rs/actix-web/3/actix_web/guard/trait.Guard.html
|
||||||
[guardfuncs]: https://docs.rs/actix-web/2/actix_web/guard/index.html#functions
|
[guardfuncs]: https://docs.rs/actix-web/3/actix_web/guard/index.html#functions
|
||||||
[guardheader]: https://docs.rs/actix-web/2/actix_web/guard/fn.Header.html
|
[guardheader]: https://docs.rs/actix-web/3/actix_web/guard/fn.Header.html
|
||||||
[data]: https://docs.rs/actix-web/2/actix_web/web/struct.Data.html
|
[data]: https://docs.rs/actix-web/3/actix_web/web/struct.Data.html
|
||||||
[app]: https://docs.rs/actix-web/2/actix_web/struct.App.html
|
[app]: https://docs.rs/actix-web/3/actix_web/struct.App.html
|
||||||
[appconfig]: https://docs.rs/actix-web/2/actix_web/struct.App.html#method.configure
|
[appconfig]: https://docs.rs/actix-web/3/actix_web/struct.App.html#method.configure
|
||||||
[appdata]: https://docs.rs/actix-web/2/actix_web/struct.App.html#method.app_data
|
[appdata]: https://docs.rs/actix-web/3/actix_web/struct.App.html#method.app_data
|
||||||
[scope]: https://docs.rs/actix-web/2/actix_web/struct.Scope.html
|
[scope]: https://docs.rs/actix-web/3/actix_web/struct.Scope.html
|
||||||
[webscopeconfig]: https://docs.rs/actix-web/2/actix_web/struct.Scope.html#method.configure
|
[webscopeconfig]: https://docs.rs/actix-web/3/actix_web/struct.Scope.html#method.configure
|
||||||
[webscope]: https://docs.rs/actix-web/2/actix_web/web/fn.scope.html
|
[webscope]: https://docs.rs/actix-web/3/actix_web/web/fn.scope.html
|
||||||
[urlfor]: https://docs.rs/actix-web/2/actix_web/struct.HttpRequest.html#method.url_for
|
[urlfor]: https://docs.rs/actix-web/3/actix_web/struct.HttpRequest.html#method.url_for
|
||||||
[serviceconfig]: https://docs.rs/actix-web/2/actix_web/web/struct.ServiceConfig.html
|
[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
|
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
|
# Diesel
|
||||||
|
|
||||||
{{% alert %}}
|
The current version of Diesel (v1) does not support asynchronous operations, so it is important to
|
||||||
NOTE: The `actix-web` 1.0 version of this section is still
|
use the [`web::block`][web-block] function to offload your database operations to the Actix runtime
|
||||||
[being updated](https://github.com/cldershem/actix-website/tree/update1.0-db). Checkout
|
thread-pool.
|
||||||
this [example](https://github.com/actix/examples/tree/master/async_db) until then.
|
|
||||||
{{% /alert %}}
|
|
||||||
|
|
||||||
At the moment, Diesel 1.0 does not support asynchronous operations,
|
You can create action functions that correspond to all the operations your app will perform on the
|
||||||
but it's possible to use the `actix` synchronous actor system as a database interface api.
|
database.
|
||||||
|
|
||||||
Technically, sync actors are worker style actors. Multiple sync actors
|
{{< include-example example="databases" file="main.rs" section="handler" >}}
|
||||||
can be run in parallel and process messages from same queue. Sync actors work in mpsc mode.
|
|
||||||
|
|
||||||
Let's create a simple database api that can insert a new user row into a SQLite table.
|
Now you should set up the database pool using a crate such as `r2d2`, which makes many DB
|
||||||
We must define a sync actor and a connection that this actor will use. The same approach
|
connections available to your app. This means that multiple handlers can manipulate the DB at the
|
||||||
can be used for other databases.
|
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
|
{{< include-example example="databases" file="main.rs" section="index" >}}
|
||||||
`User` model instance. Next, we must define the handler implementation for this message.
|
|
||||||
|
|
||||||
{{< 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.
|
[web-block]: https://docs.rs/actix-web/3/actix_web/web/fn.block.html
|
||||||
All we need is to start *DbExecutor* actors and store the address in a state where http handler
|
[response-error]: https://docs.rs/actix-web/3/actix_web/trait.ResponseError.html
|
||||||
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
|
|
||||||
|
@ -7,12 +7,12 @@ weight: 180
|
|||||||
# Errors
|
# Errors
|
||||||
|
|
||||||
Actix-web uses its own [`actix_web::error::Error`][actixerror] type and
|
Actix-web uses its own [`actix_web::error::Error`][actixerror] type and
|
||||||
[`actix_web::error::ResponseError`][responseerror] trait for error handling
|
[`actix_web::error::ResponseError`][responseerror] trait for error handling from web handlers.
|
||||||
from web handlers.
|
|
||||||
|
|
||||||
If a handler returns an `Error` (referring to the [general Rust trait
|
If a handler returns an `Error` (referring to the [general Rust trait
|
||||||
`std::error::Error`][stderror]) in a `Result` that also implements the
|
`std::error::Error`][stderror]) in a `Result` that also implements the `ResponseError` trait,
|
||||||
`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:
|
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
|
```rust
|
||||||
pub trait ResponseError {
|
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>
|
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
|
`Error` in the code above is actix-web's error definition, and any errors that implement
|
||||||
implement `ResponseError` can be converted to one automatically.
|
`ResponseError` can be converted to one automatically.
|
||||||
|
|
||||||
Actix-web provides `ResponseError` implementations for some common non-actix
|
Actix-web provides `ResponseError` implementations for some common non-actix errors. For example, if
|
||||||
errors. For example, if a handler responds with an `io::Error`, that error is
|
a handler responds with an `io::Error`, that error is converted into an `HttpInternalServerError`:
|
||||||
converted into an `HttpInternalServerError`:
|
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use std::io;
|
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
|
See [the actix-web API documentation][responseerrorimpls] for a full list of foreign implementations
|
||||||
implementations for `ResponseError`.
|
for `ResponseError`.
|
||||||
|
|
||||||
## An example of a custom error response
|
## 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" >}}
|
{{< include-example example="errors" file="main.rs" section="response-error" >}}
|
||||||
|
|
||||||
`ResponseError` has a default implementation for `error_response()` that will
|
`ResponseError` has a default implementation for `error_response()` that will render a _500_
|
||||||
render a _500_ (internal server error), and that's what will happen when the
|
(internal server error), and that's what will happen when the `index` handler executes above.
|
||||||
`index` handler executes above.
|
|
||||||
|
|
||||||
Override `error_response()` to produce more useful results:
|
Override `error_response()` to produce more useful results:
|
||||||
|
|
||||||
@ -62,69 +61,56 @@ Override `error_response()` to produce more useful results:
|
|||||||
|
|
||||||
# Error helpers
|
# Error helpers
|
||||||
|
|
||||||
Actix-web provides a set of error helper functions that are useful for generating
|
Actix-web provides a set of error helper functions that are useful for generating specific HTTP
|
||||||
specific HTTP error codes from other errors. Here we convert `MyError`, which
|
error codes from other errors. Here we convert `MyError`, which doesn't implement the
|
||||||
doesn't implement the `ResponseError` trait, to a _400_ (bad request) using
|
`ResponseError` trait, to a _400_ (bad request) using `map_err`:
|
||||||
`map_err`:
|
|
||||||
|
|
||||||
{{< include-example example="errors" file="helpers.rs" section="helpers" >}}
|
{{< include-example example="errors" file="helpers.rs" section="helpers" >}}
|
||||||
|
|
||||||
See the [API documentation for actix-web's `error` module][actixerror]
|
See the [API documentation for actix-web's `error` module][actixerror] for a full list of available
|
||||||
for a full list of available error helpers.
|
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.
|
|
||||||
|
|
||||||
# Error logging
|
# Error logging
|
||||||
|
|
||||||
Actix logs all errors at the `WARN` log level. If an application's log level is
|
Actix logs all errors at the `WARN` log level. If an application's log level is set to `DEBUG` and
|
||||||
set to `DEBUG` and `RUST_BACKTRACE` is enabled, the backtrace is also logged.
|
`RUST_BACKTRACE` is enabled, the backtrace is also logged. These are configurable with environmental
|
||||||
These are configurable with environmental variables:
|
variables:
|
||||||
|
|
||||||
```
|
```
|
||||||
>> RUST_BACKTRACE=1 RUST_LOG=actix_web=debug cargo run
|
>> RUST_BACKTRACE=1 RUST_LOG=actix_web=debug cargo run
|
||||||
```
|
```
|
||||||
|
|
||||||
The `Error` type uses the cause's error backtrace if available. If the
|
The `Error` type uses the cause's error backtrace if available. If the underlying failure does not
|
||||||
underlying failure does not provide a backtrace, a new backtrace is constructed
|
provide a backtrace, a new backtrace is constructed pointing to the point where the conversion
|
||||||
pointing to the point where the conversion occurred (rather than the origin of
|
occurred (rather than the origin of the error).
|
||||||
the error).
|
|
||||||
|
|
||||||
# Recommended practices in error handling
|
# Recommended practices in error handling
|
||||||
|
|
||||||
It might be useful to think about dividing the errors an application produces
|
It might be useful to think about dividing the errors an application produces into two broad groups:
|
||||||
into two broad groups: those which are intended to be be user-facing, and those
|
those which are intended to be be user-facing, and those which are not.
|
||||||
which are not.
|
|
||||||
|
|
||||||
An example of the former is that I might use failure to specify a `UserError`
|
An example of the former is that I might use failure to specify a `UserError` enum which
|
||||||
enum which encapsulates a `ValidationError` to return whenever a user sends bad
|
encapsulates a `ValidationError` to return whenever a user sends bad input:
|
||||||
input:
|
|
||||||
|
|
||||||
{{< include-example example="errors" file="recommend_one.rs" section="recommend-one" >}}
|
{{< include-example example="errors" file="recommend_one.rs" section="recommend-one" >}}
|
||||||
|
|
||||||
This will behave exactly as intended because the error message defined with
|
This will behave exactly as intended because the error message defined with `display` is written
|
||||||
`display` is written with the explicit intent to be read by a user.
|
with the explicit intent to be read by a user.
|
||||||
|
|
||||||
However, sending back an error's message isn't desirable for all errors --
|
However, sending back an error's message isn't desirable for all errors -- there are many failures
|
||||||
there are many failures that occur in a server environment where we'd probably
|
that occur in a server environment where we'd probably want the specifics to be hidden from the
|
||||||
want the specifics to be hidden from the user. For example, if a database goes
|
user. For example, if a database goes down and client libraries start producing connect timeout
|
||||||
down and client libraries start producing connect timeout errors, or if an HTML
|
errors, or if an HTML template was improperly formatted and errors when rendered. In these cases, it
|
||||||
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.
|
||||||
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`
|
Here's an example that maps an internal error to a user-facing `InternalError` with a custom
|
||||||
with a custom message:
|
message:
|
||||||
|
|
||||||
{{< include-example example="errors" file="recommend_two.rs" section="recommend-two" >}}
|
{{< 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
|
By dividing errors into those which are user facing and those which are not, we can ensure that we
|
||||||
can ensure that we don't accidentally expose users to errors thrown by
|
don't accidentally expose users to errors thrown by application internals which they weren't meant
|
||||||
application internals which they weren't meant to see.
|
to see.
|
||||||
|
|
||||||
# Error Logging
|
# Error Logging
|
||||||
|
|
||||||
@ -132,10 +118,11 @@ This is a basic example using `middleware::Logger`:
|
|||||||
|
|
||||||
{{< include-example example="errors" file="logging.rs" section="logging" >}}
|
{{< include-example example="errors" file="logging.rs" section="logging" >}}
|
||||||
|
|
||||||
[actixerror]: https://docs.rs/actix-web/2/actix_web/error/struct.Error.html
|
[actixerror]: https://docs.rs/actix-web/3/actix_web/error/struct.Error.html
|
||||||
[errorhelpers]: https://docs.rs/actix-web/2/actix_web/trait.ResponseError.html
|
[errorhelpers]: https://docs.rs/actix-web/3/actix_web/trait.ResponseError.html
|
||||||
[failure]: https://github.com/rust-lang-nursery/failure
|
[derive_more]: https://crates.io/crates/derive_more
|
||||||
[responseerror]: https://docs.rs/actix-web/2/actix_web/error/trait.ResponseError.html
|
[responseerror]: https://docs.rs/actix-web/3/actix_web/error/trait.ResponseError.html
|
||||||
[responseerrorimpls]: https://docs.rs/actix-web/2/actix_web/error/trait.ResponseError.html#foreign-impls
|
[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
|
[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*][pathstruct] provides information that can be extracted from the Request's
|
||||||
path. You can deserialize any variable segment from the path.
|
path. You can deserialize any variable segment from the path.
|
||||||
|
|
||||||
For instance, for resource that registered for the `/users/{userid}/{friend}` path,
|
For instance, for resource that registered for the `/users/{user_id}/{friend}` path,
|
||||||
two segments could be deserialized, `userid` and `friend`. These segments could be
|
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
|
extracted into a `tuple`, i.e. `Path<(u32, String)>` or any structure that implements
|
||||||
the `Deserialize` trait from the *serde* crate.
|
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
|
> request handling processes would block. If you need to share or update some state
|
||||||
> from multiple threads, consider using the tokio synchronization primitives.
|
> from multiple threads, consider using the tokio synchronization primitives.
|
||||||
|
|
||||||
[pathstruct]: https://docs.rs/actix-web/2/actix_web/dev/struct.Path.html
|
[pathstruct]: https://docs.rs/actix-web/3/actix_web/dev/struct.Path.html
|
||||||
[querystruct]: https://docs.rs/actix-web/2/actix_web/web/struct.Query.html
|
[querystruct]: https://docs.rs/actix-web/3/actix_web/web/struct.Query.html
|
||||||
[jsonstruct]: https://docs.rs/actix-web/2/actix_web/web/struct.Json.html
|
[jsonstruct]: https://docs.rs/actix-web/3/actix_web/web/struct.Json.html
|
||||||
[jsonconfig]: https://docs.rs/actix-web/2/actix_web/web/struct.JsonConfig.html
|
[jsonconfig]: https://docs.rs/actix-web/3/actix_web/web/struct.JsonConfig.html
|
||||||
[formconfig]: https://docs.rs/actix-web/2/actix_web/web/struct.FormConfig.html
|
[formconfig]: https://docs.rs/actix-web/3/actix_web/web/struct.FormConfig.html
|
||||||
[datastruct]: https://docs.rs/actix-web/2/actix_web/web/struct.Data.html
|
[datastruct]: https://docs.rs/actix-web/3/actix_web/web/struct.Data.html
|
||||||
[stringexample]: https://docs.rs/actix-web/2/actix_web/trait.FromRequest.html#example-2
|
[stringexample]: https://docs.rs/actix-web/3/actix_web/trait.FromRequest.html#example-2
|
||||||
[bytesexample]: https://docs.rs/actix-web/2/actix_web/trait.FromRequest.html#example-4
|
[bytesexample]: https://docs.rs/actix-web/3/actix_web/trait.FromRequest.html#example-4
|
||||||
[payloadexample]: https://docs.rs/actix-web/2/actix_web/web/struct.Payload.html
|
[payloadexample]: https://docs.rs/actix-web/3/actix_web/web/struct.Payload.html
|
||||||
[actix]: https://actix.github.io/actix/actix/
|
[actix]: https://actix.github.io/actix/actix/
|
||||||
|
@ -4,9 +4,14 @@ menu: docs_basics
|
|||||||
weight: 130
|
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!
|
## Hello, world!
|
||||||
|
|
||||||
@ -17,71 +22,35 @@ cargo new hello-world
|
|||||||
cd hello-world
|
cd hello-world
|
||||||
```
|
```
|
||||||
|
|
||||||
Now, add `actix-web` as a dependency of your project by ensuring your `Cargo.toml`
|
Add `actix-web` as a dependency of your project by adding the following to your `Cargo.toml` file.
|
||||||
contains the following:
|
|
||||||
|
|
||||||
```ini
|
```toml
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-web = "{{< actix-version "actix-web" >}}"
|
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.
|
Request handlers use an async functions that accept zero or more parameters. These parameters can be
|
||||||
Now your `Cargo.toml` should look like following:
|
extracted from a request (see `FromRequest` trait) and returns a type that can be converted into an
|
||||||
|
`HttpResponse` (see `Responder` trait):
|
||||||
|
|
||||||
```ini
|
{{< include-example example="getting-started" section="handlers" >}}
|
||||||
[dependencies]
|
|
||||||
actix-web = "{{< actix-version "actix-web" >}}"
|
|
||||||
actix-rt = "{{< actix-version "actix-rt" >}}"
|
|
||||||
```
|
|
||||||
|
|
||||||
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
|
Next, create an `App` instance and register the request handlers. Use `App::service` for the
|
||||||
extracted from a request (ie, `impl FromRequest`) and returns a type that can be
|
handlers using routing macros and `App::route` for manually routed handlers, declaring the a path
|
||||||
converted into an `HttpResponse` (ie, `impl Responder`):
|
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="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.
|
|
||||||
|
|
||||||
{{< include-example example="getting-started" section="main" >}}
|
{{< include-example example="getting-started" section="main" >}}
|
||||||
|
|
||||||
That's it! Now, compile and run the program with `cargo run`.
|
That's it! Compile and run the program with `cargo run`. The `#[actix_web::main]` macro executes the
|
||||||
Head over to `http://localhost:8088/` to see the results.
|
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
|
<!-- LINKS -->
|
||||||
macro executes the associated async function within the actix runtime.
|
|
||||||
Any async function could be marked and executed by this macro.
|
|
||||||
|
|
||||||
### Using Attribute Macros to Define Routes
|
|
||||||
|
|
||||||
Alternatively, you can define routes using macro attributes which
|
|
||||||
allow you to specify the routes above your functions like so:
|
|
||||||
|
|
||||||
{{< include-example example="getting-started" section="macro-attributes">}}
|
|
||||||
|
|
||||||
You can then register the route using `service()`:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
App::new()
|
|
||||||
.service(index3)
|
|
||||||
```
|
|
||||||
|
|
||||||
For consistency reasons, this documentation only uses the explicit syntax shown at the
|
|
||||||
beginning of this page. However, if you prefer this syntax you should feel free to
|
|
||||||
use it any time you declare a route as it's only syntactic sugar.
|
|
||||||
|
|
||||||
To learn more, see [actix-web-codegen].
|
|
||||||
|
|
||||||
### Auto-reloading
|
|
||||||
|
|
||||||
If you want, you can have an automatically reloading server during development
|
|
||||||
that recompiles on demand. This isn't necessary, but it makes rapid prototyping
|
|
||||||
more convenient as you can see changes instantly upon saving.
|
|
||||||
To see how this can be accomplished, have a look at the [autoreload pattern][autoload].
|
|
||||||
|
|
||||||
|
[rustguide]: https://doc.rust-lang.org/book/ch01-01-installation.html
|
||||||
[actix-web-codegen]: https://docs.rs/actix-web-codegen/
|
[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
|
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.
|
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.
|
different responder types into a single type.
|
||||||
|
|
||||||
{{< include-example example="either" file="main.rs" section="either" >}}
|
{{< include-example example="either" file="main.rs" section="either" >}}
|
||||||
|
|
||||||
[implfromrequest]: https://docs.rs/actix-web/2/actix_web/trait.FromRequest.html
|
[implfromrequest]: https://docs.rs/actix-web/3/actix_web/trait.FromRequest.html
|
||||||
[respondertrait]: https://docs.rs/actix-web/2/actix_web/trait.Responder.html
|
[respondertrait]: https://docs.rs/actix-web/3/actix_web/trait.Responder.html
|
||||||
[responderimpls]: https://docs.rs/actix-web/2/actix_web/trait.Responder.html#foreign-impls
|
[responderimpls]: https://docs.rs/actix-web/3/actix_web/trait.Responder.html#foreign-impls
|
||||||
[either]: https://docs.rs/actix-web/2/actix_web/enum.Either.html
|
[either]: https://docs.rs/actix-web/3/actix_web/enum.Either.html
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
---
|
---
|
||||||
title: HTTP/2.0
|
title: HTTP/2
|
||||||
menu: docs_proto
|
menu: docs_protocols
|
||||||
weight: 250
|
weight: 250
|
||||||
---
|
---
|
||||||
|
|
||||||
`actix-web` automatically upgrades connections to *HTTP/2.0* if possible.
|
`actix-web` automatically upgrades connections to *HTTP/2* if possible.
|
||||||
|
|
||||||
# Negotiation
|
# 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.
|
> Currently, only `rust-openssl` has support.
|
||||||
|
|
||||||
`alpn` negotiation requires enabling the feature. When enabled, `HttpServer` provides the
|
`alpn` negotiation requires enabling the feature. When enabled, `HttpServer` provides the
|
||||||
@ -18,7 +19,6 @@ weight: 250
|
|||||||
```toml
|
```toml
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-web = { version = "{{< actix-version "actix-web" >}}", features = ["openssl"] }
|
actix-web = { version = "{{< actix-version "actix-web" >}}", features = ["openssl"] }
|
||||||
actix-rt = "1.0.0"
|
|
||||||
openssl = { version = "0.10", features = ["v110"] }
|
openssl = { version = "0.10", features = ["v110"] }
|
||||||
```
|
```
|
||||||
{{< include-example example="http2" file="main.rs" section="main" >}}
|
{{< 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
|
[rfcsection32]: https://http2.github.io/http2-spec/#rfc.section.3.2
|
||||||
[rfcsection34]: https://http2.github.io/http2-spec/#rfc.section.3.4
|
[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
|
[tlsalpn]: https://tools.ietf.org/html/rfc7301
|
||||||
[examples]: https://github.com/actix/examples/tree/master/rustls
|
[examples]: https://github.com/actix/examples/tree/master/rustls
|
||||||
|
@ -1,20 +1,21 @@
|
|||||||
---
|
---
|
||||||
title: Http Server Initialization
|
title: HTTP Server Initialization
|
||||||
menu: docs_architecture
|
menu: docs_architecture
|
||||||
weight: 1020
|
weight: 1020
|
||||||
---
|
---
|
||||||
|
|
||||||
## Architecture overview
|
## 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
|
```rust
|
||||||
#[actix_rt::main]
|
#[actix_web::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
HttpServer::new(|| {
|
HttpServer::new(|| {
|
||||||
App::new()
|
App::new()
|
||||||
.route("/", web::to(|| HttpResponse::Ok()))
|
.route("/", web::to(|| HttpResponse::Ok()))
|
||||||
})
|
})
|
||||||
.bind("127.0.0.1:8088")?
|
.bind("127.0.0.1:8080")?
|
||||||
.run()
|
.run()
|
||||||
.await
|
.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
|
menu: docs_advanced
|
||||||
weight: 220
|
weight: 220
|
||||||
---
|
---
|
||||||
@ -29,11 +29,11 @@ The following demonstrates creating a simple middleware:
|
|||||||
|
|
||||||
{{< include-example example="middleware" file="main.rs" section="simple" >}}
|
{{< 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" >}}
|
{{< 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.
|
> *compress*, etc.
|
||||||
|
|
||||||
# Logging
|
# Logging
|
||||||
@ -89,8 +89,7 @@ a specified header.
|
|||||||
## User sessions
|
## User sessions
|
||||||
|
|
||||||
Actix-web provides a general solution for session management. The
|
Actix-web provides a general solution for session management. The
|
||||||
[**actix-session**][actixsession] middleware can be used with different backend types
|
[**actix-session**][actixsession] middleware can use multiple backend types to store session data.
|
||||||
to store session data in different backends.
|
|
||||||
|
|
||||||
> By default, only cookie session backend is implemented. Other backend implementations
|
> By default, only cookie session backend is implemented. Other backend implementations
|
||||||
> can be added.
|
> can be added.
|
||||||
@ -132,6 +131,6 @@ into a response.
|
|||||||
[cookiesession]: https://docs.rs/actix-session/0.3.0/actix_session/struct.CookieSession.html
|
[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/
|
[actixsession]: https://docs.rs/actix-session/0.3.0/actix_session/
|
||||||
[envlogger]: https://docs.rs/env_logger/*/env_logger/
|
[envlogger]: https://docs.rs/env_logger/*/env_logger/
|
||||||
[servicetrait]: https://docs.rs/actix-web/2/actix_web/dev/trait.Service.html
|
[servicetrait]: https://docs.rs/actix-web/3/actix_web/dev/trait.Service.html
|
||||||
[transformtrait]: https://docs.rs/actix-web/2/actix_web/dev/trait.Transform.html
|
[transformtrait]: https://docs.rs/actix-web/3/actix_web/dev/trait.Transform.html
|
||||||
[wrap_fn]: https://docs.rs/actix-web/2/actix_web/struct.App.html#method.wrap_fn
|
[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
|
[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
|
[fieldstruct]: https://docs.rs/actix-multipart/0.2/actix_multipart/struct.Field.html
|
||||||
[multipartexample]: https://github.com/actix/examples/tree/master/multipart/
|
[multipartexample]: https://github.com/actix/examples/tree/master/multipart/
|
||||||
[urlencoded]: https://docs.rs/actix-web/2/actix_web/dev/struct.UrlEncoded.html
|
[urlencoded]: https://docs.rs/actix-web/3/actix_web/dev/struct.UrlEncoded.html
|
||||||
[payloadextractor]: https://docs.rs/actix-web/2/actix_web/web/struct.Payload.html
|
[payloadextractor]: https://docs.rs/actix-web/3/actix_web/web/struct.Payload.html
|
||||||
[multipartcrate]: https://crates.io/crates/actix-multipart
|
[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" >}}
|
{{< include-example example="responses" file="json_resp.rs" section="json-resp" >}}
|
||||||
|
|
||||||
[responsebuilder]: https://docs.rs/actix-web/2/actix_web/dev/struct.HttpResponseBuilder.html
|
[responsebuilder]: https://docs.rs/actix-web/3/actix_web/dev/struct.HttpResponseBuilder.html
|
||||||
[compressmidddleware]: https://docs.rs/actix-web/2/actix_web/middleware/struct.Compress.html
|
[compressmidddleware]: https://docs.rs/actix-web/3/actix_web/middleware/struct.Compress.html
|
||||||
|
@ -6,32 +6,32 @@ weight: 150
|
|||||||
|
|
||||||
# The HTTP Server
|
# 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
|
`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.
|
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
|
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
|
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.
|
method.
|
||||||
|
|
||||||
{{< include-example example="server" section="main" >}}
|
{{< include-example example="server" section="main" >}}
|
||||||
|
|
||||||
The `run()` method returns an instance of the [`Server`][server] type. Methods of server type
|
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
|
- `pause()` - Pause accepting incoming connections
|
||||||
- `resume()` - Resume accepting incoming connections
|
- `resume()` - Resume accepting incoming connections
|
||||||
- `stop()` - Stop incoming connection processing, stop all workers and exit
|
- `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" >}}
|
{{< include-example example="server" file="signals.rs" section="signals" >}}
|
||||||
|
|
||||||
## Multi-threading
|
## 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
|
equal to the number of logical CPUs in the system. This number can be overridden with the
|
||||||
[`HttpServer::workers()`][workers] method.
|
[`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
|
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
|
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*.
|
> *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
|
> It is possible to disable signal handling with
|
||||||
[`HttpServer::disable_signals()`][disablesignals] method.
|
[`HttpServer::disable_signals()`][disablesignals] method.
|
||||||
|
|
||||||
[server]: https://docs.rs/actix-web/2/actix_web/dev/struct.Server.html
|
[server]: https://docs.rs/actix-web/3/actix_web/dev/struct.Server.html
|
||||||
[httpserverstruct]: https://docs.rs/actix-web/2/actix_web/struct.HttpServer.html
|
[httpserverstruct]: https://docs.rs/actix-web/3/actix_web/struct.HttpServer.html
|
||||||
[bindmethod]: https://docs.rs/actix-web/2/actix_web/struct.HttpServer.html#method.bind
|
[bindmethod]: https://docs.rs/actix-web/3/actix_web/struct.HttpServer.html#method.bind
|
||||||
[bindopensslmethod]: https://docs.rs/actix-web/2/actix_web/struct.HttpServer.html#method.bind_openssl
|
[bindopensslmethod]: https://docs.rs/actix-web/3/actix_web/struct.HttpServer.html#method.bind_openssl
|
||||||
[bindrusttls]: https://docs.rs/actix-web/2/actix_web/struct.HttpServer.html#method.bind_rustls
|
[bindrusttls]: https://docs.rs/actix-web/3/actix_web/struct.HttpServer.html#method.bind_rustls
|
||||||
[startmethod]: https://docs.rs/actix-web/2/actix_web/struct.HttpServer.html#method.start
|
[startmethod]: https://docs.rs/actix-web/3/actix_web/struct.HttpServer.html#method.start
|
||||||
[workers]: https://docs.rs/actix-web/2/actix_web/struct.HttpServer.html#method.workers
|
[workers]: https://docs.rs/actix-web/3/actix_web/struct.HttpServer.html#method.workers
|
||||||
[tlsalpn]: https://tools.ietf.org/html/rfc7301
|
[tlsalpn]: https://tools.ietf.org/html/rfc7301
|
||||||
[exampleopenssl]: https://github.com/actix/examples/blob/master/openssl
|
[exampleopenssl]: https://github.com/actix/examples/blob/master/openssl
|
||||||
[shutdowntimeout]: https://docs.rs/actix-web/2/actix_web/struct.HttpServer.html#method.shutdown_timeout
|
[shutdowntimeout]: https://docs.rs/actix-web/3/actix_web/struct.HttpServer.html#method.shutdown_timeout
|
||||||
[disablesignals]: https://docs.rs/actix-web/2/actix_web/struct.HttpServer.html#method.disable_signals
|
[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
|
# Integration tests
|
||||||
|
|
||||||
There are a few methods for testing your application. Actix-web can be used
|
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
|
`TestRequest::get()`, `TestRequest::post()` and other
|
||||||
methods can be used to send requests to the test server.
|
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
|
To create a `Service` for testing, use the `test::init_service` method which accepts a
|
||||||
regular `App` builder.
|
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" >}}
|
{{< 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" >}}
|
{{< 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
|
[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
|
[responsebody]: https://docs.rs/actix-web/3/actix_web/body/enum.ResponseBody.html
|
||||||
[actixdocs]: https://docs.rs/actix-web/2/actix_web/test/index.html
|
[actixdocs]: https://docs.rs/actix-web/3/actix_web/test/index.html
|
||||||
[testrequest]: https://docs.rs/actix-web/2/actix_web/test/struct.TestRequest.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
|
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*,
|
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.
|
for the same path, in that case, multiple routes register for the same resource path.
|
||||||
|
|
||||||
{{< include-example example="url-dispatch" section="main" >}}
|
{{< 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" >}}
|
{{< 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
|
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
|
## Configuring a Route
|
||||||
|
|
||||||
@ -197,7 +197,7 @@ When matching the following URL:
|
|||||||
http://example.com/foo/La%20Pe%C3%B1a
|
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'}
|
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" >}}
|
{{< include-example example="url-dispatch" file="scope.rs" section="scope" >}}
|
||||||
|
|
||||||
A *scoped* path can contain variable path segments as resources. Consistent with
|
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()`.
|
You can get variable path segments from `HttpRequest::match_info()`.
|
||||||
[`Path` extractor][pathextractor] also is able to extract scope level variable segments.
|
[`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]
|
Actix provides functionality for type safe path information extraction. [*Path*][pathstruct]
|
||||||
extracts information, destination type could be defined in several different forms. Simplest
|
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 pattern. i.e. you can match path pattern `/{id}/{username}/` against
|
||||||
`Path<(u32, String)>` type, but `Path<(String, String, String)>` type will always fail.
|
`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
|
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
|
and returns *true* or *false*. Formally, a guard is any object that implements the
|
||||||
[`Guard`][guardtrait] trait. Actix provides several predicates, you can check
|
[`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*:
|
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" >}}
|
{{< include-example example="url-dispatch" file="dhandler.rs" section="default" >}}
|
||||||
|
|
||||||
[handlersection]: ../handlers/
|
[handlersection]: ../handlers/
|
||||||
[approute]: https://docs.rs/actix-web/2/actix_web/struct.App.html#method.route
|
[approute]: https://docs.rs/actix-web/3/actix_web/struct.App.html#method.route
|
||||||
[appservice]: https://docs.rs/actix-web/2/actix_web/struct.App.html?search=#method.service
|
[appservice]: https://docs.rs/actix-web/3/actix_web/struct.App.html?search=#method.service
|
||||||
[webresource]: https://docs.rs/actix-web/2/actix_web/struct.Resource.html
|
[webresource]: https://docs.rs/actix-web/3/actix_web/struct.Resource.html
|
||||||
[resourcehandler]: https://docs.rs/actix-web/2/actix_web/struct.Resource.html#method.route
|
[resourcehandler]: https://docs.rs/actix-web/3/actix_web/struct.Resource.html#method.route
|
||||||
[route]: https://docs.rs/actix-web/2/actix_web/struct.Route.html
|
[route]: https://docs.rs/actix-web/3/actix_web/struct.Route.html
|
||||||
[routeguard]: https://docs.rs/actix-web/2/actix_web/struct.Route.html#method.guard
|
[routeguard]: https://docs.rs/actix-web/3/actix_web/struct.Route.html#method.guard
|
||||||
[routemethod]: https://docs.rs/actix-web/2/actix_web/struct.Route.html#method.method
|
[routemethod]: https://docs.rs/actix-web/3/actix_web/struct.Route.html#method.method
|
||||||
[routeto]: https://docs.rs/actix-web/2/actix_web/struct.Route.html#method.to
|
[routeto]: https://docs.rs/actix-web/3/actix_web/struct.Route.html#method.to
|
||||||
[routetoasync]: https://docs.rs/actix-web/2/actix_web/struct.Route.html#method.to_async
|
[routetoasync]: https://docs.rs/actix-web/3/actix_web/struct.Route.html#method.to_async
|
||||||
[matchinfo]: https://docs.rs/actix-web/2/actix_web/struct.HttpRequest.html#method.match_info
|
[matchinfo]: https://docs.rs/actix-web/3/actix_web/struct.HttpRequest.html#method.match_info
|
||||||
[pathget]: https://docs.rs/actix-web/2/actix_web/dev/struct.Path.html#method.get
|
[pathget]: https://docs.rs/actix-web/3/actix_web/dev/struct.Path.html#method.get
|
||||||
[pathstruct]: https://docs.rs/actix-web/2/actix_web/dev/struct.Path.html
|
[pathstruct]: https://docs.rs/actix-web/3/actix_web/dev/struct.Path.html
|
||||||
[query]: https://docs.rs/actix-web/2/actix_web/web/struct.Query.html
|
[query]: https://docs.rs/actix-web/3/actix_web/web/struct.Query.html
|
||||||
[urlfor]: https://docs.rs/actix-web/2/actix_web/struct.HttpRequest.html#method.url_for
|
[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
|
[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
|
[guardtrait]: https://docs.rs/actix-web/3/actix_web/guard/trait.Guard.html
|
||||||
[guardfuncs]: https://docs.rs/actix-web/2/actix_web/guard/index.html#functions
|
[guardfuncs]: https://docs.rs/actix-web/3/actix_web/guard/index.html#functions
|
||||||
[requestextensions]: https://docs.rs/actix-web/2/actix_web/struct.HttpRequest.html#method.extensions
|
[requestextensions]: https://docs.rs/actix-web/3/actix_web/struct.HttpRequest.html#method.extensions
|
||||||
[implfromrequest]: https://docs.rs/actix-web/2/actix_web/trait.FromRequest.html
|
[implfromrequest]: https://docs.rs/actix-web/3/actix_web/trait.FromRequest.html
|
||||||
[implresponder]: https://docs.rs/actix-web/2/actix_web/trait.Responder.html
|
[implresponder]: https://docs.rs/actix-web/3/actix_web/trait.Responder.html
|
||||||
[pathextractor]: ../extractors
|
[pathextractor]: ../extractors
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
title: Websockets
|
title: Websockets
|
||||||
menu: docs_proto
|
menu: docs_protocols
|
||||||
weight: 240
|
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].
|
> 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]
|
> is available in [websocket-chat directory][chat]
|
||||||
|
|
||||||
[message]: https://docs.rs/actix-web-actors/2/actix_web_actors/ws/enum.Message.html
|
[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/
|
[examples]: https://github.com/actix/examples/tree/master/websocket/
|
||||||
[chat]: https://github.com/actix/examples/tree/master/websocket-chat/
|
[chat]: https://github.com/actix/examples/tree/master/websocket-chat/
|
||||||
|
@ -4,24 +4,29 @@ menu: docs_intro
|
|||||||
weight: 100
|
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
|
Actix is a few things. The base of it is a powerful actor system for Rust on top of which the
|
||||||
top of which the `actix-web` system was originally built. This is what you are most
|
`actix-web` system was originally built. This is what you are most likely going to work with. What
|
||||||
likely going to work with. What `actix-web` gives you is a fun and very fast web
|
`actix-web` gives you is a powerful and very fast web development framework.
|
||||||
development framework.
|
|
||||||
|
|
||||||
We call `actix-web` a small and pragmatic framework. For all intents and purposes
|
We call `actix-web` a small and pragmatic framework. For all intents and purposes it's a
|
||||||
it's a microframework with a few twists. If you are already a Rust programmer
|
micro-framework with a few twists. If you are already a Rust programmer you will probably find
|
||||||
you will probably find yourself at home quickly, but even if you are coming from
|
yourself at home quickly, but even if you are coming from another programming language you should
|
||||||
another programming language you should find `actix-web` easy to pick up.
|
find `actix-web` easy to pick up.
|
||||||
|
|
||||||
An application developed with `actix-web` will expose an HTTP server contained
|
An application developed with `actix-web` will expose an HTTP server contained within a native
|
||||||
within a native executable. You can either put this behind another HTTP server like
|
executable. You can either put this behind another HTTP server like nginx or serve it up as-is. Even
|
||||||
nginx or serve it up as-is. Even in the complete absence of another HTTP
|
in the complete absence of another HTTP server `actix-web` is powerful enough to provide HTTP/1 and
|
||||||
server `actix-web` is powerful enough to provide HTTP 1 and HTTP 2 support as
|
HTTP/2 support as well as TLS (HTTPS). This makes it useful for building small services ready for
|
||||||
well as SSL/TLS. This makes it useful for building small services ready for
|
|
||||||
distribution.
|
distribution.
|
||||||
|
|
||||||
Most importantly: `actix-web` runs on Rust {{< rust-version "actix-web" >}} or later
|
Most importantly: `actix-web` runs on Rust {{< rust-version "actix-web" >}} or later and it works
|
||||||
and it works with stable releases.
|
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]
|
[workspace]
|
||||||
members = [
|
members = [
|
||||||
"application",
|
"application",
|
||||||
|
"async-handlers",
|
||||||
"easy-form-handling",
|
"easy-form-handling",
|
||||||
|
"either",
|
||||||
|
"errors",
|
||||||
|
"extractors",
|
||||||
"flexible-responders",
|
"flexible-responders",
|
||||||
"getting-started",
|
"getting-started",
|
||||||
"main-example",
|
|
||||||
"powerful-extractors",
|
|
||||||
"request-routing",
|
|
||||||
"server",
|
|
||||||
"url-dispatch",
|
|
||||||
"responder-trait",
|
|
||||||
"either",
|
|
||||||
"extractors",
|
|
||||||
"autoreload",
|
|
||||||
"errors",
|
|
||||||
"requests",
|
|
||||||
"responses",
|
|
||||||
"middleware",
|
|
||||||
"static-files",
|
|
||||||
"http2",
|
"http2",
|
||||||
"testing",
|
"main-example",
|
||||||
"async-handlers",
|
"middleware",
|
||||||
"websockets",
|
"powerful-extractors",
|
||||||
"request-handlers",
|
"request-handlers",
|
||||||
|
"request-routing",
|
||||||
|
"requests",
|
||||||
|
"responder-trait",
|
||||||
|
"responses",
|
||||||
|
"server",
|
||||||
|
"static-files",
|
||||||
|
"testing",
|
||||||
|
"url-dispatch",
|
||||||
|
"websockets",
|
||||||
]
|
]
|
||||||
exclude = [
|
exclude = ["databases", "sentry"]
|
||||||
"og_databases",
|
|
||||||
"sentry",
|
|
||||||
]
|
|
||||||
|
@ -5,6 +5,5 @@ edition = "2018"
|
|||||||
workspace = "../"
|
workspace = "../"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-web = "2.0"
|
actix-web = "3"
|
||||||
actix-rt = "1.0"
|
actix-service = "1"
|
||||||
actix-service = "1.0"
|
|
||||||
|
@ -1,18 +1,23 @@
|
|||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
// <setup>
|
// <setup>
|
||||||
use actix_web::{web, App, Responder, HttpServer};
|
use actix_web::{web, App, HttpServer, Responder};
|
||||||
|
|
||||||
async fn index() -> impl Responder {
|
async fn index() -> impl Responder {
|
||||||
"Hello world!"
|
"Hello world!"
|
||||||
}
|
}
|
||||||
|
|
||||||
#[actix_rt::main]
|
#[actix_web::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
HttpServer::new(|| {
|
HttpServer::new(|| {
|
||||||
App::new().service(
|
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()
|
.run()
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
@ -1,24 +1,27 @@
|
|||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
use actix_web::{web, App, HttpResponse, HttpServer};
|
use actix_web::{web, App, HttpResponse, HttpServer};
|
||||||
|
|
||||||
// <combine>
|
// <combine>
|
||||||
struct State1;
|
struct State1;
|
||||||
struct State2;
|
struct State2;
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[actix_web::main]
|
||||||
#[actix_rt::main]
|
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
HttpServer::new(|| {
|
HttpServer::new(|| {
|
||||||
App::new()
|
App::new()
|
||||||
.service(
|
.service(
|
||||||
web::scope("/app1")
|
web::scope("/app1")
|
||||||
.data(State1)
|
.data(State1)
|
||||||
.route("/", web::to(|| HttpResponse::Ok())))
|
.route("/", web::to(|| HttpResponse::Ok())),
|
||||||
|
)
|
||||||
.service(
|
.service(
|
||||||
web::scope("/app2")
|
web::scope("/app2")
|
||||||
.data(State2)
|
.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()
|
.run()
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
// <config>
|
// <config>
|
||||||
use actix_web::{web, App, HttpResponse, HttpServer};
|
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<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
HttpServer::new(|| {
|
HttpServer::new(|| {
|
||||||
App::new()
|
App::new()
|
||||||
@ -27,7 +29,7 @@ async fn main() -> std::io::Result<()> {
|
|||||||
.service(web::scope("/api").configure(scoped_config))
|
.service(web::scope("/api").configure(scoped_config))
|
||||||
.route("/", web::get().to(|| HttpResponse::Ok().body("/")))
|
.route("/", web::get().to(|| HttpResponse::Ok().body("/")))
|
||||||
})
|
})
|
||||||
.bind("127.0.0.1:8088")?
|
.bind("127.0.0.1:8080")?
|
||||||
.run()
|
.run()
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ pub mod state;
|
|||||||
pub mod vh;
|
pub mod vh;
|
||||||
|
|
||||||
// <multi>
|
// <multi>
|
||||||
#[actix_rt::main]
|
#[actix_web::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
HttpServer::new(|| {
|
HttpServer::new(|| {
|
||||||
App::new()
|
App::new()
|
||||||
@ -20,7 +20,7 @@ async fn main() -> std::io::Result<()> {
|
|||||||
)
|
)
|
||||||
.route("/", web::to(|| HttpResponse::Ok()))
|
.route("/", web::to(|| HttpResponse::Ok()))
|
||||||
})
|
})
|
||||||
.bind("127.0.0.1:8088")?
|
.bind("127.0.0.1:8080")?
|
||||||
.run()
|
.run()
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ async fn index(data: web::Data<AppStateWithCounter>) -> String {
|
|||||||
// </setup_mutable>
|
// </setup_mutable>
|
||||||
|
|
||||||
// <make_app_mutable>
|
// <make_app_mutable>
|
||||||
#[actix_rt::main]
|
#[actix_web::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
let counter = web::Data::new(AppStateWithCounter {
|
let counter = web::Data::new(AppStateWithCounter {
|
||||||
counter: Mutex::new(0),
|
counter: Mutex::new(0),
|
||||||
@ -28,7 +28,7 @@ async fn main() -> std::io::Result<()> {
|
|||||||
.app_data(counter.clone()) // <- register the created data
|
.app_data(counter.clone()) // <- register the created data
|
||||||
.route("/", web::get().to(index))
|
.route("/", web::get().to(index))
|
||||||
})
|
})
|
||||||
.bind("127.0.0.1:8088")?
|
.bind("127.0.0.1:8080")?
|
||||||
.run()
|
.run()
|
||||||
.await
|
.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 {
|
async fn show_users(_req: HttpRequest) -> impl Responder {
|
||||||
"unimplemented!"
|
"unimplemented!"
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustfmt::skip]
|
|
||||||
// <scope>
|
// <scope>
|
||||||
#[actix_rt::main]
|
#[actix_web::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
App::new()
|
let scope = web::scope("/users").service(show_users);
|
||||||
.service(
|
App::new().service(scope);
|
||||||
web::scope("/users")
|
|
||||||
.route("/show", web::get().to(show_users)));
|
|
||||||
}
|
}
|
||||||
// </scope>
|
// </scope>
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
// <setup>
|
// <setup>
|
||||||
use actix_web::{web, App, HttpServer};
|
use actix_web::{get, web, App, HttpServer};
|
||||||
use std::sync::Mutex;
|
|
||||||
|
|
||||||
// This struct represents state
|
// This struct represents state
|
||||||
struct AppState {
|
struct AppState {
|
||||||
app_name: String,
|
app_name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[get("/")]
|
||||||
async fn index(data: web::Data<AppState>) -> String {
|
async fn index(data: web::Data<AppState>) -> String {
|
||||||
let app_name = &data.app_name; // <- get app_name
|
let app_name = &data.app_name; // <- get app_name
|
||||||
|
|
||||||
@ -15,16 +15,16 @@ async fn index(data: web::Data<AppState>) -> String {
|
|||||||
// </setup>
|
// </setup>
|
||||||
|
|
||||||
// <start_app>
|
// <start_app>
|
||||||
#[actix_rt::main]
|
#[actix_web::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
HttpServer::new(|| {
|
HttpServer::new(|| {
|
||||||
App::new()
|
App::new()
|
||||||
.data(AppState {
|
.data(AppState {
|
||||||
app_name: String::from("Actix-web"),
|
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()
|
.run()
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use actix_web::{guard, web, App, HttpResponse, HttpServer};
|
use actix_web::{guard, web, App, HttpResponse, HttpServer};
|
||||||
|
|
||||||
// <vh>
|
// <vh>
|
||||||
#[actix_rt::main]
|
#[actix_web::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
HttpServer::new(|| {
|
HttpServer::new(|| {
|
||||||
App::new()
|
App::new()
|
||||||
@ -17,7 +17,7 @@ async fn main() -> std::io::Result<()> {
|
|||||||
)
|
)
|
||||||
.route("/", web::to(|| HttpResponse::Ok()))
|
.route("/", web::to(|| HttpResponse::Ok()))
|
||||||
})
|
})
|
||||||
.bind("127.0.0.1:8088")?
|
.bind("127.0.0.1:8080")?
|
||||||
.run()
|
.run()
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@ version = "2.0.0"
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-web = "2.0"
|
actix-web = "3"
|
||||||
actix-rt = "1.0"
|
|
||||||
futures = "0.3.1"
|
futures = "0.3.1"
|
||||||
bytes = "0.5"
|
bytes = "0.5"
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
// <stream>
|
// <stream>
|
||||||
use actix_web::{web, App, HttpServer, Error, HttpResponse};
|
use actix_web::{get, App, Error, HttpResponse, HttpServer};
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use futures::stream::once;
|
|
||||||
use futures::future::ok;
|
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")));
|
let body = once(ok::<_, Error>(Bytes::from_static(b"test")));
|
||||||
|
|
||||||
HttpResponse::Ok()
|
HttpResponse::Ok()
|
||||||
@ -12,10 +13,10 @@ async fn index() -> HttpResponse {
|
|||||||
.streaming(body)
|
.streaming(body)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[actix_rt::main]
|
#[actix_web::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
HttpServer::new(|| App::new().route("/async", web::to(index)))
|
HttpServer::new(|| App::new().service(stream))
|
||||||
.bind("127.0.0.1:8088")?
|
.bind("127.0.0.1:8080")?
|
||||||
.run()
|
.run()
|
||||||
.await
|
.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"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-web = "2.0"
|
actix-web = "3"
|
||||||
actix-rt = "1.0"
|
|
||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
|
@ -18,14 +18,14 @@ async fn register(form: web::Form<Register>) -> impl Responder {
|
|||||||
format!("Hello {} from {}!", form.username, form.country)
|
format!("Hello {} from {}!", form.username, form.country)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[actix_rt::main]
|
#[actix_web::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
HttpServer::new(|| {
|
HttpServer::new(|| {
|
||||||
App::new()
|
App::new()
|
||||||
.route("/", web::get().to(index))
|
.route("/", web::get().to(index))
|
||||||
.route("/register", web::post().to(register))
|
.route("/register", web::post().to(register))
|
||||||
})
|
})
|
||||||
.bind("127.0.0.1:8088")?
|
.bind("127.0.0.1:8080")?
|
||||||
.run()
|
.run()
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
@ -4,5 +4,4 @@ version = "1.0.0"
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-web = "1.0"
|
actix-web = "3"
|
||||||
futures = "0.1"
|
|
||||||
|
@ -3,7 +3,7 @@ use actix_web::{Either, Error, HttpResponse};
|
|||||||
|
|
||||||
type RegisterResult = Either<HttpResponse, Result<&'static str, Error>>;
|
type RegisterResult = Either<HttpResponse, Result<&'static str, Error>>;
|
||||||
|
|
||||||
fn index() -> RegisterResult {
|
async fn index() -> RegisterResult {
|
||||||
if is_a_variant() {
|
if is_a_variant() {
|
||||||
// <- choose variant A
|
// <- choose variant A
|
||||||
Either::A(HttpResponse::BadRequest().body("Bad data"))
|
Either::A(HttpResponse::BadRequest().body("Bad data"))
|
||||||
@ -14,14 +14,14 @@ fn index() -> RegisterResult {
|
|||||||
}
|
}
|
||||||
// </either>
|
// </either>
|
||||||
|
|
||||||
fn main() {
|
#[actix_web::main]
|
||||||
|
async fn main() -> std::io::Result<()> {
|
||||||
use actix_web::{web, App, HttpServer};
|
use actix_web::{web, App, HttpServer};
|
||||||
|
|
||||||
HttpServer::new(|| App::new().route("/", web::get().to(index)))
|
HttpServer::new(|| App::new().route("/", web::get().to(index)))
|
||||||
.bind("127.0.0.1:8088")
|
.bind("127.0.0.1:8080")?
|
||||||
.unwrap()
|
|
||||||
.run()
|
.run()
|
||||||
.unwrap();
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_a_variant() -> bool {
|
fn is_a_variant() -> bool {
|
||||||
|
@ -4,9 +4,8 @@ version = "1.0.0"
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-web = "2.0.0"
|
actix-web = "3"
|
||||||
actix-rt = "1.0.0"
|
derive_more = "0.99"
|
||||||
env_logger = "0.7.1"
|
env_logger = "0.7"
|
||||||
log = "0.4.8"
|
log = "0.4"
|
||||||
failure = "0.1.6"
|
# actix-http = "1"
|
||||||
actix-http = "1.0.1"
|
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
use actix_web::{web, App};
|
|
||||||
// <helpers>
|
// <helpers>
|
||||||
use actix_web::{error, Result};
|
use actix_web::{error, get, App, HttpServer, Result};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct MyError {
|
struct MyError {
|
||||||
name: &'static str,
|
name: &'static str,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[get("/")]
|
||||||
async fn index() -> Result<&'static str> {
|
async fn index() -> Result<&'static str> {
|
||||||
let result: Result<&'static str, MyError> = Err(MyError { name: "test error" });
|
let result: Result<&'static str, MyError> = Err(MyError { name: "test error" });
|
||||||
|
|
||||||
@ -14,12 +14,10 @@ async fn index() -> Result<&'static str> {
|
|||||||
}
|
}
|
||||||
// </helpers>
|
// </helpers>
|
||||||
|
|
||||||
#[actix_rt::main]
|
#[actix_web::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
use actix_web::HttpServer;
|
HttpServer::new(|| App::new().service(index))
|
||||||
|
.bind("127.0.0.1:8080")?
|
||||||
HttpServer::new(|| App::new().route("/", web::get().to(index)))
|
|
||||||
.bind("127.0.0.1:8088")?
|
|
||||||
.run()
|
.run()
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
// <logging>
|
// <logging>
|
||||||
use actix_web::{error, Result};
|
use actix_web::{error, get, middleware::Logger, App, HttpServer, Result};
|
||||||
use failure::Fail;
|
|
||||||
use log::debug;
|
use log::debug;
|
||||||
|
use derive_more::{Display, Error};
|
||||||
|
|
||||||
#[derive(Fail, Debug)]
|
#[derive(Debug, Display, Error)]
|
||||||
#[fail(display = "my error")]
|
#[display(fmt = "my error: {}", name)]
|
||||||
pub struct MyError {
|
pub struct MyError {
|
||||||
name: &'static str,
|
name: &'static str,
|
||||||
}
|
}
|
||||||
@ -12,26 +12,21 @@ pub struct MyError {
|
|||||||
// Use default implementation for `error_response()` method
|
// Use default implementation for `error_response()` method
|
||||||
impl error::ResponseError for MyError {}
|
impl error::ResponseError for MyError {}
|
||||||
|
|
||||||
|
#[get("/")]
|
||||||
async fn index() -> Result<&'static str, MyError> {
|
async fn index() -> Result<&'static str, MyError> {
|
||||||
let err = MyError { name: "test error" };
|
let err = MyError { name: "test error" };
|
||||||
debug!("{}", err);
|
debug!("{}", err);
|
||||||
Err(err)
|
Err(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[actix_rt::main]
|
#[actix_web::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
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_LOG", "my_errors=debug,actix_web=info");
|
||||||
std::env::set_var("RUST_BACKTRACE", "1");
|
std::env::set_var("RUST_BACKTRACE", "1");
|
||||||
env_logger::init();
|
env_logger::init();
|
||||||
|
|
||||||
HttpServer::new(|| {
|
HttpServer::new(|| App::new().wrap(Logger::default()).service(index))
|
||||||
App::new()
|
.bind("127.0.0.1:8080")?
|
||||||
.wrap(Logger::default())
|
|
||||||
.route("/", web::get().to(index))
|
|
||||||
})
|
|
||||||
.bind("127.0.0.1:8088")?
|
|
||||||
.run()
|
.run()
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
@ -6,10 +6,10 @@ pub mod recommend_two;
|
|||||||
|
|
||||||
// <response-error>
|
// <response-error>
|
||||||
use actix_web::{error, Result};
|
use actix_web::{error, Result};
|
||||||
use failure::Fail;
|
use derive_more::{Display, Error};
|
||||||
|
|
||||||
#[derive(Fail, Debug)]
|
#[derive(Debug, Display, Error)]
|
||||||
#[fail(display = "my error")]
|
#[display(fmt = "my error: {}", name)]
|
||||||
struct MyError {
|
struct MyError {
|
||||||
name: &'static str,
|
name: &'static str,
|
||||||
}
|
}
|
||||||
@ -22,12 +22,12 @@ async fn index() -> Result<&'static str, MyError> {
|
|||||||
}
|
}
|
||||||
// </response-error>
|
// </response-error>
|
||||||
|
|
||||||
#[actix_rt::main]
|
#[actix_web::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
use actix_web::{web, App, HttpServer};
|
use actix_web::{web, App, HttpServer};
|
||||||
|
|
||||||
HttpServer::new(|| App::new().route("/", web::get().to(index)))
|
HttpServer::new(|| App::new().route("/", web::get().to(index)))
|
||||||
.bind("127.0.0.1:8088")?
|
.bind("127.0.0.1:8080")?
|
||||||
.run()
|
.run()
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
@ -1,22 +1,24 @@
|
|||||||
use actix_web::{web, App};
|
|
||||||
// <override>
|
// <override>
|
||||||
use actix_http::ResponseBuilder;
|
use actix_web::{
|
||||||
use actix_web::{error, http::header, http::StatusCode, HttpResponse};
|
dev::HttpResponseBuilder, error, get, http::header, http::StatusCode, App, HttpResponse,
|
||||||
use failure::Fail;
|
};
|
||||||
|
use derive_more::{Display, Error};
|
||||||
|
|
||||||
#[derive(Fail, Debug)]
|
#[derive(Debug, Display, Error)]
|
||||||
enum MyError {
|
enum MyError {
|
||||||
#[fail(display = "internal error")]
|
#[display(fmt = "internal error")]
|
||||||
InternalError,
|
InternalError,
|
||||||
#[fail(display = "bad request")]
|
|
||||||
|
#[display(fmt = "bad request")]
|
||||||
BadClientData,
|
BadClientData,
|
||||||
#[fail(display = "timeout")]
|
|
||||||
|
#[display(fmt = "timeout")]
|
||||||
Timeout,
|
Timeout,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl error::ResponseError for MyError {
|
impl error::ResponseError for MyError {
|
||||||
fn error_response(&self) -> HttpResponse {
|
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")
|
.set_header(header::CONTENT_TYPE, "text/html; charset=utf-8")
|
||||||
.body(self.to_string())
|
.body(self.to_string())
|
||||||
}
|
}
|
||||||
@ -30,30 +32,28 @@ impl error::ResponseError for MyError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[get("/")]
|
||||||
async fn index() -> Result<&'static str, MyError> {
|
async fn index() -> Result<&'static str, MyError> {
|
||||||
Err(MyError::BadClientData)
|
Err(MyError::BadClientData)
|
||||||
}
|
}
|
||||||
// </override>
|
// </override>
|
||||||
|
|
||||||
|
#[get("/e2")]
|
||||||
async fn error2() -> Result<&'static str, MyError> {
|
async fn error2() -> Result<&'static str, MyError> {
|
||||||
Err(MyError::InternalError)
|
Err(MyError::InternalError)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[get("/e3")]
|
||||||
async fn error3() -> Result<&'static str, MyError> {
|
async fn error3() -> Result<&'static str, MyError> {
|
||||||
Err(MyError::Timeout)
|
Err(MyError::Timeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[actix_rt::main]
|
#[actix_web::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
use actix_web::HttpServer;
|
use actix_web::HttpServer;
|
||||||
|
|
||||||
HttpServer::new(|| {
|
HttpServer::new(|| App::new().service(index).service(error2).service(error3))
|
||||||
App::new()
|
.bind("127.0.0.1:8080")?
|
||||||
.route("/", web::get().to(index))
|
|
||||||
.route("/e2", web::get().to(error2))
|
|
||||||
.route("/e3", web::get().to(error3))
|
|
||||||
})
|
|
||||||
.bind("127.0.0.1:8088")?
|
|
||||||
.run()
|
.run()
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,19 @@
|
|||||||
// <recommend-one>
|
// <recommend-one>
|
||||||
use actix_http::ResponseBuilder;
|
use actix_web::{
|
||||||
use actix_web::{error, http::header, http::StatusCode, HttpResponse};
|
dev::HttpResponseBuilder, error, get, http::header, http::StatusCode, App, HttpResponse,
|
||||||
use failure::Fail;
|
HttpServer,
|
||||||
|
};
|
||||||
|
use derive_more::{Display, Error};
|
||||||
|
|
||||||
#[derive(Fail, Debug)]
|
#[derive(Debug, Display, Error)]
|
||||||
enum UserError {
|
enum UserError {
|
||||||
#[fail(display = "Validation error on field: {}", field)]
|
#[display(fmt = "Validation error on field: {}", field)]
|
||||||
ValidationError { field: String },
|
ValidationError { field: String },
|
||||||
}
|
}
|
||||||
|
|
||||||
impl error::ResponseError for UserError {
|
impl error::ResponseError for UserError {
|
||||||
fn error_response(&self) -> HttpResponse {
|
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")
|
.set_header(header::CONTENT_TYPE, "text/html; charset=utf-8")
|
||||||
.body(self.to_string())
|
.body(self.to_string())
|
||||||
}
|
}
|
||||||
@ -22,18 +24,18 @@ impl error::ResponseError for UserError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// </recommend-one>
|
// </recommend-one>
|
||||||
|
|
||||||
|
#[get("/")]
|
||||||
async fn index() -> Result<&'static str, UserError> {
|
async fn index() -> Result<&'static str, UserError> {
|
||||||
Err(UserError::ValidationError {
|
Err(UserError::ValidationError {
|
||||||
field: "bad stuff".to_string(),
|
field: "bad stuff".to_string(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[actix_rt::main]
|
#[actix_web::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
use actix_web::{web, App, HttpServer};
|
HttpServer::new(|| App::new().service(index))
|
||||||
|
.bind("127.0.0.1:8080")?
|
||||||
HttpServer::new(|| App::new().route("/", web::get().to(index)))
|
|
||||||
.bind("127.0.0.1:8088")?
|
|
||||||
.run()
|
.run()
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,19 @@
|
|||||||
// <recommend-two>
|
// <recommend-two>
|
||||||
use actix_http::ResponseBuilder;
|
use actix_web::{
|
||||||
use actix_web::{error, http::header, http::StatusCode, HttpResponse};
|
dev::HttpResponseBuilder, error, get, http::header, http::StatusCode, App, HttpResponse,
|
||||||
use failure::Fail;
|
HttpServer,
|
||||||
|
};
|
||||||
|
use derive_more::{Display, Error};
|
||||||
|
|
||||||
#[derive(Fail, Debug)]
|
#[derive(Debug, Display, Error)]
|
||||||
enum UserError {
|
enum UserError {
|
||||||
#[fail(display = "An internal error occurred. Please try again later.")]
|
#[display(fmt = "An internal error occurred. Please try again later.")]
|
||||||
InternalError,
|
InternalError,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl error::ResponseError for UserError {
|
impl error::ResponseError for UserError {
|
||||||
fn error_response(&self) -> HttpResponse {
|
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")
|
.set_header(header::CONTENT_TYPE, "text/html; charset=utf-8")
|
||||||
.body(self.to_string())
|
.body(self.to_string())
|
||||||
}
|
}
|
||||||
@ -22,22 +24,21 @@ impl error::ResponseError for UserError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[get("/")]
|
||||||
async fn index() -> Result<&'static str, UserError> {
|
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!")
|
Ok("success!")
|
||||||
}
|
}
|
||||||
// </recommend-two>
|
// </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"))
|
Err(std::io::Error::new(std::io::ErrorKind::Other, "some error"))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[actix_rt::main]
|
#[actix_web::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
use actix_web::{web, App, HttpServer};
|
HttpServer::new(|| App::new().service(index))
|
||||||
|
.bind("127.0.0.1:8080")?
|
||||||
HttpServer::new(|| App::new().route("/", web::get().to(index)))
|
|
||||||
.bind("127.0.0.1:8088")?
|
|
||||||
.run()
|
.run()
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@ version = "1.0.0"
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-web = "2.0"
|
actix-web = "3"
|
||||||
actix-rt = "1.0"
|
|
||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// <form>
|
// <form>
|
||||||
use actix_web::{web, Result};
|
use actix_web::{post, web, App, HttpServer, Result};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
@ -10,17 +10,16 @@ struct FormData {
|
|||||||
/// extract form data using serde
|
/// extract form data using serde
|
||||||
/// this handler gets called only if the content type is *x-www-form-urlencoded*
|
/// 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
|
/// and the content of the request could be deserialized to a `FormData` struct
|
||||||
|
#[post("/")]
|
||||||
async fn index(form: web::Form<FormData>) -> Result<String> {
|
async fn index(form: web::Form<FormData>) -> Result<String> {
|
||||||
Ok(format!("Welcome {}!", form.username))
|
Ok(format!("Welcome {}!", form.username))
|
||||||
}
|
}
|
||||||
// </form>
|
// </form>
|
||||||
|
|
||||||
#[actix_rt::main]
|
#[actix_web::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
use actix_web::{App, HttpServer};
|
HttpServer::new(|| App::new().service(index))
|
||||||
|
.bind("127.0.0.1:8080")?
|
||||||
HttpServer::new(|| App::new().route("/", web::post().to(index)))
|
|
||||||
.bind("127.0.0.1:8088")?
|
|
||||||
.run()
|
.run()
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// <json-one>
|
// <json-one>
|
||||||
use actix_web::{web, Result};
|
use actix_web::{get, web, App, HttpServer, Result};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
@ -8,17 +8,16 @@ struct Info {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// deserialize `Info` from request's body
|
/// deserialize `Info` from request's body
|
||||||
|
#[get("/")]
|
||||||
async fn index(info: web::Json<Info>) -> Result<String> {
|
async fn index(info: web::Json<Info>) -> Result<String> {
|
||||||
Ok(format!("Welcome {}!", info.username))
|
Ok(format!("Welcome {}!", info.username))
|
||||||
}
|
}
|
||||||
// </json-one>
|
// </json-one>
|
||||||
|
|
||||||
#[actix_rt::main]
|
#[actix_web::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
use actix_web::{App, HttpServer};
|
HttpServer::new(|| App::new().service(index))
|
||||||
|
.bind("127.0.0.1:8080")?
|
||||||
HttpServer::new(|| App::new().route("/", web::post().to(index)))
|
|
||||||
.bind("127.0.0.1:8088")?
|
|
||||||
.run()
|
.run()
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
// <json-two>
|
// <json-two>
|
||||||
use actix_web::{error, web, FromRequest, HttpResponse, Responder};
|
use actix_web::{error, web, App, FromRequest, HttpResponse, HttpServer, Responder};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
@ -12,28 +14,24 @@ async fn index(info: web::Json<Info>) -> impl Responder {
|
|||||||
format!("Welcome {}!", info.username)
|
format!("Welcome {}!", info.username)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[actix_rt::main]
|
#[actix_web::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
use actix_web::{App, HttpServer};
|
|
||||||
|
|
||||||
HttpServer::new(|| {
|
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(
|
App::new().service(
|
||||||
web::resource("/")
|
web::resource("/")
|
||||||
// change json extractor configuration
|
// change json extractor configuration
|
||||||
.app_data(web::Json::<Info>::configure(|cfg| {
|
.app_data(json_config)
|
||||||
cfg.limit(4096).error_handler(|err, _req| {
|
|
||||||
// create custom error response
|
|
||||||
error::InternalError::from_response(
|
|
||||||
err,
|
|
||||||
HttpResponse::Conflict().finish(),
|
|
||||||
)
|
|
||||||
.into()
|
|
||||||
})
|
|
||||||
}))
|
|
||||||
.route(web::post().to(index)),
|
.route(web::post().to(index)),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.bind("127.0.0.1:8088")?
|
.bind("127.0.0.1:8080")?
|
||||||
.run()
|
.run()
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
@ -18,17 +18,18 @@ struct MyInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// <option-one>
|
// <option-one>
|
||||||
async fn index(
|
async fn index(path: web::Path<(String, String)>, json: web::Json<MyInfo>) -> impl Responder {
|
||||||
path: web::Path<(String, String)>,
|
let path = path.into_inner();
|
||||||
json: web::Json<MyInfo>,
|
|
||||||
) -> impl Responder {
|
|
||||||
format!("{} {} {} {}", path.0, path.1, json.id, json.username)
|
format!("{} {} {} {}", path.0, path.1, json.id, json.username)
|
||||||
}
|
}
|
||||||
// </option-one>
|
// </option-one>
|
||||||
|
|
||||||
// <option-two>
|
// <option-two>
|
||||||
async fn extract(req: HttpRequest) -> impl Responder {
|
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)
|
let info = web::Json::<MyInfo>::extract(&req)
|
||||||
.await
|
.await
|
||||||
@ -38,14 +39,14 @@ async fn extract(req: HttpRequest) -> impl Responder {
|
|||||||
}
|
}
|
||||||
// </option-two>
|
// </option-two>
|
||||||
|
|
||||||
#[actix_rt::main]
|
#[actix_web::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
HttpServer::new(|| {
|
HttpServer::new(|| {
|
||||||
App::new()
|
App::new()
|
||||||
.route("/{name}/{id}", web::post().to(index))
|
.route("/{name}/{id}", web::post().to(index))
|
||||||
.route("/{name}/{id}/extract", web::post().to(extract))
|
.route("/{name}/{id}/extract", web::post().to(extract))
|
||||||
})
|
})
|
||||||
.bind("127.0.0.1:8088")?
|
.bind("127.0.0.1:8080")?
|
||||||
.run()
|
.run()
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// <multi>
|
// <multi>
|
||||||
use actix_web::web;
|
use actix_web::{get, web};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
@ -7,26 +7,23 @@ struct Info {
|
|||||||
username: String,
|
username: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[get("/users/{user_id}/{friend}")] // <- define path parameters
|
||||||
async fn index(
|
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 {
|
) -> String {
|
||||||
format!(
|
format!(
|
||||||
"Welcome {}, friend {}, userid {}!",
|
"Welcome {}, friend {}, user_id {}!",
|
||||||
query.username, path.1, path.0
|
query.username, friend, user_id
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[actix_rt::main]
|
#[actix_web::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
use actix_web::{App, HttpServer};
|
use actix_web::{App, HttpServer};
|
||||||
|
|
||||||
HttpServer::new(|| {
|
HttpServer::new(|| App::new().service(index))
|
||||||
App::new().route(
|
.bind("127.0.0.1:8080")?
|
||||||
"/users/{userid}/{friend}", // <- define path parameters
|
|
||||||
web::get().to(index),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.bind("127.0.0.1:8088")?
|
|
||||||
.run()
|
.run()
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
@ -1,24 +1,20 @@
|
|||||||
// <path-one>
|
// <path-one>
|
||||||
use actix_web::{web, Result};
|
use actix_web::{get, web, Result};
|
||||||
|
|
||||||
/// extract path info from "/users/{userid}/{friend}" url
|
/// extract path info from "/users/{user_id}/{friend}" url
|
||||||
/// {userid} - - deserializes to a u32
|
/// {user_id} - deserializes to a u32
|
||||||
/// {friend} - deserializes to a String
|
/// {friend} - deserializes to a String
|
||||||
async fn index(info: web::Path<(u32, String)>) -> Result<String> {
|
#[get("/users/{user_id}/{friend}")] // <- define path parameters
|
||||||
Ok(format!("Welcome {}, userid {}!", info.1, info.0))
|
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<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
use actix_web::{App, HttpServer};
|
use actix_web::{App, HttpServer};
|
||||||
|
|
||||||
HttpServer::new(|| {
|
HttpServer::new(|| App::new().service(index))
|
||||||
App::new().route(
|
.bind("127.0.0.1:8080")?
|
||||||
"/users/{userid}/{friend}", // <- define path parameters
|
|
||||||
web::get().to(index),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.bind("127.0.0.1:8088")?
|
|
||||||
.run()
|
.run()
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
@ -1,25 +1,20 @@
|
|||||||
use actix_web::{web, HttpRequest, Result};
|
use actix_web::{get, HttpRequest, Result};
|
||||||
|
|
||||||
// <path-three>
|
// <path-three>
|
||||||
|
#[get("/users/{userid}/{friend}")] // <- define path parameters
|
||||||
async fn index(req: HttpRequest) -> Result<String> {
|
async fn index(req: HttpRequest) -> Result<String> {
|
||||||
let name: String =
|
let name: String = req.match_info().get("friend").unwrap().parse().unwrap();
|
||||||
req.match_info().get("friend").unwrap().parse().unwrap();
|
|
||||||
let userid: i32 = req.match_info().query("userid").parse().unwrap();
|
let userid: i32 = req.match_info().query("userid").parse().unwrap();
|
||||||
|
|
||||||
Ok(format!("Welcome {}, userid {}!", name, userid))
|
Ok(format!("Welcome {}, userid {}!", name, userid))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[actix_rt::main]
|
#[actix_web::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
use actix_web::{App, HttpServer};
|
use actix_web::{App, HttpServer};
|
||||||
|
|
||||||
HttpServer::new(|| {
|
HttpServer::new(|| App::new().service(index))
|
||||||
App::new().route(
|
.bind("127.0.0.1:8080")?
|
||||||
"/users/{userid}/{friend}", // <- define path parameters
|
|
||||||
web::get().to(index),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.bind("127.0.0.1:8088")?
|
|
||||||
.run()
|
.run()
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
@ -1,29 +1,28 @@
|
|||||||
// <path-two>
|
// <path-two>
|
||||||
use actix_web::{web, Result};
|
use actix_web::{get, web, Result};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
struct Info {
|
struct Info {
|
||||||
userid: u32,
|
user_id: u32,
|
||||||
friend: String,
|
friend: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// extract path info using serde
|
/// extract path info using serde
|
||||||
|
#[get("/users/{user_id}/{friend}")] // <- define path parameters
|
||||||
async fn index(info: web::Path<Info>) -> Result<String> {
|
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<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
use actix_web::{App, HttpServer};
|
use actix_web::{App, HttpServer};
|
||||||
|
|
||||||
HttpServer::new(|| {
|
HttpServer::new(|| App::new().service(index))
|
||||||
App::new().route(
|
.bind("127.0.0.1:8080")?
|
||||||
"/users/{userid}/{friend}", // <- define path parameters
|
|
||||||
web::get().to(index),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.bind("127.0.0.1:8088")?
|
|
||||||
.run()
|
.run()
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// <query>
|
// <query>
|
||||||
use actix_web::web;
|
use actix_web::{get, web, App, HttpServer};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
@ -8,17 +8,16 @@ struct Info {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// this handler get called only if the request's query contains `username` field
|
// this handler get called only if the request's query contains `username` field
|
||||||
|
#[get("/")]
|
||||||
async fn index(info: web::Query<Info>) -> String {
|
async fn index(info: web::Query<Info>) -> String {
|
||||||
format!("Welcome {}!", info.username)
|
format!("Welcome {}!", info.username)
|
||||||
}
|
}
|
||||||
// </query>
|
// </query>
|
||||||
|
|
||||||
#[actix_rt::main]
|
#[actix_web::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
use actix_web::{App, HttpServer};
|
HttpServer::new(|| App::new().service(index))
|
||||||
|
.bind("127.0.0.1:8080")?
|
||||||
HttpServer::new(|| App::new().route("/", web::get().to(index)))
|
|
||||||
.bind("127.0.0.1:8088")?
|
|
||||||
.run()
|
.run()
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,5 @@ version = "1.0.0"
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-web = "2.0"
|
actix-web = "3"
|
||||||
actix-rt = "1.0"
|
|
||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
|
@ -15,14 +15,14 @@ async fn current_temperature() -> impl Responder {
|
|||||||
web::Json(Measurement { temperature: 42.3 })
|
web::Json(Measurement { temperature: 42.3 })
|
||||||
}
|
}
|
||||||
|
|
||||||
#[actix_rt::main]
|
#[actix_web::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
HttpServer::new(|| {
|
HttpServer::new(|| {
|
||||||
App::new()
|
App::new()
|
||||||
.service(web::resource("/").to(hello_world))
|
.service(web::resource("/").to(hello_world))
|
||||||
.service(web::resource("/temp").to(current_temperature))
|
.service(web::resource("/temp").to(current_temperature))
|
||||||
})
|
})
|
||||||
.bind("127.0.0.1:8088")?
|
.bind("127.0.0.1:8080")?
|
||||||
.run()
|
.run()
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
@ -5,5 +5,4 @@ edition = "2018"
|
|||||||
workspace = "../"
|
workspace = "../"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-web = "2.0"
|
actix-web = "3"
|
||||||
actix-rt = "1.0.0"
|
|
||||||
|
@ -1,33 +1,31 @@
|
|||||||
// <setup>
|
// <handlers>
|
||||||
use actix_web::{web, App, HttpResponse, HttpServer, Responder};
|
use actix_web::{get, post, web, App, HttpResponse, HttpServer, Responder};
|
||||||
|
|
||||||
async fn index() -> impl Responder {
|
#[get("/")]
|
||||||
|
async fn hello() -> impl Responder {
|
||||||
HttpResponse::Ok().body("Hello world!")
|
HttpResponse::Ok().body("Hello world!")
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn index2() -> impl Responder {
|
#[post("/echo")]
|
||||||
HttpResponse::Ok().body("Hello world again!")
|
async fn echo(req_body: String) -> impl Responder {
|
||||||
|
HttpResponse::Ok().body(req_body)
|
||||||
}
|
}
|
||||||
// </setup>
|
|
||||||
|
|
||||||
// <macro-attributes>
|
async fn manual_hello() -> impl Responder {
|
||||||
use actix_web::get;
|
|
||||||
|
|
||||||
#[get("/hello")]
|
|
||||||
async fn index3() -> impl Responder {
|
|
||||||
HttpResponse::Ok().body("Hey there!")
|
HttpResponse::Ok().body("Hey there!")
|
||||||
}
|
}
|
||||||
// </macro-attributes>
|
// </handlers>
|
||||||
|
|
||||||
// <main>
|
// <main>
|
||||||
#[actix_rt::main]
|
#[actix_web::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
HttpServer::new(|| {
|
HttpServer::new(|| {
|
||||||
App::new()
|
App::new()
|
||||||
.route("/", web::get().to(index))
|
.service(hello)
|
||||||
.route("/again", web::get().to(index2))
|
.service(echo)
|
||||||
|
.route("/hey", web::get().to(manual_hello))
|
||||||
})
|
})
|
||||||
.bind("127.0.0.1:8088")?
|
.bind("127.0.0.1:8080")?
|
||||||
.run()
|
.run()
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,5 @@ version = "1.0.0"
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-web = { version = "2.0", features = ["openssl"] }
|
actix-web = { version = "3", features = ["openssl"] }
|
||||||
actix-rt = "1.0"
|
|
||||||
openssl = { version = "0.10", features = ["v110"] }
|
openssl = { version = "0.10", features = ["v110"] }
|
||||||
|
@ -6,7 +6,7 @@ async fn index(_req: HttpRequest) -> impl Responder {
|
|||||||
"Hello."
|
"Hello."
|
||||||
}
|
}
|
||||||
|
|
||||||
#[actix_rt::main]
|
#[actix_web::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
// load ssl keys
|
// load ssl keys
|
||||||
// to create a self-signed temporary cert for testing:
|
// 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();
|
builder.set_certificate_chain_file("cert.pem").unwrap();
|
||||||
|
|
||||||
HttpServer::new(|| App::new().route("/", web::get().to(index)))
|
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()
|
.run()
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
@ -4,5 +4,4 @@ version = "1.0.0"
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-web = "2.0"
|
actix-web = "3"
|
||||||
actix-rt = "1.0"
|
|
||||||
|
@ -6,14 +6,14 @@ async fn greet(req: HttpRequest) -> impl Responder {
|
|||||||
format!("Hello {}!", &name)
|
format!("Hello {}!", &name)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[actix_rt::main]
|
#[actix_web::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
HttpServer::new(|| {
|
HttpServer::new(|| {
|
||||||
App::new()
|
App::new()
|
||||||
.route("/", web::get().to(greet))
|
.route("/", web::get().to(greet))
|
||||||
.route("/{name}", web::get().to(greet))
|
.route("/{name}", web::get().to(greet))
|
||||||
})
|
})
|
||||||
.bind("127.0.0.1:8088")?
|
.bind("127.0.0.1:8080")?
|
||||||
.run()
|
.run()
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
@ -4,9 +4,8 @@ version = "1.0.0"
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-web = "2.0"
|
actix-web = "3"
|
||||||
actix-rt = "1.0"
|
actix-service = "1"
|
||||||
actix-service = "1.0"
|
actix-session = "0.4"
|
||||||
actix-session = "0.3"
|
futures = "0.3"
|
||||||
futures = "0.3.1"
|
env_logger = "0.7"
|
||||||
env_logger = "0.6"
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// <default-headers>
|
// <default-headers>
|
||||||
use actix_web::{http, middleware, HttpResponse};
|
use actix_web::{http, middleware, HttpResponse};
|
||||||
|
|
||||||
#[actix_rt::main]
|
#[actix_web::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
use actix_web::{web, App, HttpServer};
|
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()
|
.run()
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
// <error-handler>
|
// <error-handler>
|
||||||
use actix_web::middleware::errhandlers::{ErrorHandlerResponse, ErrorHandlers};
|
use actix_web::middleware::errhandlers::{ErrorHandlerResponse, ErrorHandlers};
|
||||||
use actix_web::{dev, http, HttpResponse, Result};
|
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))
|
Ok(ErrorHandlerResponse::Response(res))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[actix_rt::main]
|
#[actix_web::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
use actix_web::{web, App, HttpServer};
|
use actix_web::{web, App, HttpServer};
|
||||||
|
|
||||||
@ -26,7 +28,7 @@ async fn main() -> std::io::Result<()> {
|
|||||||
.route(web::head().to(|| HttpResponse::MethodNotAllowed())),
|
.route(web::head().to(|| HttpResponse::MethodNotAllowed())),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.bind("127.0.0.1:8088")?
|
.bind("127.0.0.1:8080")?
|
||||||
.run()
|
.run()
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
use actix_web::middleware::Logger;
|
use actix_web::middleware::Logger;
|
||||||
use env_logger::Env;
|
use env_logger::Env;
|
||||||
|
|
||||||
#[actix_rt::main]
|
#[actix_web::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
use actix_web::{App, HttpServer};
|
use actix_web::{App, HttpServer};
|
||||||
|
|
||||||
@ -13,7 +13,7 @@ async fn main() -> std::io::Result<()> {
|
|||||||
.wrap(Logger::default())
|
.wrap(Logger::default())
|
||||||
.wrap(Logger::new("%a %{User-Agent}i"))
|
.wrap(Logger::new("%a %{User-Agent}i"))
|
||||||
})
|
})
|
||||||
.bind("127.0.0.1:8088")?
|
.bind("127.0.0.1:8080")?
|
||||||
.run()
|
.run()
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
@ -74,7 +74,7 @@ where
|
|||||||
}
|
}
|
||||||
// </simple>
|
// </simple>
|
||||||
|
|
||||||
#[actix_rt::main]
|
#[actix_web::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
use actix_web::{web, App, HttpServer};
|
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()
|
.run()
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
// <user-session>
|
// <user-session>
|
||||||
use actix_session::{CookieSession, Session};
|
use actix_session::{CookieSession, Session};
|
||||||
use actix_web::{web, App, Error, HttpResponse, HttpServer};
|
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<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
HttpServer::new(|| {
|
HttpServer::new(|| {
|
||||||
App::new()
|
App::new()
|
||||||
@ -26,7 +28,7 @@ async fn main() -> std::io::Result<()> {
|
|||||||
)
|
)
|
||||||
.service(web::resource("/").to(index))
|
.service(web::resource("/").to(index))
|
||||||
})
|
})
|
||||||
.bind("127.0.0.1:8088")?
|
.bind("127.0.0.1:8080")?
|
||||||
.run()
|
.run()
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
|
#![allow(dead_code, unused_variables)]
|
||||||
|
|
||||||
// <wrap-fn>
|
// <wrap-fn>
|
||||||
use actix_service::Service;
|
use actix_service::Service;
|
||||||
use actix_web::{web, App};
|
use actix_web::{web, App};
|
||||||
use futures::future::FutureExt;
|
use futures::future::FutureExt;
|
||||||
|
|
||||||
#[actix_rt::main]
|
#[actix_web::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
let app = App::new()
|
let app = App::new()
|
||||||
.wrap_fn(|req, srv| {
|
.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"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-web = "2.0"
|
actix-web = "3"
|
||||||
actix-rt = "1.0"
|
|
||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
|
@ -31,14 +31,14 @@ async fn index() -> HttpResponse {
|
|||||||
.body(include_str!("../static/form.html"))
|
.body(include_str!("../static/form.html"))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[actix_rt::main]
|
#[actix_web::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
HttpServer::new(|| {
|
HttpServer::new(|| {
|
||||||
App::new()
|
App::new()
|
||||||
.route("/", web::get().to(index))
|
.route("/", web::get().to(index))
|
||||||
.route("/event", web::post().to(capture_event))
|
.route("/event", web::post().to(capture_event))
|
||||||
})
|
})
|
||||||
.bind("127.0.0.1:8088")?
|
.bind("127.0.0.1:8080")?
|
||||||
.run()
|
.run()
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function submitJson() {
|
function submitJson() {
|
||||||
fetch('http://localhost:8088/event', {
|
fetch('http://localhost:8080/event', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Accept': 'application/json',
|
'Accept': 'application/json',
|
||||||
|
@ -4,5 +4,4 @@ version = "1.0.0"
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-web = "2.0"
|
actix-web = "3"
|
||||||
actix-rt = "1.0"
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// <arc>
|
// <arc>
|
||||||
use actix_web::{web, Responder};
|
use actix_web::{get, web, App, HttpServer, Responder};
|
||||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
@ -8,20 +8,20 @@ struct AppState {
|
|||||||
count: Arc<AtomicUsize>,
|
count: Arc<AtomicUsize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[get("/")]
|
||||||
async fn show_count(data: web::Data<AppState>) -> impl Responder {
|
async fn show_count(data: web::Data<AppState>) -> impl Responder {
|
||||||
format!("count: {}", data.count.load(Ordering::Relaxed))
|
format!("count: {}", data.count.load(Ordering::Relaxed))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[get("/add")]
|
||||||
async fn add_one(data: web::Data<AppState>) -> impl Responder {
|
async fn add_one(data: web::Data<AppState>) -> impl Responder {
|
||||||
data.count.fetch_add(1, Ordering::Relaxed);
|
data.count.fetch_add(1, Ordering::Relaxed);
|
||||||
|
|
||||||
format!("count: {}", data.count.load(Ordering::Relaxed))
|
format!("count: {}", data.count.load(Ordering::Relaxed))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[actix_rt::main]
|
#[actix_web::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
use actix_web::{App, HttpServer};
|
|
||||||
|
|
||||||
let data = AppState {
|
let data = AppState {
|
||||||
count: Arc::new(AtomicUsize::new(0)),
|
count: Arc::new(AtomicUsize::new(0)),
|
||||||
};
|
};
|
||||||
@ -29,10 +29,10 @@ async fn main() -> std::io::Result<()> {
|
|||||||
HttpServer::new(move || {
|
HttpServer::new(move || {
|
||||||
App::new()
|
App::new()
|
||||||
.data(data.clone())
|
.data(data.clone())
|
||||||
.route("/", web::to(show_count))
|
.service(show_count)
|
||||||
.route("/add", web::to(add_one))
|
.service(add_one)
|
||||||
})
|
})
|
||||||
.bind("127.0.0.1:8088")?
|
.bind("127.0.0.1:8080")?
|
||||||
.run()
|
.run()
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ async fn add_one(data: web::Data<AppState>) -> impl Responder {
|
|||||||
format!("count: {}", data.count.get())
|
format!("count: {}", data.count.get())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[actix_rt::main]
|
#[actix_web::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
use actix_web::{App, HttpServer};
|
use actix_web::{App, HttpServer};
|
||||||
|
|
||||||
@ -33,7 +33,7 @@ async fn main() -> std::io::Result<()> {
|
|||||||
.route("/", web::to(show_count))
|
.route("/", web::to(show_count))
|
||||||
.route("/add", web::to(add_one))
|
.route("/add", web::to(add_one))
|
||||||
})
|
})
|
||||||
.bind("127.0.0.1:8088")?
|
.bind("127.0.0.1:8080")?
|
||||||
.run()
|
.run()
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
@ -4,5 +4,4 @@ version = "1.0.0"
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-web = "2.0"
|
actix-web = "3"
|
||||||
actix-rt = "1.0"
|
|
||||||
|
@ -9,14 +9,14 @@ async fn hello(path: web::Path<String>) -> impl Responder {
|
|||||||
format!("Hello {}!", &path)
|
format!("Hello {}!", &path)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[actix_rt::main]
|
#[actix_web::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
HttpServer::new(|| {
|
HttpServer::new(|| {
|
||||||
App::new()
|
App::new()
|
||||||
.service(web::resource("/").to(index))
|
.service(web::resource("/").to(index))
|
||||||
.service(web::resource("/{name}").to(hello))
|
.service(web::resource("/{name}").to(hello))
|
||||||
})
|
})
|
||||||
.bind("127.0.0.1:8088")?
|
.bind("127.0.0.1:8080")?
|
||||||
.run()
|
.run()
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
@ -6,8 +6,6 @@ edition = "2018"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
actix-web = "2.0"
|
actix-web = "3"
|
||||||
actix-rt = "1.0"
|
|
||||||
futures = "0.3.1"
|
futures = "0.3.1"
|
||||||
bytes = "0.4"
|
actix-multipart = "0.3"
|
||||||
actix-multipart = "0.2"
|
|
||||||
|
@ -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 manual;
|
||||||
pub mod multipart;
|
pub mod multipart;
|
||||||
pub mod streaming;
|
pub mod streaming;
|
||||||
@ -18,10 +17,10 @@ async fn index(info: web::Json<Info>) -> Result<String> {
|
|||||||
Ok(format!("Welcome {}!", info.username))
|
Ok(format!("Welcome {}!", info.username))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[actix_rt::main]
|
#[actix_web::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
HttpServer::new(|| App::new().route("/", web::post().to(index)))
|
HttpServer::new(|| App::new().route("/", web::post().to(index)))
|
||||||
.bind("127.0.0.1:8088")?
|
.bind("127.0.0.1:8080")?
|
||||||
.run()
|
.run()
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
// <json-manual>
|
// <json-manual>
|
||||||
use actix_web::{error, web, App, Error, HttpResponse};
|
use actix_web::{error, post, web, App, Error, HttpResponse};
|
||||||
use bytes::BytesMut;
|
|
||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_json;
|
use serde_json;
|
||||||
@ -13,9 +12,10 @@ struct MyObj {
|
|||||||
|
|
||||||
const MAX_SIZE: usize = 262_144; // max payload size is 256k
|
const MAX_SIZE: usize = 262_144; // max payload size is 256k
|
||||||
|
|
||||||
|
#[post("/")]
|
||||||
async fn index_manual(mut payload: web::Payload) -> Result<HttpResponse, Error> {
|
async fn index_manual(mut payload: web::Payload) -> Result<HttpResponse, Error> {
|
||||||
// payload is a stream of Bytes objects
|
// 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 {
|
while let Some(chunk) = payload.next().await {
|
||||||
let chunk = chunk?;
|
let chunk = chunk?;
|
||||||
// limit max size of in-memory payload
|
// limit max size of in-memory payload
|
||||||
@ -31,12 +31,12 @@ async fn index_manual(mut payload: web::Payload) -> Result<HttpResponse, Error>
|
|||||||
}
|
}
|
||||||
// </json-manual>
|
// </json-manual>
|
||||||
|
|
||||||
#[actix_rt::main]
|
#[actix_web::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
use actix_web::HttpServer;
|
use actix_web::HttpServer;
|
||||||
|
|
||||||
HttpServer::new(|| App::new().route("/", web::post().to(index_manual)))
|
HttpServer::new(|| App::new().service(index_manual))
|
||||||
.bind("127.0.0.1:8088")?
|
.bind("127.0.0.1:8080")?
|
||||||
.run()
|
.run()
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
// <streaming>
|
// <streaming>
|
||||||
use actix_web::{web, Error, HttpResponse};
|
use actix_web::{get, web, Error, HttpResponse};
|
||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
|
|
||||||
|
#[get("/")]
|
||||||
async fn index(mut body: web::Payload) -> Result<HttpResponse, Error> {
|
async fn index(mut body: web::Payload) -> Result<HttpResponse, Error> {
|
||||||
let mut bytes = web::BytesMut::new();
|
let mut bytes = web::BytesMut::new();
|
||||||
while let Some(item) = body.next().await {
|
while let Some(item) = body.next().await {
|
||||||
@ -14,12 +15,12 @@ async fn index(mut body: web::Payload) -> Result<HttpResponse, Error> {
|
|||||||
}
|
}
|
||||||
// </streaming>
|
// </streaming>
|
||||||
|
|
||||||
#[actix_rt::main]
|
#[actix_web::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
use actix_web::{App, HttpServer};
|
use actix_web::{App, HttpServer};
|
||||||
|
|
||||||
HttpServer::new(|| App::new().route("/", web::post().to(index)))
|
HttpServer::new(|| App::new().service(index))
|
||||||
.bind("127.0.0.1:8088")?
|
.bind("127.0.0.1:8080")?
|
||||||
.run()
|
.run()
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// <urlencoded>
|
// <urlencoded>
|
||||||
use actix_web::{web, HttpResponse};
|
use actix_web::{post, web, HttpResponse};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
@ -7,17 +7,18 @@ struct FormData {
|
|||||||
username: String,
|
username: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[post("/")]
|
||||||
async fn index(form: web::Form<FormData>) -> HttpResponse {
|
async fn index(form: web::Form<FormData>) -> HttpResponse {
|
||||||
HttpResponse::Ok().body(format!("username: {}", form.username))
|
HttpResponse::Ok().body(format!("username: {}", form.username))
|
||||||
}
|
}
|
||||||
// </urlencoded>
|
// </urlencoded>
|
||||||
|
|
||||||
#[actix_rt::main]
|
#[actix_web::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
use actix_web::{App, HttpServer};
|
use actix_web::{App, HttpServer};
|
||||||
|
|
||||||
HttpServer::new(|| App::new().route("/", web::post().to(index)))
|
HttpServer::new(|| App::new().service(index))
|
||||||
.bind("127.0.0.1:8088")?
|
.bind("127.0.0.1:8080")?
|
||||||
.run()
|
.run()
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,7 @@ version = "1.0.0"
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-web = "2.0"
|
actix-web = "3"
|
||||||
actix-rt = "1.0"
|
|
||||||
futures = "0.3.1"
|
futures = "0.3.1"
|
||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
|
@ -28,12 +28,12 @@ async fn index() -> impl Responder {
|
|||||||
}
|
}
|
||||||
// </responder-trait>
|
// </responder-trait>
|
||||||
|
|
||||||
#[actix_rt::main]
|
#[actix_web::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
use actix_web::{web, App, HttpServer};
|
use actix_web::{web, App, HttpServer};
|
||||||
|
|
||||||
HttpServer::new(|| App::new().route("/", web::get().to(index)))
|
HttpServer::new(|| App::new().route("/", web::get().to(index)))
|
||||||
.bind("127.0.0.1:8088")?
|
.bind("127.0.0.1:8080")?
|
||||||
.run()
|
.run()
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,7 @@ version = "1.0.0"
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-web = "2.0"
|
actix-web = "3"
|
||||||
actix-rt = "1.0"
|
|
||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
futures = "0.3.1"
|
futures = "0.3.1"
|
||||||
bytes = "0.5"
|
bytes = "0.5"
|
||||||
|
@ -1,20 +1,19 @@
|
|||||||
// <auto>
|
// <auto>
|
||||||
use actix_web::{http::ContentEncoding, middleware, HttpResponse};
|
use actix_web::{get, http::ContentEncoding, middleware, App, HttpResponse, HttpServer};
|
||||||
|
|
||||||
|
#[get("/")]
|
||||||
async fn index() -> HttpResponse {
|
async fn index() -> HttpResponse {
|
||||||
HttpResponse::Ok().body("data")
|
HttpResponse::Ok().body("data")
|
||||||
}
|
}
|
||||||
|
|
||||||
#[actix_rt::main]
|
#[actix_web::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
use actix_web::{web, App, HttpServer};
|
|
||||||
|
|
||||||
HttpServer::new(|| {
|
HttpServer::new(|| {
|
||||||
App::new()
|
App::new()
|
||||||
.wrap(middleware::Compress::new(ContentEncoding::Br))
|
.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()
|
.run()
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
@ -1,22 +1,23 @@
|
|||||||
// <brotli>
|
// <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 {
|
async fn index_br() -> HttpResponse {
|
||||||
HttpResponse::Ok()
|
HttpResponse::Ok()
|
||||||
.encoding(ContentEncoding::Br)
|
.encoding(ContentEncoding::Br)
|
||||||
.body("data")
|
.body("data")
|
||||||
}
|
}
|
||||||
|
|
||||||
#[actix_rt::main]
|
#[actix_web::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
use actix_web::{middleware, web, App, HttpServer};
|
|
||||||
|
|
||||||
HttpServer::new(|| {
|
HttpServer::new(|| {
|
||||||
App::new()
|
App::new()
|
||||||
.wrap(middleware::Compress::default())
|
.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()
|
.run()
|
||||||
.await
|
.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