Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Sitting idle] Strongly-typed headers #65

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
32 changes: 8 additions & 24 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 @@ -121,32 +122,15 @@ pub fn match_assets<P: ?Sized>(request: &Request, path: &P) -> Response
.unwrap_or(time::now().tm_nsec as u64)
^ 0xd3f40305c9f8e911u64).to_string();

let not_modified: bool = request.header("If-None-Match")
.map(|req_etag| req_etag == etag)
.unwrap_or(false);

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,
};
}

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,
},
data: ResponseBody::from_file(file),
upgrade: None,
}
.. Response::empty_200()
}.with_etag(etag.to_owned(), request)
}

/// Returns the mime type of a file based on its extension.
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