Skip to content

Commit

Permalink
Use strong typing for the headers
Browse files Browse the repository at this point in the history
  • Loading branch information
tomaka committed Dec 11, 2016
1 parent 28c7608 commit 47986d8
Show file tree
Hide file tree
Showing 10 changed files with 366 additions and 94 deletions.
9 changes: 5 additions & 4 deletions examples/database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,10 +177,11 @@ fn note_routes(request: &Request, db: &Transaction) -> Response {

let id = id.unwrap();

let mut response = Response::text("The note has been created");
response.status_code = 201;
response.headers.push(("Location".to_owned(), format!("/note/{}", id)));
response
Response {
status_code: 201,
location: Some(format!("/note/{}", id).into()),
.. Response::text("The note has been created")
}
},

(DELETE) (/note/{id: i32}) => {
Expand Down
4 changes: 2 additions & 2 deletions examples/websocket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ fn main() {
<button type=\"submit\">Send</button>
</form></p>
<p>Received: </p>
<p id=\"result\"></p>")
<p id=\"result\"></p>").into()
},

(GET) (/ws) => {
Expand Down Expand Up @@ -73,7 +73,7 @@ fn main() {
},

// Default 404 route as with all examples.
_ => rouille::Response::empty_404()
_ => rouille::Response::empty_404().into()
)
});
}
Expand Down
27 changes: 14 additions & 13 deletions src/assets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use time;

use Request;
use Response;
use ResponseCacheControl;
use ResponseBody;

/// Searches inside `path` for a file that matches the given request. If a file is found,
Expand Down Expand Up @@ -128,24 +129,24 @@ pub fn match_assets<P: ?Sized>(request: &Request, path: &P) -> Response
if not_modified {
return Response {
status_code: 304,
headers: vec![
("Cache-Control".to_owned(), "public, max-age=3600".to_owned()),
("ETag".to_owned(), etag.to_string())
],
data: ResponseBody::empty(),
upgrade: None,
cache_control: ResponseCacheControl::Public {
max_age: 3600,
must_revalidate: false,
},
data: ResponseBody::from_file(file),
.. Response::empty_200()
};
}

Response {
status_code: 200,
headers: vec![
("Cache-Control".to_owned(), "public, max-age=3600".to_owned()),
("Content-Type".to_owned(), extension_to_mime(extension).to_owned()),
("ETag".to_owned(), etag.to_string())
],
content_type: Some(extension_to_mime(extension).into()),
cache_control: ResponseCacheControl::Public {
max_age: 3600,
must_revalidate: false,
},
etag: Some(etag.to_owned().into()),
data: ResponseBody::from_file(file),
upgrade: None,
.. Response::empty_200()
}
}

Expand Down
10 changes: 5 additions & 5 deletions src/cgi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ use std::process::Command;
use std::process::Stdio;

use Request;
use Response;
use RawResponse;
use ResponseBody;

/// Error that can happen when parsing the JSON input.
Expand Down Expand Up @@ -75,11 +75,11 @@ pub trait CgiRun {
/// The body of the returned `Response` will hold a handle to the child's stdout output. This
/// means that the child can continue running in the background and send data to the client,
/// even after you have finished handling the request.
fn start_cgi(self, request: &Request) -> Result<Response, CgiError>;
fn start_cgi(self, request: &Request) -> Result<RawResponse, CgiError>;
}

impl CgiRun for Command {
fn start_cgi(mut self, request: &Request) -> Result<Response, CgiError> {
fn start_cgi(mut self, request: &Request) -> Result<RawResponse, CgiError> {
self.env("SERVER_SOFTWARE", "rouille")
.env("SERVER_NAME", "localhost") // FIXME:
.env("GATEWAY_INTERFACE", "CGI/1.1")
Expand Down Expand Up @@ -125,11 +125,11 @@ impl CgiRun for Command {
if header == "Status" {
status = val[0..3].parse().expect("Status returned by CGI program is invalid");
} else {
headers.push((header.to_owned(), val.to_owned()));
headers.push((header.to_owned().into(), val.to_owned().into()));
}
}

Response {
RawResponse {
status_code: status,
headers: headers,
data: ResponseBody::from_reader(stdout),
Expand Down
25 changes: 14 additions & 11 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ extern crate url;

pub use assets::match_assets;
pub use log::log;
pub use response::{Response, ResponseBody};
pub use response::{Response, ResponseBody, RawResponse};
pub use response::{ResponseCookie, ResponseCacheControl};
pub use tiny_http::ReadWrite;

use std::io::Cursor;
Expand Down Expand Up @@ -119,7 +120,7 @@ macro_rules! try_or_400 {
($result:expr) => (
match $result {
Ok(r) => r,
Err(_) => return $crate::Response::empty_400(),
Err(_) => return $crate::Response::empty_400().into(),
}
);
}
Expand All @@ -131,7 +132,7 @@ macro_rules! try_or_404 {
($result:expr) => (
match $result {
Ok(r) => r,
Err(_) => return $crate::Response::empty_404(),
Err(_) => return $crate::Response::empty_404().into(),
}
);
}
Expand Down Expand Up @@ -162,7 +163,7 @@ macro_rules! try_or_404 {
macro_rules! assert_or_400 {
($cond:expr) => (
if !$cond {
return $crate::Response::empty_400();
return $crate::Response::empty_400().into();
}
);
}
Expand Down Expand Up @@ -202,17 +203,18 @@ macro_rules! assert_or_400 {
/// *requests_counter.lock().unwrap() += 1;
///
/// // rest of the handler
/// # panic!()
/// # rouille::Response::empty_404()
/// })
/// ```
///
/// # Panic handling
///
/// If your request handler panicks, a 500 error will automatically be sent to the client.
///
pub fn start_server<A, F>(addr: A, handler: F) -> !
where A: ToSocketAddrs,
F: Send + Sync + 'static + Fn(&Request) -> Response
pub fn start_server<A, F, R>(addr: A, handler: F) -> !
where A: ToSocketAddrs,
F: Send + Sync + 'static + Fn(&Request) -> R,
R: Into<RawResponse>
{
let server = tiny_http::Server::http(addr).unwrap();
let handler = Arc::new(AssertUnwindSafe(handler)); // TODO: using AssertUnwindSafe here is wrong, but unwind safety has some usability problems in Rust in general
Expand Down Expand Up @@ -259,7 +261,7 @@ pub fn start_server<A, F>(addr: A, handler: F) -> !
let rouille_request = AssertUnwindSafe(rouille_request);
let res = panic::catch_unwind(move || {
let rouille_request = rouille_request;
handler(&rouille_request)
handler(&rouille_request).into()
});

match res {
Expand All @@ -268,6 +270,7 @@ pub fn start_server<A, F>(addr: A, handler: F) -> !
Response::html("<h1>Internal Server Error</h1>\
<p>An internal error has occurred on the server.</p>")
.with_status_code(500)
.into()
}
}
};
Expand All @@ -278,7 +281,7 @@ pub fn start_server<A, F>(addr: A, handler: F) -> !
.with_data(res_data, res_len);

for (key, value) in rouille_response.headers {
if let Ok(header) = tiny_http::Header::from_bytes(key, value) {
if let Ok(header) = tiny_http::Header::from_bytes(&*key, &*value) {
response.add_header(header);
} else {
// TODO: ?
Expand Down Expand Up @@ -430,7 +433,7 @@ impl Request {
///
/// fn handle(request: &Request) -> Response {
/// if !request.is_secure() {
/// return Response::redirect(&format!("https://example.com"));
/// return Response::redirect(format!("https://example.com"));
/// }
///
/// // ...
Expand Down
12 changes: 7 additions & 5 deletions src/log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use std::time::Instant;
use chrono;

use Request;
use Response;
use RawResponse;

/// Adds a log entry to the given writer at each request.
///
Expand All @@ -26,17 +26,18 @@ use Response;
///
/// ```
/// use std::io;
/// use rouille::{Request, Response};
/// use rouille::{Request, Response, RawResponse};
///
/// fn handle(request: &Request) -> Response {
/// fn handle(request: &Request) -> RawResponse {
/// rouille::log(request, io::stdout(), || {
/// Response::text("hello world")
/// })
/// }
/// ```
pub fn log<W, F>(rq: &Request, mut output: W, f: F) -> Response
pub fn log<W, F, R>(rq: &Request, mut output: W, f: F) -> RawResponse
where W: Write,
F: FnOnce() -> Response
F: FnOnce() -> R,
R: Into<RawResponse>
{
let start_instant = Instant::now();
let rq_line = format!("{} UTC - {} {}", chrono::UTC::now().format("%Y-%m-%d %H:%M:%S%.6f"),
Expand All @@ -51,6 +52,7 @@ pub fn log<W, F>(rq: &Request, mut output: W, f: F) -> Response

match response {
Ok(response) => {
let response: RawResponse = response.into();
let _ = writeln!(output, "{} - {} - {}", rq_line, elapsed_time, response.status_code);
response
},
Expand Down
16 changes: 8 additions & 8 deletions src/proxy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@
//! client.
//!
//! ```
//! use rouille::{Request, Response};
//! use rouille::{Request, Response, RawResponse};
//! use rouille::proxy;
//!
//! fn handle_request(request: &Request) -> Response {
//! fn handle_request(request: &Request) -> RawResponse {
//! let config = match request.header("Host") {
//! Some(ref h) if h == "domain1.com" => {
//! proxy::ProxyConfig {
Expand All @@ -40,12 +40,12 @@
//! }
//! },
//!
//! _ => return Response::empty_404()
//! _ => return Response::empty_404().into()
//! };
//!
//! match proxy::proxy(request, config) {
//! Ok(r) => r,
//! Err(_) => Response::text("Bad gateway").with_status_code(500),
//! Err(_) => Response::text("Bad gateway").with_status_code(500).into(),
//! }
//! }
//! ```
Expand All @@ -60,7 +60,7 @@ use std::net::TcpStream;
use std::net::ToSocketAddrs;

use Request;
use Response;
use RawResponse;
use ResponseBody;

/// Error that can happen when dispatching the request to another server.
Expand Down Expand Up @@ -98,7 +98,7 @@ pub struct ProxyConfig<A> {
///
/// > **Note**: SSL is not supported.
// TODO: ^
pub fn proxy<A>(request: &Request, config: ProxyConfig<A>) -> Result<Response, ProxyError>
pub fn proxy<A>(request: &Request, config: ProxyConfig<A>) -> Result<RawResponse, ProxyError>
where A: ToSocketAddrs
{
let mut socket = try!(TcpStream::connect(config.addr));
Expand Down Expand Up @@ -164,11 +164,11 @@ pub fn proxy<A>(request: &Request, config: ProxyConfig<A>) -> Result<Response, P
};
let val = &val[1..];

headers.push((header.to_owned(), val.to_owned()));
headers.push((header.to_owned().into(), val.to_owned().into()));
}
}

Ok(Response {
Ok(RawResponse {
status_code: status,
headers: headers,
data: ResponseBody::from_reader(socket),
Expand Down
Loading

0 comments on commit 47986d8

Please sign in to comment.