Skip to content

Commit

Permalink
Merge pull request #21 from stephank/hyper-0.13
Browse files Browse the repository at this point in the history
Hyper 0.13
  • Loading branch information
Stéphan Kochen authored Dec 13, 2019
2 parents 6177c70 + 1b3a4bb commit 19d34d2
Show file tree
Hide file tree
Showing 14 changed files with 493 additions and 677 deletions.
18 changes: 10 additions & 8 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,27 +1,29 @@
[package]
name = "hyper-staticfile"
version = "0.4.2"
version = "0.5.0"
authors = [
"Zach Pomerantz <zmp@umich.edu>",
"Jonathan Reem <jonathan.reem@gmail.com>",
"Stéphan Kochen <stephan@kochen.nl>",
]
description = "Static file serving for Hyper 0.12"
description = "Static file serving for Hyper 0.13"
repository = "https://github.com/stephank/hyper-staticfile"
license = "MIT"
readme = "README.md"
documentation = "https://docs.rs/hyper-staticfile"
keywords = ["hyper", "web", "http", "file", "static"]
categories = ["web-programming::http-server"]
edition = "2018"

[dependencies]
chrono = "0.4.2"
futures = "0.1.21"
http = "0.1.5"
hyper = "0.12.1"
tokio = "0.1.7"
url = "1.7.0"
chrono = "0.4.10"
futures-util = "0.3.1"
http = "0.2.0"
hyper = "0.13.0"
mime_guess = "2.0.1"
percent-encoding = "2.1.0"
tokio = { version = "0.2.4", features = ["fs", "macros"] }
url = "2.1.0"

[dev-dependencies]
tempdir = "0.3.7"
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
[![Crate](https://img.shields.io/crates/v/hyper-staticfile.svg)](https://crates.io/crates/hyper-staticfile)
[![Build Status](https://travis-ci.org/stephank/hyper-staticfile.svg?branch=master)](https://travis-ci.org/stephank/hyper-staticfile)

Static file-serving for [Hyper 0.12](https://github.com/hyperium/hyper).
Static file-serving for [Hyper 0.13](https://github.com/hyperium/hyper).

See [`examples/doc_server.rs`](examples/doc_server.rs) for a complete example that you can compile.

Expand Down
89 changes: 25 additions & 64 deletions examples/doc_server.rs
Original file line number Diff line number Diff line change
@@ -1,80 +1,41 @@
extern crate futures;
extern crate http;
extern crate hyper;
extern crate hyper_staticfile;

// This example serves the docs from `target/doc/`.
//
// Run `cargo doc && cargo run --example doc_server`, then
// point your browser to http://localhost:3000/

use futures::{future, Async::*, Future, Poll};
use futures_util::future;
use http::response::Builder as ResponseBuilder;
use http::{header, Request, Response, StatusCode};
use hyper::Body;
use hyper_staticfile::{Static, StaticFuture};
use std::io::Error;
use http::{header, StatusCode};
use hyper::service::{make_service_fn, service_fn};
use hyper::{Body, Request, Response};
use hyper_staticfile::Static;
use std::io::Error as IoError;
use std::path::Path;

/// Future returned from `MainService`.
enum MainFuture {
Root,
Static(StaticFuture<Body>),
}

impl Future for MainFuture {
type Item = Response<Body>;
type Error = Error;

fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
match *self {
MainFuture::Root => {
let res = ResponseBuilder::new()
.status(StatusCode::MOVED_PERMANENTLY)
.header(header::LOCATION, "/hyper_staticfile/")
.body(Body::empty())
.expect("unable to build response");
Ok(Ready(res))
}
MainFuture::Static(ref mut future) => future.poll(),
}
async fn handle_request<B>(req: Request<B>, static_: Static) -> Result<Response<Body>, IoError> {
if req.uri().path() == "/" {
let res = ResponseBuilder::new()
.status(StatusCode::MOVED_PERMANENTLY)
.header(header::LOCATION, "/hyper_staticfile/")
.body(Body::empty())
.expect("unable to build response");
Ok(res)
} else {
static_.clone().serve(req).await
}
}

/// Hyper `Service` implementation that serves all requests.
struct MainService {
static_: Static,
}
#[tokio::main]
async fn main() {
let static_ = Static::new(Path::new("target/doc/"));

impl MainService {
fn new() -> MainService {
MainService {
static_: Static::new(Path::new("target/doc/")),
}
}
}

impl hyper::service::Service for MainService {
type ReqBody = Body;
type ResBody = Body;
type Error = Error;
type Future = MainFuture;

fn call(&mut self, req: Request<Body>) -> MainFuture {
if req.uri().path() == "/" {
MainFuture::Root
} else {
MainFuture::Static(self.static_.serve(req))
}
}
}
let make_service = make_service_fn(|_| {
let static_ = static_.clone();
future::ok::<_, hyper::Error>(service_fn(move |req| handle_request(req, static_.clone())))
});

/// Application entry point.
fn main() {
let addr = ([127, 0, 0, 1], 3000).into();
let server = hyper::Server::bind(&addr)
.serve(|| future::ok::<_, Error>(MainService::new()))
.map_err(|e| eprintln!("server error: {}", e));
let server = hyper::Server::bind(&addr).serve(make_service);
eprintln!("Doc server running on http://{}/", addr);
hyper::rt::run(server);
server.await.expect("Server failed");
}
82 changes: 33 additions & 49 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#![deny(missing_docs)]
#![deny(warnings)]

//! Static file-serving for [Hyper 0.12](https://github.com/hyperium/hyper).
//! Static file-serving for [Hyper 0.13](https://github.com/hyperium/hyper).
//!
//! This library exports a high-level interface `Static` for simple file-serving, and lower-level
//! interfaces for more control over responses.
Expand All @@ -14,18 +14,15 @@
//! trait. It can be used as:
//!
//! ```rust
//! extern crate http;
//! extern crate hyper_staticfile;
//!
//! // Instance of `Static`. Can be reused for multiple requests.
//! // Instance of `Static` containing configuration.
//! let static_ = hyper_staticfile::Static::new("my/doc/root/");
//!
//! // A dummy request, but normally obtained from Hyper.
//! let request = http::Request::get("/foo/bar.txt")
//! .body(())
//! .unwrap();
//!
//! // Serve the request. Returns a `StaticFuture` for a response.
//! // Serve the request. Returns a future for a `hyper::Response`.
//! let response_future = static_.serve(request);
//! ```
//!
Expand All @@ -38,35 +35,34 @@
//! same by doing something similar to the following:
//!
//! ```rust
//! extern crate futures;
//! extern crate http;
//! extern crate hyper_staticfile;
//!
//! use futures::future::Future;
//! use std::path::Path;
//!
//! // Document root path.
//! let root = Path::new("my/doc/root/");
//!
//! // A dummy request, but normally obtained from Hyper.
//! let request = http::Request::get("/foo/bar.txt")
//! .body(())
//! .unwrap();
//!
//! // First, resolve the request. Returns a `ResolveFuture` for a `ResolveResult`.
//! let resolve_future = hyper_staticfile::resolve(&root, &request);
//!
//! // Then, build a response based on the result.
//! // The `ResponseBuilder` is typically a short-lived, per-request instance.
//! let response_future = resolve_future.map(move |result| {
//! hyper_staticfile::ResponseBuilder::new()
//! .build(&request, result)
//! .unwrap()
//! });
//! #[tokio::main]
//! async fn main() {
//! // Document root path.
//! let root = Path::new("my/doc/root/");
//!
//! // A dummy request, but normally obtained from Hyper.
//! let request = http::Request::get("/foo/bar.txt")
//! .body(())
//! .unwrap();
//!
//! // First, resolve the request. Returns a future for a `ResolveResult`.
//! let result = hyper_staticfile::resolve(&root, &request)
//! .await
//! .unwrap();
//!
//! // Then, build a response based on the result.
//! // The `ResponseBuilder` is typically a short-lived, per-request instance.
//! let response = hyper_staticfile::ResponseBuilder::new()
//! .request(&request)
//! .build(result)
//! .unwrap();
//! }
//! ```
//!
//! The `resolve` function tries to find the file in the root, and returns a `ResolveFuture` for
//! the `ResolveResult` enum, which determines what kind of response should be sent. The
//! The `resolve` function tries to find the file in the root, and returns a future for the
//! `ResolveResult` enum, which determines what kind of response should be sent. The
//! `ResponseBuilder` is then used to create a default response. It holds some settings, and can be
//! constructed using the builder pattern.
//!
Expand All @@ -79,28 +75,16 @@
//! and want to serve it. It takes care of basic headers, 'not modified' responses, and streaming
//! the file in the body.
//!
//! Finally, there's `FileChunkStream`, which is used by `FileResponseBuilder` to stream the file.
//! Finally, there's `FileBytesStream`, which is used by `FileResponseBuilder` to stream the file.
//! This is a struct wrapping a `tokio::fs::File` and implementing a `futures::Stream` that
//! produces `hyper::Chunk`s. It can be used for streaming a file in custom response.
extern crate chrono;
#[macro_use]
extern crate futures;
extern crate http;
extern crate hyper;
extern crate mime_guess;
extern crate tokio;
extern crate url;

#[cfg(windows)]
extern crate winapi;
//! produces `Bytes`s. It can be used for streaming a file in custom response.
mod resolve;
mod response_builder;
mod service;
mod util;

pub use resolve::*;
pub use response_builder::*;
pub use service::*;
pub use util::{FileChunkStream, FileResponseBuilder};
pub use crate::resolve::*;
pub use crate::response_builder::*;
pub use crate::service::*;
pub use crate::util::{FileBytesStream, FileResponseBuilder};
Loading

0 comments on commit 19d34d2

Please sign in to comment.