mirror of
https://github.com/actix/actix-extras.git
synced 2024-11-24 07:53:00 +01:00
Merge pull request #163 from memoryruins/guide
Guide: edits to the second half
This commit is contained in:
commit
602d78b76c
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
## Install Rust
|
## Install Rust
|
||||||
|
|
||||||
Before we begin, we need to install Rust using the [rustup](https://www.rustup.rs/):
|
Before we begin, we need to install Rust using [rustup](https://www.rustup.rs/):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl https://sh.rustup.rs -sSf | sh
|
curl https://sh.rustup.rs -sSf | sh
|
||||||
|
@ -1,23 +1,25 @@
|
|||||||
# Middleware
|
# Middleware
|
||||||
|
|
||||||
Actix' middleware system allows to add additional behavior to request/response processing.
|
Actix's middleware system allows us to add additional behavior to request/response processing.
|
||||||
Middleware can hook into incoming request process and modify request or halt request
|
Middleware can hook into an incoming request process, enabling us to modify requests
|
||||||
processing and return response early. Also it can hook into response processing.
|
as well as halt request processing to return a response early.
|
||||||
|
|
||||||
Typically middlewares are involved in the following actions:
|
Middleware can also hook into response processing.
|
||||||
|
|
||||||
|
Typically, middleware is involved in the following actions:
|
||||||
|
|
||||||
* Pre-process the Request
|
* Pre-process the Request
|
||||||
* Post-process a Response
|
* Post-process a Response
|
||||||
* Modify application state
|
* Modify application state
|
||||||
* Access external services (redis, logging, sessions)
|
* Access external services (redis, logging, sessions)
|
||||||
|
|
||||||
Middlewares are registered for each application and are executed in same order as
|
Middleware is registered for each application and executed in same order as
|
||||||
registration order. In general, a *middleware* is a type that implements the
|
registration. In general, a *middleware* is a type that implements the
|
||||||
[*Middleware trait*](../actix_web/middlewares/trait.Middleware.html). Each method
|
[*Middleware trait*](../actix_web/middlewares/trait.Middleware.html). Each method
|
||||||
in this trait has a default implementation. Each method can return a result immediately
|
in this trait has a default implementation. Each method can return a result immediately
|
||||||
or a *future* object.
|
or a *future* object.
|
||||||
|
|
||||||
Here is an example of a simple middleware that adds request and response headers:
|
The following demonstrates using middleware to add request and response headers:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
# extern crate http;
|
# extern crate http;
|
||||||
@ -57,16 +59,17 @@ fn main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Actix provides several useful middlewares, like *logging*, *user sessions*, etc.
|
> Actix provides several useful middlewares, such as *logging*, *user sessions*, etc.
|
||||||
|
|
||||||
|
|
||||||
## Logging
|
## Logging
|
||||||
|
|
||||||
Logging is implemented as a middleware.
|
Logging is implemented as a middleware.
|
||||||
It is common to register a logging middleware as the first middleware for the application.
|
It is common to register a logging middleware as the first middleware for the application.
|
||||||
Logging middleware has to be registered for each application. *Logger* middleware
|
Logging middleware must be registered for each application.
|
||||||
uses the standard log crate to log information. You should enable logger for *actix_web*
|
|
||||||
package to see access log ([env_logger](https://docs.rs/env_logger/*/env_logger/) or similar).
|
The `Logger` middleware uses the standard log crate to log information. You should enable logger
|
||||||
|
for *actix_web* package to see access log ([env_logger](https://docs.rs/env_logger/*/env_logger/)
|
||||||
|
or similar).
|
||||||
|
|
||||||
### Usage
|
### Usage
|
||||||
|
|
||||||
@ -76,6 +79,7 @@ Default `Logger` can be created with `default` method, it uses the default forma
|
|||||||
```ignore
|
```ignore
|
||||||
%a %t "%r" %s %b "%{Referer}i" "%{User-Agent}i" %T
|
%a %t "%r" %s %b "%{Referer}i" "%{User-Agent}i" %T
|
||||||
```
|
```
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
# extern crate actix_web;
|
# extern crate actix_web;
|
||||||
extern crate env_logger;
|
extern crate env_logger;
|
||||||
@ -93,7 +97,7 @@ fn main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Here is an example of the default logging format:
|
The following is an example of the default logging format:
|
||||||
|
|
||||||
```
|
```
|
||||||
INFO:actix_web::middleware::logger: 127.0.0.1:59934 [02/Dec/2017:00:21:43 -0800] "GET / HTTP/1.1" 302 0 "-" "curl/7.54.0" 0.000397
|
INFO:actix_web::middleware::logger: 127.0.0.1:59934 [02/Dec/2017:00:21:43 -0800] "GET / HTTP/1.1" 302 0 "-" "curl/7.54.0" 0.000397
|
||||||
@ -126,12 +130,11 @@ INFO:actix_web::middleware::logger: 127.0.0.1:59947 [02/Dec/2017:00:22:40 -0800]
|
|||||||
|
|
||||||
`%{FOO}e` os.environ['FOO']
|
`%{FOO}e` os.environ['FOO']
|
||||||
|
|
||||||
|
|
||||||
## Default headers
|
## Default headers
|
||||||
|
|
||||||
To set default response headers the `DefaultHeaders` middleware can be used. The
|
To set default response headers, the `DefaultHeaders` middleware can be used. The
|
||||||
*DefaultHeaders* middleware does not set the header if response headers already contain
|
*DefaultHeaders* middleware does not set the header if response headers already contain
|
||||||
the specified header.
|
a specified header.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
# extern crate actix_web;
|
# extern crate actix_web;
|
||||||
@ -153,27 +156,28 @@ fn main() {
|
|||||||
## User sessions
|
## User sessions
|
||||||
|
|
||||||
Actix provides a general solution for session management. The
|
Actix provides a general solution for session management. The
|
||||||
[*Session storage*](../actix_web/middleware/struct.SessionStorage.html) middleware can be
|
[**SessionStorage**](../actix_web/middleware/struct.SessionStorage.html) middleware can be
|
||||||
used with different backend types to store session data in different backends.
|
used with different backend types to store session data in different backends.
|
||||||
By default only cookie session backend is implemented. Other backend implementations
|
|
||||||
could be added later.
|
|
||||||
|
|
||||||
[*Cookie session backend*](../actix_web/middleware/struct.CookieSessionBackend.html)
|
> By default, only cookie session backend is implemented. Other backend implementations
|
||||||
uses signed cookies as session storage. *Cookie session backend* creates sessions which
|
> can be added.
|
||||||
are limited to storing fewer than 4000 bytes of data (as the payload must fit into a
|
|
||||||
single cookie). Internal server error is generated if session contains more than 4000 bytes.
|
|
||||||
|
|
||||||
You need to pass a random value to the constructor of *CookieSessionBackend*.
|
[**CookieSessionBackend**](../actix_web/middleware/struct.CookieSessionBackend.html)
|
||||||
This is private key for cookie session. When this value is changed, all session data is lost.
|
uses signed cookies as session storage. `CookieSessionBackend` creates sessions which
|
||||||
Note that whatever you write into your session is visible by the user (but not modifiable).
|
are limited to storing fewer than 4000 bytes of data, as the payload must fit into a
|
||||||
|
single cookie. An internal server error is generated if a session contains more than 4000 bytes.
|
||||||
|
|
||||||
In general case, you create
|
You need to pass a random value to the constructor of `CookieSessionBackend`.
|
||||||
[*Session storage*](../actix_web/middleware/struct.SessionStorage.html) middleware
|
This is a private key for cookie session. When this value is changed, all session data is lost.
|
||||||
and initializes it with specific backend implementation, like *CookieSessionBackend*.
|
|
||||||
To access session data
|
> **Note**: anything you write into the session is visible by the user, but it is not modifiable.
|
||||||
|
|
||||||
|
In general, you create a
|
||||||
|
`SessionStorage` middleware and initialize it with specific backend implementation,
|
||||||
|
such as a `CookieSessionBackend`. To access session data,
|
||||||
[*HttpRequest::session()*](../actix_web/middleware/trait.RequestSession.html#tymethod.session)
|
[*HttpRequest::session()*](../actix_web/middleware/trait.RequestSession.html#tymethod.session)
|
||||||
has to be used. This method returns a
|
must be used. This method returns a
|
||||||
[*Session*](../actix_web/middleware/struct.Session.html) object, which allows to get or set
|
[*Session*](../actix_web/middleware/struct.Session.html) object, which allows us to get or set
|
||||||
session data.
|
session data.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
@ -212,12 +216,12 @@ fn main() {
|
|||||||
|
|
||||||
## Error handlers
|
## Error handlers
|
||||||
|
|
||||||
`ErrorHandlers` middleware allows to provide custom handlers for responses.
|
`ErrorHandlers` middleware allows us to provide custom handlers for responses.
|
||||||
|
|
||||||
You can use `ErrorHandlers::handler()` method to register a custom error handler
|
You can use the `ErrorHandlers::handler()` method to register a custom error handler
|
||||||
for specific status code. You can modify existing response or create completly new
|
for a specific status code. You can modify an existing response or create a completly new
|
||||||
one. Error handler can return response immediately or return future that resolves
|
one. The error handler can return a response immediately or return a future that resolves
|
||||||
to a response.
|
into a response.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
# extern crate actix_web;
|
# extern crate actix_web;
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
## Individual file
|
## Individual file
|
||||||
|
|
||||||
It is possible to serve static files with custom path pattern and `NamedFile`. To
|
It is possible to serve static files with a custom path pattern and `NamedFile`. To
|
||||||
match path tail we can use `[.*]` regex.
|
match a path tail, we can use a `[.*]` regex.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
# extern crate actix_web;
|
# extern crate actix_web;
|
||||||
@ -24,9 +24,9 @@ fn main() {
|
|||||||
|
|
||||||
## Directory
|
## Directory
|
||||||
|
|
||||||
To serve files from specific directory and sub-directories `StaticFiles` could be used.
|
To serve files from specific directories and sub-directories, `StaticFiles` can be used.
|
||||||
`StaticFiles` must be registered with `App::handler()` method otherwise
|
`StaticFiles` must be registered with an `App::handler()` method, otherwise
|
||||||
it won't be able to serve sub-paths.
|
it will be unable to serve sub-paths.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
# extern crate actix_web;
|
# extern crate actix_web;
|
||||||
@ -39,11 +39,11 @@ fn main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
First parameter is a base directory. Second parameter is *show_index*, if it is set to *true*
|
The first parameter is the base directory. If the second parameter, *show_index*, is set to **true**,
|
||||||
directory listing would be returned for directories, if it is set to *false*
|
the directory listing will be returned, and if it is set to **false**,
|
||||||
then *404 Not Found* would be returned instead of directory listing.
|
*404 Not Found* will be returned.
|
||||||
|
|
||||||
Instead of showing files listing for directory, it is possible to redirect to specific
|
Instead of showing files listing for directory, it is possible to redirect to a specific
|
||||||
index file. Use
|
index file. Use the
|
||||||
[*StaticFiles::index_file()*](../actix_web/s/struct.StaticFiles.html#method.index_file)
|
[*StaticFiles::index_file()*](../actix_web/s/struct.StaticFiles.html#method.index_file)
|
||||||
method to configure this redirect.
|
method to configure this redirect.
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
# HTTP/2.0
|
# HTTP/2.0
|
||||||
|
|
||||||
Actix web automatically upgrades connection to *HTTP/2.0* if possible.
|
Actix web automatically upgrades connections to *HTTP/2.0* if possible.
|
||||||
|
|
||||||
## Negotiation
|
## Negotiation
|
||||||
|
|
||||||
*HTTP/2.0* protocol over tls without prior knowledge requires
|
*HTTP/2.0* protocol over tls without prior knowledge requires
|
||||||
[tls alpn](https://tools.ietf.org/html/rfc7301). At the moment only
|
[tls alpn](https://tools.ietf.org/html/rfc7301).
|
||||||
`rust-openssl` has support. Turn on the `alpn` feature to enable `alpn` negotiation.
|
|
||||||
With enabled `alpn` feature `HttpServer` provides the
|
> Currently, only `rust-openssl` has support.
|
||||||
|
|
||||||
|
`alpn` negotiation requires enabling the feature. When enabled, `HttpServer` provides the
|
||||||
[serve_tls](../actix_web/struct.HttpServer.html#method.serve_tls) method.
|
[serve_tls](../actix_web/struct.HttpServer.html#method.serve_tls) method.
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
@ -35,10 +37,10 @@ fn main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Upgrade to *HTTP/2.0* schema described in
|
Upgrades to *HTTP/2.0* schema described in
|
||||||
[rfc section 3.2](https://http2.github.io/http2-spec/#rfc.section.3.2) is not supported.
|
[rfc section 3.2](https://http2.github.io/http2-spec/#rfc.section.3.2) is not supported.
|
||||||
Starting *HTTP/2* with prior knowledge is supported for both clear text connection
|
Starting *HTTP/2* with prior knowledge is supported for both clear text connection
|
||||||
and tls connection. [rfc section 3.4](https://http2.github.io/http2-spec/#rfc.section.3.4)
|
and tls connection. [rfc section 3.4](https://http2.github.io/http2-spec/#rfc.section.3.4)
|
||||||
|
|
||||||
Please check [example](https://github.com/actix/actix-web/tree/master/examples/tls)
|
> Check out [examples/tls](https://github.com/actix/actix-web/tree/master/examples/tls)
|
||||||
for a concrete example.
|
> for a concrete example.
|
||||||
|
@ -2,13 +2,14 @@
|
|||||||
|
|
||||||
## Diesel
|
## Diesel
|
||||||
|
|
||||||
At the moment of 1.0 release Diesel does not support asynchronous operations.
|
At the moment, Diesel 1.0 does not support asynchronous operations,
|
||||||
But it possible to use the `actix` synchronous actor system as a db interface api.
|
but it possible to use the `actix` synchronous actor system as a database interface api.
|
||||||
Technically sync actors are worker style actors, multiple of them
|
|
||||||
can be run in parallel and process messages from same queue (sync actors work in mpsc mode).
|
|
||||||
|
|
||||||
Let's create a simple db api that can insert a new user row into an SQLite table.
|
Technically, sync actors are worker style actors. Multiple sync actors
|
||||||
We have to define sync actor and connection that this actor will use. The same approach
|
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.
|
||||||
|
We must define a sync actor and a connection that this actor will use. The same approach
|
||||||
can be used for other databases.
|
can be used for other databases.
|
||||||
|
|
||||||
```rust,ignore
|
```rust,ignore
|
||||||
@ -21,7 +22,7 @@ impl Actor for DbExecutor {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
This is the definition of our actor. Now we need to define the *create user* message and response.
|
This is the definition of our actor. Now, we must define the *create user* message and response.
|
||||||
|
|
||||||
```rust,ignore
|
```rust,ignore
|
||||||
struct CreateUser {
|
struct CreateUser {
|
||||||
@ -33,8 +34,8 @@ impl Message for CreateUser {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
We can send a `CreateUser` message to the `DbExecutor` actor, and as a result we get a
|
We can send a `CreateUser` message to the `DbExecutor` actor, and as a result, we will receive a
|
||||||
`User` model instance. Now we need to define the actual handler implementation for this message.
|
`User` model instance. Next, we must define the handler implementation for this message.
|
||||||
|
|
||||||
```rust,ignore
|
```rust,ignore
|
||||||
impl Handler<CreateUser> for DbExecutor {
|
impl Handler<CreateUser> for DbExecutor {
|
||||||
@ -67,7 +68,7 @@ impl Handler<CreateUser> for DbExecutor {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
That's it. Now we can use the *DbExecutor* actor from any http handler or middleware.
|
That's it! Now, we can use the *DbExecutor* actor from any http handler or middleware.
|
||||||
All we need is to start *DbExecutor* actors and store the address in a state where http handler
|
All we need is to start *DbExecutor* actors and store the address in a state where http handler
|
||||||
can access it.
|
can access it.
|
||||||
|
|
||||||
@ -97,9 +98,9 @@ fn main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
And finally we can use the address in a request handler. We get a message response
|
We will use the address in a request handler. The handle returns a future object;
|
||||||
asynchronously, so the handler needs to return a future object, also `Route::a()` needs to be
|
thus, we receive the message response asynchronously.
|
||||||
used for async handler registration.
|
`Route::a()` must be used for async handler registration.
|
||||||
|
|
||||||
|
|
||||||
```rust,ignore
|
```rust,ignore
|
||||||
@ -120,8 +121,8 @@ fn index(req: HttpRequest<State>) -> Box<Future<Item=HttpResponse, Error=Error>>
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Full example is available in the
|
> A full example is available in the
|
||||||
[examples directory](https://github.com/actix/actix-web/tree/master/examples/diesel/).
|
> [examples directory](https://github.com/actix/actix-web/tree/master/examples/diesel/).
|
||||||
|
|
||||||
More information on sync actors can be found in the
|
> More information on sync actors can be found in the
|
||||||
[actix documentation](https://docs.rs/actix/0.5.0/actix/sync/index.html).
|
> [actix documentation](https://docs.rs/actix/0.5.0/actix/sync/index.html).
|
||||||
|
@ -4,10 +4,13 @@
|
|||||||
|
|
||||||
A builder-like pattern is used to construct an instance of `HttpResponse`.
|
A builder-like pattern is used to construct an instance of `HttpResponse`.
|
||||||
`HttpResponse` provides several methods that return a `HttpResponseBuilder` instance,
|
`HttpResponse` provides several methods that return a `HttpResponseBuilder` instance,
|
||||||
which implements various convenience methods that helps building responses.
|
which implements various convenience methods for building responses.
|
||||||
Check [documentation](../actix_web/dev/struct.HttpResponseBuilder.html)
|
|
||||||
for type descriptions. The methods `.body`, `.finish`, `.json` finalize response creation and
|
> Check the [documentation](../actix_web/dev/struct.HttpResponseBuilder.html)
|
||||||
return a constructed *HttpResponse* instance. If this methods is called for the same
|
> for type descriptions.
|
||||||
|
|
||||||
|
The methods `.body`, `.finish`, and `.json` finalize response creation and
|
||||||
|
return a constructed *HttpResponse* instance. If this methods is called on the same
|
||||||
builder instance multiple times, the builder will panic.
|
builder instance multiple times, the builder will panic.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
@ -26,22 +29,24 @@ fn index(req: HttpRequest) -> HttpResponse {
|
|||||||
|
|
||||||
## Content encoding
|
## Content encoding
|
||||||
|
|
||||||
Actix automatically *compresses*/*decompresses* payloads. Following codecs are supported:
|
Actix automatically *compresses*/*decompresses* payloads. The following codecs are supported:
|
||||||
|
|
||||||
* Brotli
|
* Brotli
|
||||||
* Gzip
|
* Gzip
|
||||||
* Deflate
|
* Deflate
|
||||||
* Identity
|
* Identity
|
||||||
|
|
||||||
If request headers contain a `Content-Encoding` header, the request payload is decompressed
|
If request headers contain a `Content-Encoding` header, the request payload is decompressed
|
||||||
according to the header value. Multiple codecs are not supported, i.e: `Content-Encoding: br, gzip`.
|
according to the header value. Multiple codecs are not supported, i.e: `Content-Encoding: br, gzip`.
|
||||||
|
|
||||||
Response payload is compressed based on the *content_encoding* parameter.
|
Response payload is compressed based on the *content_encoding* parameter.
|
||||||
By default `ContentEncoding::Auto` is used. If `ContentEncoding::Auto` is selected
|
By default, `ContentEncoding::Auto` is used. If `ContentEncoding::Auto` is selected,
|
||||||
then compression depends on the request's `Accept-Encoding` header.
|
then the compression depends on the request's `Accept-Encoding` header.
|
||||||
`ContentEncoding::Identity` can be used to disable compression.
|
|
||||||
If another content encoding is selected the compression is enforced for this codec. For example,
|
> `ContentEncoding::Identity` can be used to disable compression.
|
||||||
to enable `brotli` use `ContentEncoding::Br`:
|
> If another content encoding is selected, the compression is enforced for that codec.
|
||||||
|
|
||||||
|
For example, to enable `brotli` use `ContentEncoding::Br`:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
# extern crate actix_web;
|
# extern crate actix_web;
|
||||||
@ -55,15 +60,14 @@ fn index(req: HttpRequest) -> HttpResponse {
|
|||||||
# fn main() {}
|
# fn main() {}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## JSON Request
|
## JSON Request
|
||||||
|
|
||||||
There are several options for json body deserialization.
|
There are several options for json body deserialization.
|
||||||
|
|
||||||
The first option is to use *Json* extractor. You define handler function
|
The first option is to use *Json* extractor. First, you define a handler function
|
||||||
that accepts `Json<T>` as a parameter and use `.with()` method for registering
|
that accepts `Json<T>` as a parameter, then, you use the `.with()` method for registering
|
||||||
this handler. It is also possible to accept arbitrary valid json object by
|
this handler. It is also possible to accept arbitrary valid json object by
|
||||||
using `serde_json::Value` as a type `T`
|
using `serde_json::Value` as a type `T`.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
# extern crate actix_web;
|
# extern crate actix_web;
|
||||||
@ -87,7 +91,7 @@ fn main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The second option is to use *HttpResponse::json()*. This method returns a
|
Another option is to use *HttpResponse::json()*. This method returns a
|
||||||
[*JsonBody*](../actix_web/dev/struct.JsonBody.html) object which resolves into
|
[*JsonBody*](../actix_web/dev/struct.JsonBody.html) object which resolves into
|
||||||
the deserialized value.
|
the deserialized value.
|
||||||
|
|
||||||
@ -116,8 +120,9 @@ fn index(mut req: HttpRequest) -> Box<Future<Item=HttpResponse, Error=Error>> {
|
|||||||
# fn main() {}
|
# fn main() {}
|
||||||
```
|
```
|
||||||
|
|
||||||
Or you can manually load the payload into memory and then deserialize it.
|
You may also manually load the payload into memory and then deserialize it.
|
||||||
Here is a simple example. We will deserialize a *MyObj* struct. We need to load the request
|
|
||||||
|
In the following example, we will deserialize a *MyObj* struct. We need to load the request
|
||||||
body first and then deserialize the json into an object.
|
body first and then deserialize the json into an object.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
@ -149,15 +154,14 @@ fn index(req: HttpRequest) -> Box<Future<Item=HttpResponse, Error=Error>> {
|
|||||||
# fn main() {}
|
# fn main() {}
|
||||||
```
|
```
|
||||||
|
|
||||||
A complete example for both options is available in
|
> A complete example for both options is available in
|
||||||
[examples directory](https://github.com/actix/actix-web/tree/master/examples/json/).
|
> [examples directory](https://github.com/actix/actix-web/tree/master/examples/json/).
|
||||||
|
|
||||||
|
|
||||||
## JSON Response
|
## JSON Response
|
||||||
|
|
||||||
The `Json` type allows to respond with well-formed JSON data: simply return a value of
|
The `Json` type allows to respond with well-formed JSON data: simply return a value of
|
||||||
type Json<T> where T is the type of a structure to serialize into *JSON*. The
|
type Json<T> where `T` is the type of a structure to serialize into *JSON*.
|
||||||
type `T` must implement the `Serialize` trait from *serde*.
|
The type `T` must implement the `Serialize` trait from *serde*.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
# extern crate actix_web;
|
# extern crate actix_web;
|
||||||
@ -184,14 +188,14 @@ fn main() {
|
|||||||
|
|
||||||
Actix automatically decodes *chunked* encoding. `HttpRequest::payload()` already contains
|
Actix automatically decodes *chunked* encoding. `HttpRequest::payload()` already contains
|
||||||
the decoded byte stream. If the request payload is compressed with one of the supported
|
the decoded byte stream. If the request payload is compressed with one of the supported
|
||||||
compression codecs (br, gzip, deflate) the byte stream is decompressed.
|
compression codecs (br, gzip, deflate), then the byte stream is decompressed.
|
||||||
|
|
||||||
Chunked encoding on response can be enabled with `HttpResponseBuilder::chunked()`.
|
Chunked encoding on a response can be enabled with `HttpResponseBuilder::chunked()`.
|
||||||
But this takes effect only for `Body::Streaming(BodyStream)` or `Body::StreamingContext` bodies.
|
This takes effect only for `Body::Streaming(BodyStream)` or `Body::StreamingContext` bodies.
|
||||||
Also if response payload compression is enabled and streaming body is used, chunked encoding
|
If the response payload compression is enabled and a streaming body is used, chunked encoding
|
||||||
is enabled automatically.
|
is enabled automatically.
|
||||||
|
|
||||||
Enabling chunked encoding for *HTTP/2.0* responses is forbidden.
|
> Enabling chunked encoding for *HTTP/2.0* responses is forbidden.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
# extern crate bytes;
|
# extern crate bytes;
|
||||||
@ -214,11 +218,11 @@ fn index(req: HttpRequest) -> HttpResponse {
|
|||||||
|
|
||||||
Actix provides multipart stream support.
|
Actix provides multipart stream support.
|
||||||
[*Multipart*](../actix_web/multipart/struct.Multipart.html) is implemented as
|
[*Multipart*](../actix_web/multipart/struct.Multipart.html) is implemented as
|
||||||
a stream of multipart items, each item can be a
|
a stream of multipart items. Each item can be a
|
||||||
[*Field*](../actix_web/multipart/struct.Field.html) or a nested *Multipart* stream.
|
[*Field*](../actix_web/multipart/struct.Field.html) or a nested *Multipart* stream.
|
||||||
`HttpResponse::multipart()` returns the *Multipart* stream for the current request.
|
`HttpResponse::multipart()` returns the *Multipart* stream for the current request.
|
||||||
|
|
||||||
In simple form multipart stream handling can be implemented similar to this example
|
The following demonstrates multipart stream handling for a simple form:
|
||||||
|
|
||||||
```rust,ignore
|
```rust,ignore
|
||||||
# extern crate actix_web;
|
# extern crate actix_web;
|
||||||
@ -248,17 +252,18 @@ fn index(req: HttpRequest) -> Box<Future<...>> {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
A full example is available in the
|
> A full example is available in the
|
||||||
[examples directory](https://github.com/actix/actix-web/tree/master/examples/multipart/).
|
> [examples directory](https://github.com/actix/actix-web/tree/master/examples/multipart/).
|
||||||
|
|
||||||
## Urlencoded body
|
## Urlencoded body
|
||||||
|
|
||||||
Actix provides support for *application/x-www-form-urlencoded* encoded bodies.
|
Actix provides support for *application/x-www-form-urlencoded* encoded bodies.
|
||||||
`HttpResponse::urlencoded()` returns a
|
`HttpResponse::urlencoded()` returns a
|
||||||
[*UrlEncoded*](../actix_web/dev/struct.UrlEncoded.html) future, which resolves
|
[*UrlEncoded*](../actix_web/dev/struct.UrlEncoded.html) future, which resolves
|
||||||
to the deserialized instance, the type of the instance must implement the
|
to the deserialized instance. The type of the instance must implement the
|
||||||
`Deserialize` trait from *serde*. The *UrlEncoded* future can resolve into
|
`Deserialize` trait from *serde*.
|
||||||
a error in several cases:
|
|
||||||
|
The *UrlEncoded* future can resolve into an error in several cases:
|
||||||
|
|
||||||
* content type is not `application/x-www-form-urlencoded`
|
* content type is not `application/x-www-form-urlencoded`
|
||||||
* transfer encoding is `chunked`.
|
* transfer encoding is `chunked`.
|
||||||
@ -294,7 +299,7 @@ fn index(mut req: HttpRequest) -> Box<Future<Item=HttpResponse, Error=Error>> {
|
|||||||
*HttpRequest* is a stream of `Bytes` objects. It can be used to read the request
|
*HttpRequest* is a stream of `Bytes` objects. It can be used to read the request
|
||||||
body payload.
|
body payload.
|
||||||
|
|
||||||
In this example handle reads the request payload chunk by chunk and prints every chunk.
|
In the following example, we read and print the request payload chunk by chunk:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
# extern crate actix_web;
|
# extern crate actix_web;
|
||||||
|
@ -5,9 +5,9 @@ integration tests.
|
|||||||
|
|
||||||
## Unit tests
|
## Unit tests
|
||||||
|
|
||||||
For unit testing actix provides a request builder type and simple handler runner.
|
For unit testing, actix provides a request builder type and a simple handler runner.
|
||||||
[*TestRequest*](../actix_web/test/struct.TestRequest.html) implements a builder-like pattern.
|
[*TestRequest*](../actix_web/test/struct.TestRequest.html) implements a builder-like pattern.
|
||||||
You can generate a `HttpRequest` instance with `finish()` or you can
|
You can generate a `HttpRequest` instance with `finish()`, or you can
|
||||||
run your handler with `run()` or `run_async()`.
|
run your handler with `run()` or `run_async()`.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
@ -36,19 +36,20 @@ fn main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Integration tests
|
## Integration tests
|
||||||
|
|
||||||
There are several methods how you can test your application. Actix provides
|
There are several methods for testing your application. Actix provides
|
||||||
[*TestServer*](../actix_web/test/struct.TestServer.html)
|
[*TestServer*](../actix_web/test/struct.TestServer.html), which can be used
|
||||||
server that can be used to run the whole application of just specific handlers
|
to run the application with specific handlers in a real http server.
|
||||||
in real http server. *TestServer::get()*, *TestServer::post()* or *TestServer::client()*
|
|
||||||
|
`TestServer::get()`, `TestServer::post()`, and `TestServer::client()`
|
||||||
methods can be used to send requests to the test server.
|
methods can be used to send requests to the test server.
|
||||||
|
|
||||||
In simple form *TestServer* can be configured to use handler. *TestServer::new* method
|
A simple form `TestServer` can be configured to use a handler.
|
||||||
accepts configuration function, only argument for this function is *test application*
|
`TestServer::new` method accepts a configuration function, and the only argument
|
||||||
instance. You can check the [api documentation](../actix_web/test/struct.TestApp.html)
|
for this function is a *test application* instance.
|
||||||
for more information.
|
|
||||||
|
> Check the [api documentation](../actix_web/test/struct.TestApp.html) for more information.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
# extern crate actix_web;
|
# extern crate actix_web;
|
||||||
@ -70,8 +71,8 @@ fn main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The other option is to use an application factory. In this case you need to pass the factory
|
The other option is to use an application factory. In this case, you need to pass the factory
|
||||||
function same way as you would for real http server configuration.
|
function the same way as you would for real http server configuration.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
# extern crate actix_web;
|
# extern crate actix_web;
|
||||||
@ -98,11 +99,10 @@ fn main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
If you need more complex application configuration, for example you may need to
|
If you need more complex application configuration, use the `TestServer::build_with_state()`
|
||||||
initialize application state or start `SyncActor`'s for diesel interation, you
|
method. For example, you may need to initialize application state or start `SyncActor`'s for diesel
|
||||||
can use `TestServer::build_with_state()` method. This method accepts closure
|
interation. This method accepts a closure that constructs the application state,
|
||||||
that has to construct application state. This closure runs when actix system is
|
and it runs when the actix system is configured. Thus, you can initialize any additional actors.
|
||||||
configured already, so you can initialize any additional actors.
|
|
||||||
|
|
||||||
```rust,ignore
|
```rust,ignore
|
||||||
#[test]
|
#[test]
|
||||||
@ -127,13 +127,13 @@ fn test() {
|
|||||||
|
|
||||||
## WebSocket server tests
|
## WebSocket server tests
|
||||||
|
|
||||||
It is possible to register a *handler* with `TestApp::handler()` that
|
It is possible to register a *handler* with `TestApp::handler()`, which
|
||||||
initiates a web socket connection. *TestServer* provides `ws()` which connects to
|
initiates a web socket connection. *TestServer* provides the method `ws()`, which connects to
|
||||||
the websocket server and returns ws reader and writer objects. *TestServer* also
|
the websocket server and returns ws reader and writer objects. *TestServer* also
|
||||||
provides an `execute()` method which runs future objects to completion and returns
|
provides an `execute()` method, which runs future objects to completion and returns
|
||||||
result of the future computation.
|
result of the future computation.
|
||||||
|
|
||||||
Here is a simple example that shows how to test server websocket handler.
|
The following example demonstrates how to test a websocket handler:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
# extern crate actix;
|
# extern crate actix;
|
||||||
|
@ -3,10 +3,10 @@
|
|||||||
Actix supports WebSockets out-of-the-box. It is possible to convert a request's `Payload`
|
Actix supports WebSockets out-of-the-box. It is possible to convert a request's `Payload`
|
||||||
to a stream of [*ws::Message*](../actix_web/ws/enum.Message.html) with
|
to a stream of [*ws::Message*](../actix_web/ws/enum.Message.html) with
|
||||||
a [*ws::WsStream*](../actix_web/ws/struct.WsStream.html) and then use stream
|
a [*ws::WsStream*](../actix_web/ws/struct.WsStream.html) and then use stream
|
||||||
combinators to handle actual messages. But it is simpler to handle websocket communications
|
combinators to handle actual messages, but it is simpler to handle websocket communications
|
||||||
with an http actor.
|
with an http actor.
|
||||||
|
|
||||||
This is example of a simple websocket echo server:
|
The following is an example of a simple websocket echo server:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
# extern crate actix;
|
# extern crate actix;
|
||||||
@ -41,8 +41,8 @@ fn main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
A simple websocket echo server example is available in the
|
> A simple websocket echo server example is available in the
|
||||||
[examples directory](https://github.com/actix/actix-web/blob/master/examples/websocket).
|
> [examples directory](https://github.com/actix/actix-web/blob/master/examples/websocket).
|
||||||
|
|
||||||
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](https://github.com/actix/actix-web/tree/master/examples/websocket-chat/)
|
> is available in [websocket-chat directory](https://github.com/actix/actix-web/tree/master/examples/websocket-chat/)
|
||||||
|
Loading…
Reference in New Issue
Block a user