1
0
mirror of https://github.com/actix/actix-extras.git synced 2024-11-28 01:32:57 +01:00

Merge pull request #163 from memoryruins/guide

Guide: edits to the second half
This commit is contained in:
Nikolay Kim 2018-04-06 19:11:12 -07:00 committed by GitHub
commit 602d78b76c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 153 additions and 141 deletions

View File

@ -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

View File

@ -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;

View File

@ -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.

View File

@ -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.

View File

@ -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).

View File

@ -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;

View File

@ -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;

View File

@ -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/)