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
|
||||
|
||||
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
|
||||
curl https://sh.rustup.rs -sSf | sh
|
||||
|
@ -1,23 +1,25 @@
|
||||
# Middleware
|
||||
|
||||
Actix' middleware system allows to add additional behavior to request/response processing.
|
||||
Middleware can hook into incoming request process and modify request or halt request
|
||||
processing and return response early. Also it can hook into response processing.
|
||||
Actix's middleware system allows us to add additional behavior to request/response processing.
|
||||
Middleware can hook into an incoming request process, enabling us to modify requests
|
||||
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
|
||||
* Post-process a Response
|
||||
* Modify application state
|
||||
* Access external services (redis, logging, sessions)
|
||||
|
||||
Middlewares are registered for each application and are executed in same order as
|
||||
registration order. In general, a *middleware* is a type that implements the
|
||||
Middleware is registered for each application and executed in same order as
|
||||
registration. In general, a *middleware* is a type that implements the
|
||||
[*Middleware trait*](../actix_web/middlewares/trait.Middleware.html). Each method
|
||||
in this trait has a default implementation. Each method can return a result immediately
|
||||
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
|
||||
# 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 is implemented as a middleware.
|
||||
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
|
||||
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).
|
||||
Logging middleware must be registered for each application.
|
||||
|
||||
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
|
||||
|
||||
@ -76,6 +79,7 @@ Default `Logger` can be created with `default` method, it uses the default forma
|
||||
```ignore
|
||||
%a %t "%r" %s %b "%{Referer}i" "%{User-Agent}i" %T
|
||||
```
|
||||
|
||||
```rust
|
||||
# extern crate actix_web;
|
||||
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
|
||||
@ -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']
|
||||
|
||||
|
||||
## 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
|
||||
the specified header.
|
||||
a specified header.
|
||||
|
||||
```rust
|
||||
# extern crate actix_web;
|
||||
@ -153,27 +156,28 @@ fn main() {
|
||||
## User sessions
|
||||
|
||||
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.
|
||||
By default only cookie session backend is implemented. Other backend implementations
|
||||
could be added later.
|
||||
|
||||
[*Cookie session backend*](../actix_web/middleware/struct.CookieSessionBackend.html)
|
||||
uses signed cookies as session storage. *Cookie session backend* creates sessions which
|
||||
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.
|
||||
> By default, only cookie session backend is implemented. Other backend implementations
|
||||
> can be added.
|
||||
|
||||
You need to pass a random value to the constructor of *CookieSessionBackend*.
|
||||
This is private key for cookie session. When this value is changed, all session data is lost.
|
||||
Note that whatever you write into your session is visible by the user (but not modifiable).
|
||||
[**CookieSessionBackend**](../actix_web/middleware/struct.CookieSessionBackend.html)
|
||||
uses signed cookies as session storage. `CookieSessionBackend` creates sessions which
|
||||
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
|
||||
[*Session storage*](../actix_web/middleware/struct.SessionStorage.html) middleware
|
||||
and initializes it with specific backend implementation, like *CookieSessionBackend*.
|
||||
To access session data
|
||||
You need to pass a random value to the constructor of `CookieSessionBackend`.
|
||||
This is a private key for cookie session. When this value is changed, all session data is lost.
|
||||
|
||||
> **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)
|
||||
has to be used. This method returns a
|
||||
[*Session*](../actix_web/middleware/struct.Session.html) object, which allows to get or set
|
||||
must be used. This method returns a
|
||||
[*Session*](../actix_web/middleware/struct.Session.html) object, which allows us to get or set
|
||||
session data.
|
||||
|
||||
```rust
|
||||
@ -212,12 +216,12 @@ fn main() {
|
||||
|
||||
## 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
|
||||
for specific status code. You can modify existing response or create completly new
|
||||
one. Error handler can return response immediately or return future that resolves
|
||||
to a response.
|
||||
You can use the `ErrorHandlers::handler()` method to register a custom error handler
|
||||
for a specific status code. You can modify an existing response or create a completly new
|
||||
one. The error handler can return a response immediately or return a future that resolves
|
||||
into a response.
|
||||
|
||||
```rust
|
||||
# extern crate actix_web;
|
||||
|
@ -2,8 +2,8 @@
|
||||
|
||||
## Individual file
|
||||
|
||||
It is possible to serve static files with custom path pattern and `NamedFile`. To
|
||||
match path tail we can use `[.*]` regex.
|
||||
It is possible to serve static files with a custom path pattern and `NamedFile`. To
|
||||
match a path tail, we can use a `[.*]` regex.
|
||||
|
||||
```rust
|
||||
# extern crate actix_web;
|
||||
@ -24,9 +24,9 @@ fn main() {
|
||||
|
||||
## Directory
|
||||
|
||||
To serve files from specific directory and sub-directories `StaticFiles` could be used.
|
||||
`StaticFiles` must be registered with `App::handler()` method otherwise
|
||||
it won't be able to serve sub-paths.
|
||||
To serve files from specific directories and sub-directories, `StaticFiles` can be used.
|
||||
`StaticFiles` must be registered with an `App::handler()` method, otherwise
|
||||
it will be unable to serve sub-paths.
|
||||
|
||||
```rust
|
||||
# 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*
|
||||
directory listing would be returned for directories, if it is set to *false*
|
||||
then *404 Not Found* would be returned instead of directory listing.
|
||||
The first parameter is the base directory. If the second parameter, *show_index*, is set to **true**,
|
||||
the directory listing will be returned, and if it is set to **false**,
|
||||
*404 Not Found* will be returned.
|
||||
|
||||
Instead of showing files listing for directory, it is possible to redirect to specific
|
||||
index file. Use
|
||||
Instead of showing files listing for directory, it is possible to redirect to a specific
|
||||
index file. Use the
|
||||
[*StaticFiles::index_file()*](../actix_web/s/struct.StaticFiles.html#method.index_file)
|
||||
method to configure this redirect.
|
||||
|
@ -1,13 +1,15 @@
|
||||
# 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
|
||||
|
||||
*HTTP/2.0* protocol over tls without prior knowledge requires
|
||||
[tls alpn](https://tools.ietf.org/html/rfc7301). At the moment only
|
||||
`rust-openssl` has support. Turn on the `alpn` feature to enable `alpn` negotiation.
|
||||
With enabled `alpn` feature `HttpServer` provides the
|
||||
[tls alpn](https://tools.ietf.org/html/rfc7301).
|
||||
|
||||
> 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.
|
||||
|
||||
```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.
|
||||
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)
|
||||
|
||||
Please check [example](https://github.com/actix/actix-web/tree/master/examples/tls)
|
||||
for a concrete example.
|
||||
> Check out [examples/tls](https://github.com/actix/actix-web/tree/master/examples/tls)
|
||||
> for a concrete example.
|
||||
|
@ -2,13 +2,14 @@
|
||||
|
||||
## Diesel
|
||||
|
||||
At the moment of 1.0 release Diesel does not support asynchronous operations.
|
||||
But it possible to use the `actix` synchronous actor system as a db 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).
|
||||
At the moment, Diesel 1.0 does not support asynchronous operations,
|
||||
but it possible to use the `actix` synchronous actor system as a database interface api.
|
||||
|
||||
Let's create a simple db api that can insert a new user row into an SQLite table.
|
||||
We have to define sync actor and connection that this actor will use. The same approach
|
||||
Technically, sync actors are worker style actors. Multiple sync actors
|
||||
can be run in parallel and process messages from same queue. Sync actors work in mpsc mode.
|
||||
|
||||
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.
|
||||
|
||||
```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
|
||||
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
|
||||
`User` model instance. Now we need to define the actual handler implementation for this message.
|
||||
We can send a `CreateUser` message to the `DbExecutor` actor, and as a result, we will receive a
|
||||
`User` model instance. Next, we must define the handler implementation for this message.
|
||||
|
||||
```rust,ignore
|
||||
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
|
||||
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
|
||||
asynchronously, so the handler needs to return a future object, also `Route::a()` needs to be
|
||||
used for async handler registration.
|
||||
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.
|
||||
|
||||
|
||||
```rust,ignore
|
||||
@ -120,8 +121,8 @@ fn index(req: HttpRequest<State>) -> Box<Future<Item=HttpResponse, Error=Error>>
|
||||
}
|
||||
```
|
||||
|
||||
Full example is available in the
|
||||
[examples directory](https://github.com/actix/actix-web/tree/master/examples/diesel/).
|
||||
> A full example is available in the
|
||||
> [examples directory](https://github.com/actix/actix-web/tree/master/examples/diesel/).
|
||||
|
||||
More information on sync actors can be found in the
|
||||
[actix documentation](https://docs.rs/actix/0.5.0/actix/sync/index.html).
|
||||
> More information on sync actors can be found in the
|
||||
> [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`.
|
||||
`HttpResponse` provides several methods that return a `HttpResponseBuilder` instance,
|
||||
which implements various convenience methods that helps building responses.
|
||||
Check [documentation](../actix_web/dev/struct.HttpResponseBuilder.html)
|
||||
for type descriptions. The methods `.body`, `.finish`, `.json` finalize response creation and
|
||||
return a constructed *HttpResponse* instance. If this methods is called for the same
|
||||
which implements various convenience methods for building responses.
|
||||
|
||||
> Check the [documentation](../actix_web/dev/struct.HttpResponseBuilder.html)
|
||||
> 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.
|
||||
|
||||
```rust
|
||||
@ -26,7 +29,7 @@ fn index(req: HttpRequest) -> HttpResponse {
|
||||
|
||||
## Content encoding
|
||||
|
||||
Actix automatically *compresses*/*decompresses* payloads. Following codecs are supported:
|
||||
Actix automatically *compresses*/*decompresses* payloads. The following codecs are supported:
|
||||
|
||||
* Brotli
|
||||
* Gzip
|
||||
@ -37,11 +40,13 @@ Actix automatically *compresses*/*decompresses* payloads. Following codecs are s
|
||||
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.
|
||||
By default `ContentEncoding::Auto` is used. If `ContentEncoding::Auto` is selected
|
||||
then 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,
|
||||
to enable `brotli` use `ContentEncoding::Br`:
|
||||
By default, `ContentEncoding::Auto` is used. If `ContentEncoding::Auto` is selected,
|
||||
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 that codec.
|
||||
|
||||
For example, to enable `brotli` use `ContentEncoding::Br`:
|
||||
|
||||
```rust
|
||||
# extern crate actix_web;
|
||||
@ -55,15 +60,14 @@ fn index(req: HttpRequest) -> HttpResponse {
|
||||
# fn main() {}
|
||||
```
|
||||
|
||||
|
||||
## JSON Request
|
||||
|
||||
There are several options for json body deserialization.
|
||||
|
||||
The first option is to use *Json* extractor. You define handler function
|
||||
that accepts `Json<T>` as a parameter and use `.with()` method for registering
|
||||
The first option is to use *Json* extractor. First, you define a handler function
|
||||
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
|
||||
using `serde_json::Value` as a type `T`
|
||||
using `serde_json::Value` as a type `T`.
|
||||
|
||||
```rust
|
||||
# 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
|
||||
the deserialized value.
|
||||
|
||||
@ -116,8 +120,9 @@ fn index(mut req: HttpRequest) -> Box<Future<Item=HttpResponse, Error=Error>> {
|
||||
# fn main() {}
|
||||
```
|
||||
|
||||
Or you can 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
|
||||
You may also manually load the payload into memory and then deserialize it.
|
||||
|
||||
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.
|
||||
|
||||
```rust
|
||||
@ -149,15 +154,14 @@ fn index(req: HttpRequest) -> Box<Future<Item=HttpResponse, Error=Error>> {
|
||||
# fn main() {}
|
||||
```
|
||||
|
||||
A complete example for both options is available in
|
||||
[examples directory](https://github.com/actix/actix-web/tree/master/examples/json/).
|
||||
|
||||
> A complete example for both options is available in
|
||||
> [examples directory](https://github.com/actix/actix-web/tree/master/examples/json/).
|
||||
|
||||
## JSON Response
|
||||
|
||||
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 `T` must implement the `Serialize` trait from *serde*.
|
||||
type Json<T> where `T` is the type of a structure to serialize into *JSON*.
|
||||
The type `T` must implement the `Serialize` trait from *serde*.
|
||||
|
||||
```rust
|
||||
# extern crate actix_web;
|
||||
@ -184,14 +188,14 @@ fn main() {
|
||||
|
||||
Actix automatically decodes *chunked* encoding. `HttpRequest::payload()` already contains
|
||||
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()`.
|
||||
But 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
|
||||
Chunked encoding on a response can be enabled with `HttpResponseBuilder::chunked()`.
|
||||
This takes effect only for `Body::Streaming(BodyStream)` or `Body::StreamingContext` bodies.
|
||||
If the response payload compression is enabled and a streaming body is used, chunked encoding
|
||||
is enabled automatically.
|
||||
|
||||
Enabling chunked encoding for *HTTP/2.0* responses is forbidden.
|
||||
> Enabling chunked encoding for *HTTP/2.0* responses is forbidden.
|
||||
|
||||
```rust
|
||||
# extern crate bytes;
|
||||
@ -214,11 +218,11 @@ fn index(req: HttpRequest) -> HttpResponse {
|
||||
|
||||
Actix provides multipart stream support.
|
||||
[*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.
|
||||
`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
|
||||
# extern crate actix_web;
|
||||
@ -248,17 +252,18 @@ fn index(req: HttpRequest) -> Box<Future<...>> {
|
||||
}
|
||||
```
|
||||
|
||||
A full example is available in the
|
||||
[examples directory](https://github.com/actix/actix-web/tree/master/examples/multipart/).
|
||||
> A full example is available in the
|
||||
> [examples directory](https://github.com/actix/actix-web/tree/master/examples/multipart/).
|
||||
|
||||
## Urlencoded body
|
||||
|
||||
Actix provides support for *application/x-www-form-urlencoded* encoded bodies.
|
||||
`HttpResponse::urlencoded()` returns a
|
||||
[*UrlEncoded*](../actix_web/dev/struct.UrlEncoded.html) future, which resolves
|
||||
to the deserialized instance, the type of the instance must implement the
|
||||
`Deserialize` trait from *serde*. The *UrlEncoded* future can resolve into
|
||||
a error in several cases:
|
||||
to the deserialized instance. The type of the instance must implement the
|
||||
`Deserialize` trait from *serde*.
|
||||
|
||||
The *UrlEncoded* future can resolve into an error in several cases:
|
||||
|
||||
* content type is not `application/x-www-form-urlencoded`
|
||||
* 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
|
||||
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
|
||||
# extern crate actix_web;
|
||||
|
@ -5,9 +5,9 @@ integration 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.
|
||||
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()`.
|
||||
|
||||
```rust
|
||||
@ -36,19 +36,20 @@ fn main() {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Integration tests
|
||||
|
||||
There are several methods how you can test your application. Actix provides
|
||||
[*TestServer*](../actix_web/test/struct.TestServer.html)
|
||||
server that can be used to run the whole application of just specific handlers
|
||||
in real http server. *TestServer::get()*, *TestServer::post()* or *TestServer::client()*
|
||||
There are several methods for testing your application. Actix provides
|
||||
[*TestServer*](../actix_web/test/struct.TestServer.html), which can be used
|
||||
to run the application with specific handlers in a real http server.
|
||||
|
||||
`TestServer::get()`, `TestServer::post()`, and `TestServer::client()`
|
||||
methods can be used to send requests to the test server.
|
||||
|
||||
In simple form *TestServer* can be configured to use handler. *TestServer::new* method
|
||||
accepts configuration function, only argument for this function is *test application*
|
||||
instance. You can check the [api documentation](../actix_web/test/struct.TestApp.html)
|
||||
for more information.
|
||||
A simple form `TestServer` can be configured to use a handler.
|
||||
`TestServer::new` method accepts a configuration function, and the only argument
|
||||
for this function is a *test application* instance.
|
||||
|
||||
> Check the [api documentation](../actix_web/test/struct.TestApp.html) for more information.
|
||||
|
||||
```rust
|
||||
# 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
|
||||
function same way as you would for real http server configuration.
|
||||
The other option is to use an application factory. In this case, you need to pass the factory
|
||||
function the same way as you would for real http server configuration.
|
||||
|
||||
```rust
|
||||
# extern crate actix_web;
|
||||
@ -98,11 +99,10 @@ fn main() {
|
||||
}
|
||||
```
|
||||
|
||||
If you need more complex application configuration, for example you may need to
|
||||
initialize application state or start `SyncActor`'s for diesel interation, you
|
||||
can use `TestServer::build_with_state()` method. This method accepts closure
|
||||
that has to construct application state. This closure runs when actix system is
|
||||
configured already, so you can initialize any additional actors.
|
||||
If you need more complex application configuration, use the `TestServer::build_with_state()`
|
||||
method. For example, you may need to initialize application state or start `SyncActor`'s for diesel
|
||||
interation. This method accepts a closure that constructs the application state,
|
||||
and it runs when the actix system is configured. Thus, you can initialize any additional actors.
|
||||
|
||||
```rust,ignore
|
||||
#[test]
|
||||
@ -127,13 +127,13 @@ fn test() {
|
||||
|
||||
## WebSocket server tests
|
||||
|
||||
It is possible to register a *handler* with `TestApp::handler()` that
|
||||
initiates a web socket connection. *TestServer* provides `ws()` which connects to
|
||||
It is possible to register a *handler* with `TestApp::handler()`, which
|
||||
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
|
||||
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.
|
||||
|
||||
Here is a simple example that shows how to test server websocket handler.
|
||||
The following example demonstrates how to test a websocket handler:
|
||||
|
||||
```rust
|
||||
# extern crate actix;
|
||||
|
@ -3,10 +3,10 @@
|
||||
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
|
||||
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.
|
||||
|
||||
This is example of a simple websocket echo server:
|
||||
The following is an example of a simple websocket echo server:
|
||||
|
||||
```rust
|
||||
# extern crate actix;
|
||||
@ -41,8 +41,8 @@ fn main() {
|
||||
}
|
||||
```
|
||||
|
||||
A simple websocket echo server example is available in the
|
||||
[examples directory](https://github.com/actix/actix-web/blob/master/examples/websocket).
|
||||
> A simple websocket echo server example is available in the
|
||||
> [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
|
||||
is available in [websocket-chat directory](https://github.com/actix/actix-web/tree/master/examples/websocket-chat/)
|
||||
> 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/)
|
||||
|
Loading…
Reference in New Issue
Block a user