error.rs |
|
1829 |
filter |
|
|
filters |
|
|
generic.rs |
|
5434 |
lib.rs |
# warp
warp is a super-easy, composable, web server framework for warp speeds.
Thanks to its [`Filter`][Filter] system, warp provides these out of the box:
- Path routing and parameter extraction
- Header requirements and extraction
- Query string deserialization
- JSON and Form bodies
- Multipart form data
- Static Files and Directories
- Websockets
- Access logging
- Etc
Since it builds on top of [hyper](https://hyper.rs), you automatically get:
- HTTP/1
- HTTP/2
- Asynchronous
- One of the fastest HTTP implementations
- Tested and **correct**
## Filters
The main concept in warp is the [`Filter`][Filter], which allows composition
to describe various endpoints in your web service. Besides this powerful
trait, warp comes with several built in [filters](filters/index.html), which
can be combined for your specific needs.
As a small example, consider an endpoint that has path and header requirements:
```
use warp::Filter;
let hi = warp::path("hello")
.and(warp::path::param())
.and(warp::header("user-agent"))
.map(|param: String, agent: String| {
format!("Hello {}, whose agent is {}", param, agent)
});
```
This example composes several [`Filter`s][Filter] together using `and`:
- A path prefix of "hello"
- A path parameter of a `String`
- The `user-agent` header parsed as a `String`
These specific filters will [`reject`][reject] requests that don't match
their requirements.
This ends up matching requests like:
```notrust
GET /hello/sean HTTP/1.1
Host: hyper.rs
User-Agent: reqwest/v0.8.6
```
And it returns a response similar to this:
```notrust
HTTP/1.1 200 OK
Content-Length: 41
Date: ...
Hello sean, whose agent is reqwest/v0.8.6
```
Take a look at the full list of [`filters`](filters/index.html) to see what
you can build.
## Testing
Testing your web services easily is extremely important, and warp provides
a [`test`](mod@self::test) module to help send mocked requests through your service.
[Filter]: trait.Filter.html
[reject]: reject/index.html |
4378 |
redirect.rs |
Redirect requests to a new location.
The types in this module are helpers that implement [`Reply`], and easy
to use in order to setup redirects. |
5601 |
reject.rs |
Rejections
Part of the power of the [`Filter`](../trait.Filter.html) system is being able to
reject a request from a filter chain. This allows for filters to be
combined with `or`, so that if one side of the chain finds that a request
doesn't fulfill its requirements, the other side can try to process
the request.
Many of the built-in [`filters`](../filters) will automatically reject
the request with an appropriate rejection. However, you can also build
new custom [`Filter`](../trait.Filter.html)s and still want other routes to be
matchable in the case a predicate doesn't hold.
As a request is processed by a Filter chain, the rejections are accumulated into
a list contained by the [`Rejection`](struct.Rejection.html) type. Rejections from
filters can be handled using [`Filter::recover`](../trait.Filter.html#method.recover).
This is a convenient way to map rejections into a [`Reply`](../reply/trait.Reply.html).
For a more complete example see the
[Rejection Example](https://github.com/seanmonstar/warp/blob/master/examples/rejections.rs)
from the repository.
# Example
```
use warp::{reply, Reply, Filter, reject, Rejection, http::StatusCode};
#[derive(Debug)]
struct InvalidParameter;
impl reject::Reject for InvalidParameter {}
// Custom rejection handler that maps rejections into responses.
async fn handle_rejection(err: Rejection) -> Result<impl Reply, std::convert::Infallible> {
if err.is_not_found() {
Ok(reply::with_status("NOT_FOUND", StatusCode::NOT_FOUND))
} else if let Some(e) = err.find::<InvalidParameter>() {
Ok(reply::with_status("BAD_REQUEST", StatusCode::BAD_REQUEST))
} else {
eprintln!("unhandled rejection: {:?}", err);
Ok(reply::with_status("INTERNAL_SERVER_ERROR", StatusCode::INTERNAL_SERVER_ERROR))
}
}
// Filter on `/:id`, but reject with InvalidParameter if the `id` is `0`.
// Recover from this rejection using a custom rejection handler.
let route = warp::path::param()
.and_then(|id: u32| async move {
if id == 0 {
Err(warp::reject::custom(InvalidParameter))
} else {
Ok("id is valid")
}
})
.recover(handle_rejection);
``` |
25650 |
reply.rs |
Reply to requests.
A [`Reply`](./trait.Reply.html) is a type that can be converted into an HTTP
response to be sent to the client. These are typically the successful
counterpart to a [rejection](../reject).
The functions in this module are helpers for quickly creating a reply.
Besides them, you can return a type that implements [`Reply`](./trait.Reply.html). This
could be any of the following:
- [`http::Response<impl Into<hyper::Body>>`](https://docs.rs/http)
- `String`
- `&'static str`
- `http::StatusCode`
# Example
```
use warp::{Filter, http::Response};
// Returns an empty `200 OK` response.
let empty_200 = warp::any().map(warp::reply);
// Returns a `200 OK` response with custom header and body.
let custom = warp::any().map(|| {
Response::builder()
.header("my-custom-header", "some-value")
.body("and a custom body")
});
// GET requests return the empty 200, POST return the custom.
let routes = warp::get().and(empty_200)
.or(warp::post().and(custom));
``` |
13898 |
route.rs |
|
3275 |
server.rs |
|
19996 |
service.rs |
Convert `Filter`s into `Service`s |
80 |
test.rs |
Test utilities to test your filters.
[`Filter`](../trait.Filter.html)s can be easily tested without starting up an HTTP
server, by making use of the [`RequestBuilder`](./struct.RequestBuilder.html) in this
module.
# Testing Filters
It's easy to test filters, especially if smaller filters are used to build
up your full set. Consider these example filters:
```
use warp::Filter;
fn sum() -> impl Filter<Extract = (u32,), Error = warp::Rejection> + Copy {
warp::path::param()
.and(warp::path::param())
.map(|x: u32, y: u32| {
x + y
})
}
fn math() -> impl Filter<Extract = (String,), Error = warp::Rejection> + Copy {
warp::post()
.and(sum())
.map(|z: u32| {
format!("Sum = {}", z)
})
}
```
We can test some requests against the `sum` filter like this:
```
# use warp::Filter;
#[tokio::test]
async fn test_sum() {
# let sum = || warp::any().map(|| 3);
let filter = sum();
// Execute `sum` and get the `Extract` back.
let value = warp::test::request()
.path("/1/2")
.filter(&filter)
.await
.unwrap();
assert_eq!(value, 3);
// Or simply test if a request matches (doesn't reject).
assert!(
warp::test::request()
.path("/1/-5")
.matches(&filter)
.await
);
}
```
If the filter returns something that implements `Reply`, and thus can be
turned into a response sent back to the client, we can test what exact
response is returned. The `math` filter uses the `sum` filter, but returns
a `String` that can be turned into a response.
```
# use warp::Filter;
#[test]
fn test_math() {
# let math = || warp::any().map(warp::reply);
let filter = math();
let res = warp::test::request()
.path("/1/2")
.reply(&filter);
assert_eq!(res.status(), 405, "GET is not allowed");
let res = warp::test::request()
.method("POST")
.path("/1/2")
.reply(&filter);
assert_eq!(res.status(), 200);
assert_eq!(res.body(), "Sum is 3");
}
``` |
21208 |
tls.rs |
|
14850 |
transport.rs |
|
1421 |