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

guide: improve wording & style

This commit is contained in:
Benjamin Wasty 2018-03-28 22:16:01 +02:00
parent 36161aba99
commit 368103dd09
14 changed files with 303 additions and 305 deletions

View File

@ -1,6 +1,6 @@
# Quick start
Before you can start writing a actix web application, youll need a version of Rust installed.
Before you can start writing a actix web applications, youll need a version of Rust installed.
We recommend you use rustup to install or configure such a version.
## Install Rust

View File

@ -1,23 +1,23 @@
# Middlewares
# Middleware
Actix middlewares system allows to add additional behavior to request/response processing.
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.
Typically middlewares involves in following actions:
Typically middlewares are 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 get executed in same order as
registration order. In general, *middleware* is a type that implements
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 trait*](../actix_web/middlewares/trait.Middleware.html). Each method
in this trait has default implementation. Each method can return result immediately
or *future* object.
in this trait has a default implementation. Each method can return a result immediately
or a *future* object.
Here is example of simple middleware that adds request and response headers:
Here is an example of a simple middleware that adds request and response headers:
```rust
# extern crate http;
@ -52,26 +52,26 @@ impl<S> Middleware<S> for Headers {
fn main() {
Application::new()
.middleware(Headers) // <- Register middleware, this method could be called multiple times
.middleware(Headers) // <- Register middleware, this method can be called multiple times
.resource("/", |r| r.h(httpcodes::HttpOk));
}
```
Active provides several useful middlewares, like *logging*, *user sessions*, etc.
Actix provides several useful middlewares, like *logging*, *user sessions*, etc.
## Logging
Logging is implemented as middleware.
It is common to register logging middleware as first middleware for application.
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 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)
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
Create `Logger` middleware with the specified `format`.
Default `Logger` could be created with `default` method, it uses the default format:
Default `Logger` can be created with `default` method, it uses the default format:
```ignore
%a %t "%r" %s %b "%{Referer}i" "%{User-Agent}i" %T
@ -93,7 +93,7 @@ fn main() {
}
```
Here is example of default logging format:
Here 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
@ -129,9 +129,9 @@ INFO:actix_web::middleware::logger: 127.0.0.1:59947 [02/Dec/2017:00:22:40 -0800]
## Default headers
To set default response headers `DefaultHeaders` middleware could be used.
*DefaultHeaders* middleware does not set header if response headers already contains
specified header.
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.
```rust
# extern crate actix_web;
@ -153,16 +153,16 @@ fn main() {
## User sessions
Actix provides general solution for session management.
Actix provides a general solution for session management. The
[*Session storage*](../actix_web/middleware/struct.SessionStorage.html) middleware can be
use 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)
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 get generated if session contains more than 4000 bytes.
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*.
This is private key for cookie session. When this value is changed, all session data is lost.
@ -173,7 +173,7 @@ In general case, you create
and initializes it with specific backend implementation, like *CookieSessionBackend*.
To access session data
[*HttpRequest::session()*](../actix_web/middleware/trait.RequestSession.html#tymethod.session)
method has to be used. This method returns
has to be used. This method returns a
[*Session*](../actix_web/middleware/struct.Session.html) object, which allows to get or set
session data.

View File

@ -26,7 +26,7 @@ fn main() {
To serve files from specific directory and sub-directories `StaticFiles` could be used.
`StaticFiles` must be registered with `Application::handler()` method otherwise
it won't be able to server sub-paths.
it won't be able to serve sub-paths.
```rust
# extern crate actix_web;

View File

@ -6,8 +6,8 @@ Actix web automatically upgrades connection to *HTTP/2.0* if possible.
*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 `alpn` feature to enable `alpn` negotiation.
With enable `alpn` feature `HttpServer` provides
`rust-openssl` has support. Turn on the `alpn` feature to enable `alpn` negotiation.
With enabled `alpn` feature `HttpServer` provides the
[serve_tls](../actix_web/struct.HttpServer.html#method.serve_tls) method.
```toml
@ -41,4 +41,4 @@ Starting *HTTP/2* with prior knowledge is supported for both clear text connecti
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 concrete example.
for a concrete example.

View File

@ -3,13 +3,13 @@
## Diesel
At the moment of 1.0 release Diesel does not support asynchronous operations.
But it possible to use `actix` synchronous actor system as a db interface api.
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 mpmc mode).
can be run in parallel and process messages from same queue (sync actors work in mpsc mode).
Let's create simple db api that can insert new user row into sqlite table.
We have to define sync actor and connection that this actor will use. Same approach
could be used for other databases.
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
can be used for other databases.
```rust,ignore
use actix::prelude::*;
@ -21,7 +21,7 @@ impl Actor for DbExecutor {
}
```
This is definition of our actor. Now we need to define *create user* message and response.
This is the definition of our actor. Now we need to define the *create user* message and response.
```rust,ignore
struct CreateUser {
@ -33,8 +33,8 @@ impl Message for CreateUser {
}
```
We can send `CreateUser` message to `DbExecutor` actor, and as result we get
`User` model. Now we need to define actual handler implementation for this message.
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.
```rust,ignore
impl Handler<CreateUser> for DbExecutor {
@ -67,8 +67,8 @@ impl Handler<CreateUser> for DbExecutor {
}
```
That is it. Now we can use *DbExecutor* actor from any http handler or middleware.
All we need is to start *DbExecutor* actors and store address in a state where http handler
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.
```rust,ignore
@ -97,8 +97,8 @@ fn main() {
}
```
And finally we can use address in a request handler. We get message response
asynchronously, so handler needs to return future object, also `Route::a()` needs to be
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.
@ -120,8 +120,8 @@ fn index(req: HttpRequest<State>) -> Box<Future<Item=HttpResponse, Error=Error>>
}
```
Full example is available in
Full example is available in the
[examples directory](https://github.com/actix/actix-web/tree/master/examples/diesel/).
More information on sync actors could be found in
More information on sync actors can be found in the
[actix documentation](https://docs.rs/actix/0.5.0/actix/sync/index.html).

View File

@ -3,7 +3,7 @@
Lets create and run our first actix web application. Well create a new Cargo project
that depends on actix web and then run the application.
In previous section we already installed required rust version. Now let's create new cargo projects.
In the previous section we already installed the required rust version. Now let's create new cargo projects.
## Hello, world!
@ -26,7 +26,7 @@ actix-web = "0.4"
In order to implement a web server, first we need to create a request handler.
A request handler is a function that accepts a `HttpRequest` instance as its only parameter
A request handler is a function that accepts an `HttpRequest` instance as its only parameter
and returns a type that can be converted into `HttpResponse`:
```rust
@ -53,8 +53,8 @@ request handler with the application's `resource` on a particular *HTTP method*
# }
```
After that, application instance can be used with `HttpServer` to listen for incoming
connections. Server accepts function that should return `HttpHandler` instance:
After that, the application instance can be used with `HttpServer` to listen for incoming
connections. The server accepts a function that should return an `HttpHandler` instance:
```rust,ignore
HttpServer::new(
@ -64,7 +64,7 @@ connections. Server accepts function that should return `HttpHandler` instance:
.run();
```
That's it. Now, compile and run the program with cargo run.
That's it. Now, compile and run the program with `cargo run`.
Head over to ``http://localhost:8088/`` to see the results.
Here is full source of main.rs file:
@ -92,7 +92,7 @@ fn main() {
}
```
Note on `actix` crate. Actix web framework is built on top of actix actor library.
`actix::System` initializes actor system, `HttpServer` is an actor and must run within
Note on the `actix` crate. Actix web framework is built on top of actix actor library.
`actix::System` initializes actor system, `HttpServer` is an actor and must run within a
properly configured actix system. For more information please check
[actix documentation](https://actix.github.io/actix/actix/)

View File

@ -4,16 +4,16 @@ Actix web provides some primitives to build web servers and applications with Ru
It provides routing, middlewares, pre-processing of requests, and post-processing of responses,
websocket protocol handling, multipart streams, etc.
All actix web server is built around `Application` instance.
It is used for registering routes for resources, middlewares.
Also it stores application specific state that is shared across all handlers
All actix web servers are built around the `Application` instance.
It is used for registering routes for resources, and middlewares.
It also stores application specific state that is shared across all handlers
within same application.
Application acts as namespace for all routes, i.e all routes for specific application
has same url path prefix. Application prefix always contains leading "/" slash.
If supplied prefix does not contain leading slash, it get inserted.
Prefix should consists of value path segments. i.e for application with prefix `/app`
any request with following paths `/app`, `/app/` or `/app/test` would match,
Application acts as a namespace for all routes, i.e all routes for a specific application
have the same url path prefix. The application prefix always contains a leading "/" slash.
If supplied prefix does not contain leading slash, it gets inserted.
The prefix should consist of value path segments. i.e for an application with prefix `/app`
any request with the paths `/app`, `/app/` or `/app/test` would match,
but path `/application` would not match.
```rust,ignore
@ -32,11 +32,11 @@ but path `/application` would not match.
```
In this example application with `/app` prefix and `index.html` resource
get created. This resource is available as on `/app/index.html` url.
gets created. This resource is available as on `/app/index.html` url.
For more information check
[*URL Matching*](./qs_5.html#using-a-application-prefix-to-compose-applications) section.
Multiple applications could be served with one server:
Multiple applications can be served with one server:
```rust
# extern crate actix_web;
@ -59,21 +59,21 @@ fn main() {
}
```
All `/app1` requests route to first application, `/app2` to second and then all other to third.
Applications get matched based on registration order, if application with more general
prefix is registered before less generic, that would effectively block less generic
application to get matched. For example if *application* with prefix "/" get registered
All `/app1` requests route to the first application, `/app2` to the second and then all other to the third.
Applications get matched based on registration order, if an application with more general
prefix is registered before a less generic one, that would effectively block the less generic
application from getting matched. For example, if *application* with prefix "/" gets registered
as first application, it would match all incoming requests.
## State
Application state is shared with all routes and resources within same application.
State could be accessed with `HttpRequest::state()` method as a read-only item
but interior mutability pattern with `RefCell` could be used to archive state mutability.
State could be accessed with `HttpContext::state()` in case of http actor.
State also available to route matching predicates and middlewares.
Application state is shared with all routes and resources within the same application.
State can be accessed with the `HttpRequest::state()` method as a read-only,
but an interior mutability pattern with `RefCell` can be used to achieve state mutability.
State can be accessed with `HttpContext::state()` when using an http actor.
State is also available for route matching predicates and middlewares.
Let's write simple application that uses shared state. We are going to store requests count
Let's write a simple application that uses shared state. We are going to store request count
in the state:
```rust
@ -102,8 +102,8 @@ fn main() {
}
```
Note on application state, http server accepts application factory rather than application
instance. Http server construct application instance for each thread, so application state
must be constructed multiple times. If you want to share state between different thread
Note on application state, http server accepts an application factory rather than an application
instance. Http server constructs an application instance for each thread, so application state
must be constructed multiple times. If you want to share state between different threads, a
shared object should be used, like `Arc`. Application state does not need to be `Send` and `Sync`
but application factory must be `Send` + `Sync`.
but the application factory must be `Send` + `Sync`.

View File

@ -1,13 +1,13 @@
# Server
[*HttpServer*](../actix_web/struct.HttpServer.html) type is responsible for
serving http requests. *HttpServer* accept application factory as a parameter,
Application factory must have `Send` + `Sync` boundaries. More about that in
*multi-threading* section. To bind to specific socket address `bind()` must be used.
This method could be called multiple times. To start http server one of the *start*
methods could be used. `start()` method start simple server, `start_tls()` or `start_ssl()`
The [*HttpServer*](../actix_web/struct.HttpServer.html) type is responsible for
serving http requests. *HttpServer* accepts application factory as a parameter,
Application factory must have `Send` + `Sync` boundaries. More about that in the
*multi-threading* section. To bind to a specific socket address, `bind()` must be used.
This method can be called multiple times. To start the http server, one of the *start*
methods can be used. `start()` method starts a simple server, `start_tls()` or `start_ssl()`
starts ssl server. *HttpServer* is an actix actor, it has to be initialized
within properly configured actix system:
within a properly configured actix system:
```rust
# extern crate actix;
@ -29,13 +29,13 @@ fn main() {
}
```
It is possible to start server in separate thread with *spawn()* method. In that
case server spawns new thread and create new actix system in it. To stop
this server send `StopServer` message.
It is possible to start a server in a separate thread with the *spawn()* method. In that
case the server spawns a new thread and creates a new actix system in it. To stop
this server, send a `StopServer` message.
Http server is implemented as an actix actor. It is possible to communicate with server
via messaging system. All start methods like `start()`, `start_ssl()`, etc returns
address of the started http server. Actix http server accept several messages:
Http server is implemented as an actix actor. It is possible to communicate with the server
via a messaging system. All start methods like `start()`, `start_ssl()`, etc. return the
address of the started http server. Actix http server accepts several messages:
* `PauseServer` - Pause accepting incoming connections
* `ResumeServer` - Resume accepting incoming connections
@ -73,9 +73,9 @@ fn main() {
## Multi-threading
Http server automatically starts number of http workers, by default
this number is equal to number of logical cpu in the system. This number
could be overridden with `HttpServer::threads()` method.
Http server automatically starts an number of http workers, by default
this number is equal to number of logical CPUs in the system. This number
can be overridden with the `HttpServer::threads()` method.
```rust
# extern crate actix_web;
@ -90,13 +90,13 @@ fn main() {
}
```
Server create separate application instance for each created worker. Application state
The server creates a separate application instance for each created worker. Application state
is not shared between threads, to share state `Arc` could be used. Application state
does not need to be `Send` and `Sync` but application factory must be `Send` + `Sync`.
## SSL
There are two `tls` and `alpn` features for ssl server. `tls` feature is for `native-tls`
There are two features for ssl server: `tls` and `alpn`. The `tls` feature is for `native-tls`
integration and `alpn` is for `openssl`.
```toml
@ -127,7 +127,7 @@ Note on *HTTP/2.0* protocol over tls without prior knowledge, it requires
`openssl` has `alpn ` support.
Please check [example](https://github.com/actix/actix-web/tree/master/examples/tls)
for full example.
for a full example.
## Keep-Alive
@ -162,13 +162,13 @@ fn main() {
}
```
If first option is selected then *keep alive* state
calculated based on response's *connection-type*. By default
If first option is selected then *keep alive* state is
calculated based on the response's *connection-type*. By default
`HttpResponse::connection_type` is not defined in that case *keep alive*
defined by request's http version. Keep alive is off for *HTTP/1.0*
and is on for *HTTP/1.1* and *HTTP/2.0*.
*Connection type* could be change with `HttpResponseBuilder::connection_type()` method.
*Connection type* can be change with `HttpResponseBuilder::connection_type()` method.
```rust
# extern crate actix_web;
@ -186,13 +186,13 @@ fn index(req: HttpRequest) -> HttpResponse {
## Graceful shutdown
Actix http server support graceful shutdown. After receiving a stop signal, workers
have specific amount of time to finish serving requests. Workers still alive after the
timeout are force dropped. By default shutdown timeout sets to 30 seconds.
You can change this parameter with `HttpServer::shutdown_timeout()` method.
Actix http server supports graceful shutdown. After receiving a stop signal, workers
have a specific amount of time to finish serving requests. Workers still alive after the
timeout are force-dropped. By default the shutdown timeout is set to 30 seconds.
You can change this parameter with the `HttpServer::shutdown_timeout()` method.
You can send stop message to server with server address and specify if you what
graceful shutdown or not. `start()` methods return address of the server.
You can send a stop message to the server with the server address and specify if you want
graceful shutdown or not. The `start()` methods return address of the server.
Http server handles several OS signals. *CTRL-C* is available on all OSs,
other signals are available on unix systems.
@ -201,4 +201,4 @@ other signals are available on unix systems.
* *SIGTERM* - Graceful shutdown workers
* *SIGQUIT* - Force shutdown workers
It is possible to disable signals handling with `HttpServer::disable_signals()` method.
It is possible to disable signal handling with `HttpServer::disable_signals()` method.

View File

@ -1,16 +1,16 @@
# Handler
A request handler can by any object that implements
A request handler can be any object that implements
[*Handler trait*](../actix_web/dev/trait.Handler.html).
Request handling happen in two stages. First handler object get called.
Handle can return any object that implements
Request handling happens in two stages. First the handler object is called.
Handler can return any object that implements
[*Responder trait*](../actix_web/trait.Responder.html#foreign-impls).
Then `respond_to()` get called on returned object. And finally
result of the `respond_to()` call get converted to `Reply` object.
Then `respond_to()` is called on the returned object. And finally
result of the `respond_to()` call is converted to a `Reply` object.
By default actix provides `Responder` implementations for some standard types,
like `&'static str`, `String`, etc.
For complete list of implementations check
For a complete list of implementations, check
[*Responder documentation*](../actix_web/trait.Responder.html#foreign-impls).
Examples of valid handlers:
@ -41,15 +41,15 @@ fn index(req: HttpRequest) -> Box<Future<Item=HttpResponse, Error=Error>> {
Some notes on shared application state and handler state. If you noticed
*Handler* trait is generic over *S*, which defines application state type. So
application state is accessible from handler with `HttpRequest::state()` method.
But state is accessible as a read-only reference, if you need mutable access to state
you have to implement it yourself. On other hand handler can mutable access it's own state
as `handle` method takes mutable reference to *self*. Beware, actix creates multiple copies
application state is accessible from handler with the `HttpRequest::state()` method.
But state is accessible as a read-only reference - if you need mutable access to state
you have to implement it yourself. On other hand, handler can mutably access its own state
as the `handle` method takes a mutable reference to *self*. Beware, actix creates multiple copies
of application state and handlers, unique for each thread, so if you run your
application in several threads actix will create same amount as number of threads
application in several threads, actix will create the same amount as number of threads
of application state objects and handler objects.
Here is example of handler that stores number of processed requests:
Here is an example of a handler that stores the number of processed requests:
```rust
# extern crate actix;
@ -71,8 +71,8 @@ impl<S> Handler<S> for MyHandler {
# fn main() {}
```
This handler will work, but `self.0` value will be different depends on number of threads and
number of requests processed per thread. Proper implementation would use `Arc` and `AtomicUsize`
This handler will work, but `self.0` will be different depending on the number of threads and
number of requests processed per thread. A proper implementation would use `Arc` and `AtomicUsize`
```rust
# extern crate actix;
@ -115,14 +115,14 @@ fn main() {
```
Be careful with synchronization primitives like *Mutex* or *RwLock*. Actix web framework
handles request asynchronously, by blocking thread execution all concurrent
handles requests asynchronously; by blocking thread execution all concurrent
request handling processes would block. If you need to share or update some state
from multiple threads consider using [actix](https://actix.github.io/actix/actix/) actor system.
from multiple threads consider using the [actix](https://actix.github.io/actix/actix/) actor system.
## Response with custom type
To return custom type directly from handler function, type needs to implement `Responder` trait.
Let's create response for custom type that serializes to `application/json` response:
To return a custom type directly from a handler function, the type needs to implement the `Responder` trait.
Let's create a response for a custom type that serializes to an `application/json` response:
```rust
# extern crate actix;
@ -176,9 +176,8 @@ fn main() {
There are two different types of async handlers.
Response object could be generated asynchronously or more precisely, any type
that implements [*Responder*](../actix_web/trait.Responder.html) trait. In this case handle must
return `Future` object that resolves to *Responder* type, i.e:
Response objects can be generated asynchronously or more precisely, any type
that implements the [*Responder*](../actix_web/trait.Responder.html) trait. In this case the handler must return a `Future` object that resolves to the *Responder* type, i.e:
```rust
# extern crate actix_web;
@ -210,7 +209,7 @@ fn main() {
}
```
Or response body can be generated asynchronously. In this case body
Or the response body can be generated asynchronously. In this case body
must implement stream trait `Stream<Item=Bytes, Error=Error>`, i.e:
```rust
@ -235,10 +234,10 @@ fn main() {
}
```
Both methods could be combined. (i.e Async response with streaming body)
Both methods can be combined. (i.e Async response with streaming body)
It is possible return `Result` which `Result::Item` type could be `Future`.
In this example `index` handler can return error immediately or return
It is possible to return a `Result` where the `Result::Item` type can be `Future`.
In this example the `index` handler can return an error immediately or return a
future that resolves to a `HttpResponse`.
```rust
@ -273,8 +272,8 @@ fn index(req: HttpRequest) -> Result<Box<Future<Item=HttpResponse, Error=Error>>
Sometimes you need to return different types of responses. For example
you can do error check and return error and return async response otherwise.
Or any result that requires two different types.
For this case [*Either*](../actix_web/enum.Either.html) type can be used.
*Either* allows to combine two different responder types into a single type.
For this case the [*Either*](../actix_web/enum.Either.html) type can be used.
*Either* allows combining two different responder types into a single type.
```rust
# extern crate actix_web;
@ -308,9 +307,9 @@ fn index(req: HttpRequest) -> RegisterResult {
## Tokio core handle
Any actix web handler runs within properly configured
Any actix web handler runs within a properly configured
[actix system](https://actix.github.io/actix/actix/struct.System.html)
and [arbiter](https://actix.github.io/actix/actix/struct.Arbiter.html).
You can always get access to tokio handle via
You can always get access to the tokio handle via the
[Arbiter::handle()](https://actix.github.io/actix/actix/struct.Arbiter.html#method.handle)
method.

View File

@ -3,18 +3,18 @@
Actix uses [`Error` type](../actix_web/error/struct.Error.html)
and [`ResponseError` trait](../actix_web/error/trait.ResponseError.html)
for handling handler's errors.
Any error that implements `ResponseError` trait can be returned as error value.
*Handler* can return *Result* object, actix by default provides
`Responder` implementation for compatible result types. Here is implementation
Any error that implements the `ResponseError` trait can be returned as an error value.
*Handler* can return an *Result* object; actix by default provides
`Responder` implementation for compatible result types. Here is the implementation
definition:
```rust,ignore
impl<T: Responder, E: Into<Error>> Responder for Result<T, E>
```
And any error that implements `ResponseError` can be converted into `Error` object.
For example if *handler* function returns `io::Error`, it would be converted
into `HttpInternalServerError` response. Implementation for `io::Error` is provided
And any error that implements `ResponseError` can be converted into an `Error` object.
For example, if the *handler* function returns `io::Error`, it would be converted
into an `HttpInternalServerError` response. Implementation for `io::Error` is provided
by default.
```rust
@ -35,9 +35,9 @@ fn index(req: HttpRequest) -> io::Result<fs::NamedFile> {
## Custom error response
To add support for custom errors, all we need to do is just implement `ResponseError` trait
for custom error. `ResponseError` trait has default implementation
for `error_response()` method, it generates *500* response.
To add support for custom errors, all we need to do is just implement the `ResponseError` trait
for the custom error type. The `ResponseError` trait has a default implementation
for the `error_response()` method: it generates a *500* response.
```rust
# extern crate actix_web;
@ -64,8 +64,8 @@ fn index(req: HttpRequest) -> Result<&'static str, MyError> {
# }
```
In this example *index* handler always returns *500* response. But it is easy
to return different responses for different type of errors.
In this example the *index* handler always returns a *500* response. But it is easy
to return different responses for different types of errors.
```rust
# extern crate actix_web;
@ -108,7 +108,7 @@ fn index(req: HttpRequest) -> Result<&'static str, MyError> {
## Error helpers
Actix provides set of error helper types. It is possible to use them to generate
Actix provides a set of error helper types. It is possible to use them for generating
specific error responses. We can use helper types for the first example with custom error.
```rust
@ -133,16 +133,16 @@ fn index(req: HttpRequest) -> Result<&'static str> {
# }
```
In this example *BAD REQUEST* response get generated for `MyError` error.
In this example, a *BAD REQUEST* response is generated for the `MyError` error.
## Error logging
Actix logs all errors with `WARN` log level. If log level set to `DEBUG`
and `RUST_BACKTRACE` is enabled, backtrace get logged. The Error type uses
cause's error backtrace if available, if the underlying failure does not provide
Actix logs all errors with the log level `WARN`. If log level set to `DEBUG`
and `RUST_BACKTRACE` is enabled, the backtrace gets logged. The Error type uses
the cause's error backtrace if available. If the underlying failure does not provide
a backtrace, a new backtrace is constructed pointing to that conversion point
(rather than the origin of the error). This construction only happens if there
is no underlying backtrace; if it does have a backtrace no new backtrace is constructed.
is no underlying backtrace; if it does have a backtrace, no new backtrace is constructed.
You can enable backtrace and debug logging with following command:

View File

@ -1,23 +1,23 @@
# URL Dispatch
URL dispatch provides a simple way to map URLs to `Handler` code using a simple pattern matching
language. If one of the patterns matches the path information associated with a request,
a particular handler object is invoked. A handler is a specific object that implements
URL dispatch provides a simple way for mapping URLs to `Handler` code using a simple pattern
matching language. If one of the patterns matches the path information associated with a request,
a particular handler object is invoked. A handler is a specific object that implements the
`Handler` trait, defined in your application, that receives the request and returns
a response object. More information is available in [handler section](../qs_4.html).
a response object. More information is available in the [handler section](../qs_4.html).
## Resource configuration
Resource configuration is the act of adding a new resource to an application.
Resource configuration is the act of adding a new resources to an application.
A resource has a name, which acts as an identifier to be used for URL generation.
The name also allows developers to add routes to existing resources.
A resource also has a pattern, meant to match against the *PATH* portion of a *URL*,
it does not match against *QUERY* portion (the portion following the scheme and
it does not match against the *QUERY* portion (the portion following the scheme and
port, e.g., */foo/bar* in the *URL* *http://localhost:8080/foo/bar?q=value*).
The [Application::resource](../actix_web/struct.Application.html#method.resource) methods
add a single resource to application routing table. This method accepts *path pattern*
and resource configuration function.
add a single resource to application routing table. This method accepts a *path pattern*
and a resource configuration function.
```rust
# extern crate actix_web;
@ -37,26 +37,26 @@ fn main() {
}
```
*Configuration function* has following type:
The *Configuration function* has the following type:
```rust,ignore
FnOnce(&mut Resource<_>) -> ()
```
*Configuration function* can set name and register specific routes.
If resource does not contain any route or does not have any matching routes it
returns *NOT FOUND* http resources.
The *Configuration function* can set a name and register specific routes.
If a resource does not contain any route or does not have any matching routes it
returns *NOT FOUND* http response.
## Configuring a Route
Resource contains set of routes. Each route in turn has set of predicates and handler.
New route could be created with `Resource::route()` method which returns reference
to new *Route* instance. By default *route* does not contain any predicates, so matches
all requests and default handler is `HttpNotFound`.
Resource contains a set of routes. Each route in turn has a set of predicates and a handler.
New routes can be created with `Resource::route()` method which returns a reference
to new *Route* instance. By default the *route* does not contain any predicates, so matches
all requests and the default handler is `HttpNotFound`.
Application routes incoming requests based on route criteria which is defined during
The application routes incoming requests based on route criteria which are defined during
resource registration and route registration. Resource matches all routes it contains in
the order that the routes were registered via `Resource::route()`. *Route* can contain
the order the routes were registered via `Resource::route()`. A *Route* can contain
any number of *predicates* but only one handler.
```rust
@ -76,30 +76,30 @@ fn main() {
}
```
In this example `index` get called for *GET* request,
In this example `HttpOk` is returned for *GET* requests,
if request contains `Content-Type` header and value of this header is *text/plain*
and path equals to `/test`. Resource calls handle of the first matches route.
If resource can not match any route "NOT FOUND" response get returned.
and path equals to `/path`. Resource calls handle of the first matching route.
If a resource can not match any route a "NOT FOUND" response is returned.
[*Resource::route()*](../actix_web/struct.Resource.html#method.route) method returns
[*Route*](../actix_web/struct.Route.html) object. Route can be configured with
[*Resource::route()*](../actix_web/struct.Resource.html#method.route) returns a
[*Route*](../actix_web/struct.Route.html) object. Route can be configured with a
builder-like pattern. Following configuration methods are available:
* [*Route::filter()*](../actix_web/struct.Route.html#method.filter) method registers new predicate,
any number of predicates could be registered for each route.
* [*Route::filter()*](../actix_web/struct.Route.html#method.filter) registers a new predicate.
Any number of predicates can be registered for each route.
* [*Route::f()*](../actix_web/struct.Route.html#method.f) method registers handler function
for this route. Only one handler could be registered. Usually handler registration
is the last config operation. Handler function could be function or closure and has type
* [*Route::f()*](../actix_web/struct.Route.html#method.f) registers handler function
for this route. Only one handler can be registered. Usually handler registration
is the last config operation. Handler function can be a function or closure and has the type
`Fn(HttpRequest<S>) -> R + 'static`
* [*Route::h()*](../actix_web/struct.Route.html#method.h) method registers handler object
that implements `Handler` trait. This is similar to `f()` method, only one handler could
* [*Route::h()*](../actix_web/struct.Route.html#method.h) registers a handler object
that implements the `Handler` trait. This is similar to `f()` method - only one handler can
be registered. Handler registration is the last config operation.
* [*Route::a()*](../actix_web/struct.Route.html#method.a) method registers async handler
function for this route. Only one handler could be registered. Handler registration
is the last config operation. Handler function could be function or closure and has type
* [*Route::a()*](../actix_web/struct.Route.html#method.a) registers an async handler
function for this route. Only one handler can be registered. Handler registration
is the last config operation. Handler function can be a function or closure and has the type
`Fn(HttpRequest<S>) -> Future<Item = HttpResponse, Error = Error> + 'static`
## Route matching
@ -110,8 +110,8 @@ against a URL path pattern. `path` represents the path portion of the URL that w
The way that *actix* does this is very simple. When a request enters the system,
for each resource configuration declaration present in the system, actix checks
the request's path against the pattern declared. This checking happens in the order that
the routes were declared via `Application::resource()` method. If resource could not be found,
*default resource* get used as matched resource.
the routes were declared via `Application::resource()` method. If resource can not be found,
the *default resource* is used as the matched resource.
When a route configuration is declared, it may contain route predicate arguments. All route
predicates associated with a route declaration must be `true` for the route configuration to
@ -120,13 +120,13 @@ arguments provided to a route configuration returns `false` during a check, that
skipped and route matching continues through the ordered set of routes.
If any route matches, the route matching process stops and the handler associated with
route get invoked.
the route is invoked.
If no route matches after all route patterns are exhausted, *NOT FOUND* response get returned.
If no route matches after all route patterns are exhausted, a *NOT FOUND* response get returned.
## Resource pattern syntax
The syntax of the pattern matching language used by the actix in the pattern
The syntax of the pattern matching language used by actix in the pattern
argument is straightforward.
The pattern used in route configuration may start with a slash character. If the pattern
@ -261,12 +261,12 @@ foo/abc/def/a/b/c -> Params{'bar':u'abc', 'tail': 'def/a/b/c'}
All values representing matched path segments are available in
[`HttpRequest::match_info`](../actix_web/struct.HttpRequest.html#method.match_info).
Specific value can be received with
[`Params::get()`](../actix_web/dev/struct.Params.html#method.get) method.
Specific values can be retrieved with
[`Params::get()`](../actix_web/dev/struct.Params.html#method.get).
Any matched parameter can be deserialized into specific type if this type
implements `FromParam` trait. For example most of standard integer types
implements `FromParam` trait. i.e.:
Any matched parameter can be deserialized into a specific type if the type
implements the `FromParam` trait. For example most standard integer types
the trait, i.e.:
```rust
# extern crate actix_web;
@ -320,16 +320,15 @@ fn main() {
}
```
List of `FromParam` implementation could be found in
List of `FromParam` implementations can be found in
[api docs](../actix_web/dev/trait.FromParam.html#foreign-impls)
## Path information extractor
Actix provides functionality for type safe request's path information extraction.
Actix provides functionality for type safe request path information extraction.
It uses *serde* package as a deserialization library.
[HttpRequest::extract_path()](../actix_web/struct.HttpRequest.html#method.extract_path)
method extracts information, destination type has to implements `Deserialize` trait
from *serde* libary.
extracts information, the destination type has to implement *serde's *`Deserialize` trait.
```rust
# extern crate bytes;
@ -356,14 +355,14 @@ fn main() {
```
[HttpRequest::extract_query()](../actix_web/struct.HttpRequest.html#method.extract_query)
method provides similar functionality for request's query parameters.
provides similar functionality for request query parameters.
## Generating resource URLs
Use the [HttpRequest.url_for()](../actix_web/struct.HttpRequest.html#method.url_for)
method to generate URLs based on resource patterns. For example, if you've configured a
resource with the name "foo" and the pattern "{a}/{b}/{c}", you might do this.
resource with the name "foo" and the pattern "{a}/{b}/{c}", you might do this:
```rust
# extern crate actix_web;
@ -387,13 +386,13 @@ fn main() {
This would return something like the string *http://example.com/test/1/2/3* (at least if
the current protocol and hostname implied http://example.com).
`url_for()` method return [*Url object*](https://docs.rs/url/1.6.0/url/struct.Url.html) so you
`url_for()` method returns [*Url object*](https://docs.rs/url/1.6.0/url/struct.Url.html) so you
can modify this url (add query parameters, anchor, etc).
`url_for()` could be called only for *named* resources otherwise error get returned.
## External resources
Resources that are valid URLs, could be registered as external resources. They are useful
Resources that are valid URLs, can be registered as external resources. They are useful
for URL generation purposes only and are never considered for matching at request time.
```rust
@ -427,8 +426,8 @@ and 3) append. If the path resolves with
at least one of those conditions, it will redirect to the new path.
If *append* is *true* append slash when needed. If a resource is
defined with trailing slash and the request comes without it, it will
append it automatically.
defined with trailing slash and the request doesn't have one, it will
be appended automatically.
If *merge* is *true*, merge multiple consecutive slashes in the path into one.
@ -450,14 +449,14 @@ fn main() {
}
```
In this example `/resource`, `//resource///` will be redirected to `/resource/` url.
In this example `/resource`, `//resource///` will be redirected to `/resource/`.
In this example path normalization handler get registered for all method,
In this example path normalization handler is registered for all methods,
but you should not rely on this mechanism to redirect *POST* requests. The redirect of the
slash-appending *Not Found* will turn a *POST* request into a GET, losing any
*POST* data in the original request.
It is possible to register path normalization only for *GET* requests only
It is possible to register path normalization only for *GET* requests only:
```rust
# extern crate actix_web;
@ -475,9 +474,9 @@ fn main() {
}
```
## Using a Application Prefix to Compose Applications
## Using an Application Prefix to Compose Applications
The `Application::prefix()`" method allows to set specific application prefix.
The `Application::prefix()`" method allows to set a specific application prefix.
This prefix represents a resource prefix that will be prepended to all resource patterns added
by the resource configuration. This can be used to help mount a set of routes at a different
location than the included callable's author intended while still maintaining the same
@ -509,13 +508,13 @@ it will generate a URL with that same path.
## Custom route predicates
You can think of predicate as simple function that accept *request* object reference
and returns *true* or *false*. Formally predicate is any object that implements
You can think of a predicate as a simple function that accepts a *request* object reference
and returns *true* or *false*. Formally, a predicate is any object that implements the
[`Predicate`](../actix_web/pred/trait.Predicate.html) trait. Actix provides
several predicates, you can check [functions section](../actix_web/pred/index.html#functions)
of api docs.
Here is simple predicates that check that request contains specific *header*:
Here is a simple predicate that check that a request contains a specific *header*:
```rust
# extern crate actix_web;
@ -545,9 +544,9 @@ fn main() {
In this example *index* handler will be called only if request contains *CONTENT-TYPE* header.
Predicates can have access to application's state via `HttpRequest::state()` method.
Predicates have access to the application's state via `HttpRequest::state()`.
Also predicates can store extra information in
[requests`s extensions](../actix_web/struct.HttpRequest.html#method.extensions).
[request extensions](../actix_web/struct.HttpRequest.html#method.extensions).
### Modifying predicate values
@ -572,14 +571,14 @@ fn main() {
}
```
`Any` predicate accept list of predicates and matches if any of the supplied
The `Any` predicate accepts a list of predicates and matches if any of the supplied
predicates match. i.e:
```rust,ignore
pred::Any(pred::Get()).or(pred::Post())
```
`All` predicate accept list of predicates and matches if all of the supplied
The `All` predicate accepts a list of predicates and matches if all of the supplied
predicates match. i.e:
```rust,ignore
@ -588,10 +587,10 @@ predicates match. i.e:
## Changing the default Not Found response
If path pattern can not be found in routing table or resource can not find matching
route, default resource is used. Default response is *NOT FOUND* response.
It is possible to override *NOT FOUND* response with `Application::default_resource()` method.
This method accepts *configuration function* same as normal resource configuration
If the path pattern can not be found in the routing table or a resource can not find matching
route, the default resource is used. The default response is *NOT FOUND*.
It is possible to override the *NOT FOUND* response with `Application::default_resource()`.
This method accepts a *configuration function* same as normal resource configuration
with `Application::resource()` method.
```rust

View File

@ -2,13 +2,13 @@
## Response
Builder-like patter is used to construct an instance of `HttpResponse`.
`HttpResponse` provides several method that returns `HttpResponseBuilder` instance,
which is implements various convenience methods that helps build response.
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 description. Methods `.body`, `.finish`, `.json` finalizes response creation and
returns constructed *HttpResponse* instance. if this methods get called for the same
builder instance multiple times, builder will panic.
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
builder instance multiple times, the builder will panic.
```rust
# extern crate actix_web;
@ -27,22 +27,22 @@ fn index(req: HttpRequest) -> HttpResponse {
## Content encoding
Actix automatically *compress*/*decompress* payload. Following codecs are supported:
Actix automatically *compresses*/*decompresses* payloads. Following codecs are supported:
* Brotli
* Gzip
* Deflate
* Identity
If request headers contains `Content-Encoding` header, request payload get decompressed
according to header value. Multiple codecs are not supported, i.e: `Content-Encoding: br, gzip`.
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`.
Response payload get compressed based on *content_encoding* parameter.
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 request's `Accept-Encoding` header.
`ContentEncoding::Identity` could be used to disable compression.
If other content encoding is selected the compression is enforced for this codec. For example,
to enable `brotli` response's body compression use `ContentEncoding::Br`:
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`:
```rust
# extern crate actix_web;
@ -60,11 +60,11 @@ fn index(req: HttpRequest) -> HttpResponse {
## JSON Request
There are two options of json body deserialization.
There are two options for json body deserialization.
First option is to use *HttpResponse::json()* method. This method returns
The first option is to use *HttpResponse::json()*. This method returns a
[*JsonBody*](../actix_web/dev/struct.JsonBody.html) object which resolves into
deserialized value.
the deserialized value.
```rust
# extern crate actix;
@ -91,9 +91,9 @@ fn index(mut req: HttpRequest) -> Box<Future<Item=HttpResponse, Error=Error>> {
# fn main() {}
```
Or you can manually load payload into memory and then deserialize it.
Here is simple example. We will deserialize *MyObj* struct. We need to load request
body first and then deserialize json into object.
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
body first and then deserialize the json into an object.
```rust
# extern crate actix_web;
@ -124,7 +124,7 @@ fn index(req: HttpRequest) -> Box<Future<Item=HttpResponse, Error=Error>> {
# fn main() {}
```
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/).
@ -157,14 +157,14 @@ fn main() {
## Chunked transfer encoding
Actix automatically decode *chunked* encoding. `HttpRequest::payload()` already contains
decoded bytes stream. If request payload compressed with one of supported
compression codecs (br, gzip, deflate) bytes stream get decompressed.
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.
Chunked encoding on response could be enabled with `HttpResponseBuilder::chunked()` method.
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
get enabled automatically.
is enabled automatically.
Enabling chunked encoding for *HTTP/2.0* responses is forbidden.
@ -189,11 +189,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 could be
[*Field*](../actix_web/multipart/struct.Field.html) or nested *Multipart* stream.
`HttpResponse::multipart()` method returns *Multipart* stream for current request.
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 could be implemented similar to this example
In simple form multipart stream handling can be implemented similar to this example
```rust,ignore
# extern crate actix_web;
@ -223,16 +223,16 @@ fn index(req: HttpRequest) -> Box<Future<...>> {
}
```
Full example is available in
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 body.
`HttpResponse::urlencoded()` method returns
[*UrlEncoded*](../actix_web/dev/struct.UrlEncoded.html) future, it resolves
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
into `HashMap<String, String>` which contains decoded parameters.
*UrlEncoded* future can resolve into a error in several cases:
The *UrlEncoded* future can resolve into a error in several cases:
* content type is not `application/x-www-form-urlencoded`
* transfer encoding is `chunked`.
@ -261,10 +261,10 @@ fn index(mut req: HttpRequest) -> Box<Future<Item=HttpResponse, Error=Error>> {
## Streaming request
*HttpRequest* is a stream of `Bytes` objects. It could be used to read request
*HttpRequest* is a stream of `Bytes` objects. It can be used to read the request
body payload.
In this example handle reads request payload chunk by chunk and prints every chunk.
In this example handle reads the request payload chunk by chunk and prints every chunk.
```rust
# extern crate actix_web;

View File

@ -1,14 +1,14 @@
# Testing
Every application should be well tested and. Actix provides the tools to perform unit and
Every application should be well tested. Actix provides tools to perform unit and
integration tests.
## Unit tests
For unit testing actix provides request builder type and simple handler runner.
[*TestRequest*](../actix_web/test/struct.TestRequest.html) implements builder-like pattern.
You can generate `HttpRequest` instance with `finish()` method or you can
run your handler with `run()` or `run_async()` methods.
For unit testing actix provides a request builder type and 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
run your handler with `run()` or `run_async()`.
```rust
# extern crate http;
@ -44,13 +44,13 @@ fn main() {
There are several methods how you can test your application. Actix provides
[*TestServer*](../actix_web/test/struct.TestServer.html)
server that could be used to run whole application of just specific handlers
in real http server. *TrstServer::get()*, *TrstServer::post()* or *TrstServer::client()*
methods could be used to send request to test server.
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()*
methods can be used to send requests to the test server.
In simple form *TestServer* could be configured to use handler. *TestServer::new* method
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 [api documentation](../actix_web/test/struct.TestApp.html)
instance. You can check the [api documentation](../actix_web/test/struct.TestApp.html)
for more information.
```rust
@ -73,8 +73,8 @@ fn main() {
}
```
Other option is to use application factory. In this case you need to pass factory function
same as you use for real http server configuration.
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.
```rust
# extern crate http;
@ -105,13 +105,13 @@ fn main() {
## WebSocket server tests
It is possible to register *handler* with `TestApp::handler()` method that
initiate web socket connection. *TestServer* provides `ws()` which connects to
websocket server and returns ws reader and writer objects. *TestServer* also
provides `execute()` method which runs future object to completion and returns
It is possible to register a *handler* with `TestApp::handler()` that
initiates a web socket connection. *TestServer* provides `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
result of the future computation.
Here is simple example, that shows how to test server websocket handler.
Here is a simple example that shows how to test server websocket handler.
```rust
# extern crate actix;

View File

@ -1,12 +1,12 @@
# WebSockets
Actix supports WebSockets out-of-the-box. It is possible to convert 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
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
with http actor.
with an http actor.
This is example of simple websocket echo server:
This is example of a simple websocket echo server:
```rust
# extern crate actix;
@ -41,8 +41,8 @@ fn main() {
}
```
Simple websocket echo server example is available in
A simple websocket echo server example is available in the
[examples directory](https://github.com/actix/actix-web/blob/master/examples/websocket).
Example chat server with ability to chat over websocket connection 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/)