Skip to content

Commit

Permalink
Merge branch 'master' into add-wrap-fn
Browse files Browse the repository at this point in the history
  • Loading branch information
jxs authored Aug 20, 2020
2 parents 7e72e0c + 6276e87 commit 4658343
Show file tree
Hide file tree
Showing 16 changed files with 286 additions and 25 deletions.
36 changes: 36 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: bug
assignees: ''

---

**Version**
List the versions of all `warp` crates you are using. The easiest way to get
this information is using `cargo-tree`.

`cargo install cargo-tree`
(see install here: https://github.com/sfackler/cargo-tree)

Then:

`cargo tree | grep warp`

**Platform**
The output of `uname -a` (UNIX), or version and 32 or 64-bit (Windows)

**Description**
Enter your issue details here.
One way to structure the description:

[short summary of the bug]

I tried this code:

[code sample that causes the bug]

I expected to see this happen: [explanation]

Instead, this happened: [explanation]
20 changes: 20 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: feature
assignees: ''

---

**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

**Describe the solution you'd like**
A clear and concise description of what you want to happen.

**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.

**Additional context**
Add any other context or screenshots about the feature request here.
14 changes: 14 additions & 0 deletions .github/ISSUE_TEMPLATE/question.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
name: Question
about: Please use Discord channel for questions
title: ''
labels: ''
assignees: ''

---

Please post your question the warp Discord channel:
using the #warp channel on https://discord.gg/tokio.

You may also be able to find help here:
https://users.rust-lang.org/
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
### v0.2.4 (July 20, 2020)

- **Features**:
- Add `tracing` internals in place of `log` (log is still emitted for backwards compatibility).
- Add `warp::trace` module set of filters to customize `tracing` dianostics.
- Add `path` method to `warp::fs::File` reply.
- Add `source` implementation for `BodyDeserializeError`.
- Make `warp::ws::MissingConnectionUpgrade` rejection public.

### v0.2.3 (May 19, 2020)

- **Features**:
Expand Down
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "warp"
version = "0.2.3" # don't forget to update html_root_url
version = "0.2.4" # don't forget to update html_root_url
description = "serve the web at warp speeds"
authors = ["Sean McArthur <[email protected]>"]
license = "MIT"
Expand All @@ -26,7 +26,7 @@ hyper = { version = "0.13", features = ["stream"] }
log = "0.4"
mime = "0.3"
mime_guess = "2.0.0"
multipart = { version = "0.16", default-features = false, features = ["server"], optional = true }
multipart = { version = "0.17", default-features = false, features = ["server"], optional = true }
scoped-tls = "1.0"
serde = "1.0"
serde_json = "1.0"
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Since it builds on top of [hyper](https://hyper.rs), you automatically get:
Add warp and Tokio to your dependencies:

```toml
tokio = { version = "0.2", features = ["macros"] }
tokio = { version = "0.2", features = ["full"] }
warp = "0.2"
```

Expand Down
2 changes: 1 addition & 1 deletion examples/tracing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
//! demonstrates how the `warp::trace` module can be used to instrument `warp`
//! applications with `tracing`.
//!
//! [`tracing`]: https://crates.io/tracing
//! [`tracing`]: https://crates.io/crates/tracing
#![deny(warnings)]
use tracing_subscriber::fmt::format::FmtSpan;
use warp::Filter;
Expand Down
2 changes: 1 addition & 1 deletion src/filters/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ pub fn exact(
///
/// ```
/// // Require `connection: keep-alive` header to be set.
/// let keep_alive = warp::header::exact("connection", "keep-alive");
/// let keep_alive = warp::header::exact_ignore_case("connection", "keep-alive");
/// ```
pub fn exact_ignore_case(
name: &'static str,
Expand Down
96 changes: 96 additions & 0 deletions src/filters/host.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
//! Host ("authority") filter
//!
use crate::filter::{filter_fn_one, Filter, One};
use crate::reject::{self, Rejection};
use futures::future;
pub use http::uri::Authority;
use std::str::FromStr;

/// Creates a `Filter` that requires a specific authority (target server's
/// host and port) in the request.
///
/// Authority is specified either in the `Host` header or in the target URI.
///
/// # Example
///
/// ```
/// use warp::Filter;
///
/// let multihost =
/// warp::host::exact("foo.com").map(|| "you've reached foo.com")
/// .or(warp::host::exact("bar.com").map(|| "you've reached bar.com"));
/// ```
pub fn exact(expected: &str) -> impl Filter<Extract = (), Error = Rejection> + Clone {
let expected = Authority::from_str(expected).expect("invalid host/authority");
optional()
.and_then(move |option: Option<Authority>| match option {
Some(authority) if authority == expected => future::ok(()),
_ => future::err(reject::not_found()),
})
.untuple_one()
}

/// Creates a `Filter` that looks for an authority (target server's host
/// and port) in the request.
///
/// Authority is specified either in the `Host` header or in the target URI.
///
/// If found, extracts the `Authority`, otherwise continues the request,
/// extracting `None`.
///
/// Rejects with `400 Bad Request` if the `Host` header is malformed or if there
/// is a mismatch between the `Host` header and the target URI.
///
/// # Example
///
/// ```
/// use warp::{Filter, host::Authority};
///
/// let host = warp::host::optional()
/// .map(|authority: Option<Authority>| {
/// if let Some(a) = authority {
/// format!("{} is currently not at home", a.host())
/// } else {
/// "please state who you're trying to reach".to_owned()
/// }
/// });
/// ```
pub fn optional() -> impl Filter<Extract = One<Option<Authority>>, Error = Rejection> + Copy {
filter_fn_one(move |route| {
// The authority can be sent by clients in various ways:
//
// 1) in the "target URI"
// a) serialized in the start line (HTTP/1.1 proxy requests)
// b) serialized in `:authority` pseudo-header (HTTP/2 generated - "SHOULD")
// 2) in the `Host` header (HTTP/1.1 origin requests, HTTP/2 converted)
//
// Hyper transparently handles 1a/1b, but not 2, so we must look at both.

let from_uri = route.uri().authority();

let name = "host";
let from_header = route.headers()
.get(name)
.map(|value|
// Header present, parse it
value.to_str().map_err(|_| reject::invalid_header(name))
.and_then(|value| Authority::from_str(value).map_err(|_| reject::invalid_header(name)))
);

future::ready(match (from_uri, from_header) {
// no authority in the request (HTTP/1.0 or non-conforming)
(None, None) => Ok(None),

// authority specified in either or both matching
(Some(a), None) => Ok(Some(a.clone())),
(None, Some(Ok(a))) => Ok(Some(a)),
(Some(a), Some(Ok(b))) if *a == b => Ok(Some(b)),

// mismatch
(Some(_), Some(Ok(_))) => Err(reject::invalid_header(name)),

// parse error
(_, Some(Err(r))) => Err(r),
})
})
}
1 change: 1 addition & 0 deletions src/filters/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub mod cors;
pub mod ext;
pub mod fs;
pub mod header;
pub mod host;
pub mod log;
pub mod method;
#[cfg(feature = "multipart")]
Expand Down
2 changes: 1 addition & 1 deletion src/filters/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,7 @@ fn path_and_query(route: &Route) -> PathAndQuery {
/// Any number of either type identifiers or string expressions can be passed,
/// each separated by a forward slash (`/`). Strings will be used to match
/// path segments exactly, and type identifiers are used just like
/// [`param`](filters::path::param) filters.
/// [`param`](crate::path::param) filters.
///
/// # Example
///
Expand Down
4 changes: 2 additions & 2 deletions src/filters/sse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ where
/// ```
pub fn reply<S>(event_stream: S) -> impl Reply
where
S: TryStream + Send + Sync + 'static,
S: TryStream + Send + 'static,
S::Ok: ServerSentEvent,
S::Error: StdError + Send + Sync + 'static,
{
Expand All @@ -399,7 +399,7 @@ struct SseReply<S> {

impl<S> Reply for SseReply<S>
where
S: TryStream + Send + Sync + 'static,
S: TryStream + Send + 'static,
S::Ok: ServerSentEvent,
S::Error: StdError + Send + Sync + 'static,
{
Expand Down
7 changes: 2 additions & 5 deletions src/filters/trace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,7 @@ pub fn request() -> Trace<impl Fn(Info) -> Span + Clone> {
span.record("referer", &display(referer));
}

// The the headers are, potentially, quite long, so let's record them in
// an event within the generated span, rather than including them as
// context on *every* request.
tracing::debug!(parent: &span, headers = ?info.headers(), "received request");
tracing::debug!(parent: &span, "received request");

span
})
Expand Down Expand Up @@ -205,7 +202,7 @@ impl<'a> Info<'a> {
}

/// View the request headers.
pub fn headers(&self) -> &http::HeaderMap {
pub fn request_headers(&self) -> &http::HeaderMap {
self.route.headers()
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#![doc(html_root_url = "https://docs.rs/warp/0.2.3")]
#![doc(html_root_url = "https://docs.rs/warp/0.2.4")]
#![deny(missing_docs)]
#![deny(missing_debug_implementations)]
#![cfg_attr(test, deny(warnings))]
Expand Down Expand Up @@ -132,6 +132,7 @@ pub use self::filters::{
header,
// header() function
header::header,
host,
log,
// log() function
log::log,
Expand Down
22 changes: 11 additions & 11 deletions src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ where
<F::Future as TryFuture>::Error: IsReject,
{
/// Run this `Server` forever on the current thread.
pub async fn run(self, addr: impl Into<SocketAddr> + 'static) {
pub async fn run(self, addr: impl Into<SocketAddr>) {
let (addr, fut) = self.bind_ephemeral(addr);
let span = tracing::info_span!("Server::run", ?addr);
tracing::info!(parent: &span, "listening on http://{}", addr);
Expand Down Expand Up @@ -180,7 +180,7 @@ where
///
/// In case we are unable to bind to the specified address, resolves to an
/// error and logs the reason.
pub async fn try_bind(self, addr: impl Into<SocketAddr> + 'static) {
pub async fn try_bind(self, addr: impl Into<SocketAddr>) {
let addr = addr.into();
let srv = match try_bind!(self, &addr) {
Ok((_, srv)) => srv,
Expand Down Expand Up @@ -208,7 +208,7 @@ where
/// Panics if we are unable to bind to the provided address.
pub fn bind_ephemeral(
self,
addr: impl Into<SocketAddr> + 'static,
addr: impl Into<SocketAddr>,
) -> (SocketAddr, impl Future<Output = ()> + 'static) {
let (addr, srv) = bind!(self, addr);
let srv = srv.map(|result| {
Expand All @@ -229,7 +229,7 @@ where
/// any runtime.
pub fn try_bind_ephemeral(
self,
addr: impl Into<SocketAddr> + 'static,
addr: impl Into<SocketAddr>,
) -> Result<(SocketAddr, impl Future<Output = ()> + 'static), crate::Error> {
let addr = addr.into();
let (addr, srv) = try_bind!(self, &addr).map_err(crate::Error::new)?;
Expand Down Expand Up @@ -314,9 +314,9 @@ where
/// This can be used for Unix Domain Sockets, or TLS, etc.
///
/// Returns a `Future` that can be executed on any runtime.
pub fn serve_incoming<I>(self, incoming: I) -> impl Future<Output = ()> + 'static
pub fn serve_incoming<I>(self, incoming: I) -> impl Future<Output = ()>
where
I: TryStream + Send + 'static,
I: TryStream + Send,
I::Ok: AsyncRead + AsyncWrite + Send + 'static + Unpin,
I::Error: Into<Box<dyn StdError + Send + Sync>>,
{
Expand All @@ -338,9 +338,9 @@ where
self,
incoming: I,
signal: impl Future<Output = ()> + Send + 'static,
) -> impl Future<Output = ()> + 'static
) -> impl Future<Output = ()>
where
I: TryStream + Send + 'static,
I: TryStream + Send,
I::Ok: AsyncRead + AsyncWrite + Send + 'static + Unpin,
I::Error: Into<Box<dyn StdError + Send + Sync>>,
{
Expand Down Expand Up @@ -449,7 +449,7 @@ where
/// Run this `TlsServer` forever on the current thread.
///
/// *This function requires the `"tls"` feature.*
pub async fn run(self, addr: impl Into<SocketAddr> + 'static) {
pub async fn run(self, addr: impl Into<SocketAddr>) {
let (addr, fut) = self.bind_ephemeral(addr);
let span = tracing::info_span!("TlsServer::run", %addr);
tracing::info!(parent: &span, "listening on https://{}", addr);
Expand All @@ -461,7 +461,7 @@ where
/// executed on a runtime.
///
/// *This function requires the `"tls"` feature.*
pub async fn bind(self, addr: impl Into<SocketAddr> + 'static) {
pub async fn bind(self, addr: impl Into<SocketAddr>) {
let (_, fut) = self.bind_ephemeral(addr);
fut.await;
}
Expand All @@ -474,7 +474,7 @@ where
/// *This function requires the `"tls"` feature.*
pub fn bind_ephemeral(
self,
addr: impl Into<SocketAddr> + 'static,
addr: impl Into<SocketAddr>,
) -> (SocketAddr, impl Future<Output = ()> + 'static) {
let (addr, srv) = bind!(tls: self, addr);
let srv = srv.map(|result| {
Expand Down
Loading

0 comments on commit 4658343

Please sign in to comment.