Allow different lifetimes in handler Request reference and its contents.

This commit is contained in:
Sergio Benitez 2016-10-06 20:38:13 -07:00
parent 639a78a8d6
commit bcb9bd860b
14 changed files with 83 additions and 27 deletions

View File

@ -57,9 +57,9 @@ pub fn error_decorator(ecx: &mut ExtCtxt, sp: Span, meta_item: &MetaItem,
let fn_arguments = error.generate_fn_arguments(ecx, err_ident, req_ident); let fn_arguments = error.generate_fn_arguments(ecx, err_ident, req_ident);
emit_item(push, quote_item!(ecx, emit_item(push, quote_item!(ecx,
fn $catch_fn_name<'rocket>($err_ident: ::rocket::Error, fn $catch_fn_name<'_b, '_r>($err_ident: ::rocket::Error,
$req_ident: &'rocket ::rocket::Request<'rocket>) $req_ident: &'_b ::rocket::Request<'_r>)
-> ::rocket::Response<'rocket> { -> ::rocket::Response<'_b> {
let result = $user_fn_name($fn_arguments); let result = $user_fn_name($fn_arguments);
rocket::Response::with_raw_status($code, result) rocket::Response::with_raw_status($code, result)
} }

View File

@ -219,8 +219,8 @@ fn generic_route_decorator(known_method: Option<Spanned<Method>>,
let user_fn_name = route.annotated_fn.ident(); let user_fn_name = route.annotated_fn.ident();
let route_fn_name = user_fn_name.prepend(ROUTE_FN_PREFIX); let route_fn_name = user_fn_name.prepend(ROUTE_FN_PREFIX);
emit_item(push, quote_item!(ecx, emit_item(push, quote_item!(ecx,
fn $route_fn_name<'rocket>(_req: &'rocket ::rocket::Request<'rocket>) fn $route_fn_name<'_b, '_r>(_req: &'_b ::rocket::Request<'_r>)
-> ::rocket::Response<'rocket> { -> ::rocket::Response<'_b> {
$form_statement $form_statement
$query_statement $query_statement
$param_statements $param_statements

View File

@ -0,0 +1,18 @@
#![feature(plugin, custom_derive)]
#![plugin(rocket_codegen)]
extern crate rocket;
use rocket::http::Cookies;
#[derive(FromForm)]
struct User {
name: String
}
#[post("/<name>", format = "application/json", form = "<user>", rank = 2)]
fn get(name: &str, user: User, cookies: &Cookies) -> &'static str { "hi" }
fn main() {
let _ = routes![get];
}

View File

@ -15,10 +15,14 @@ fn err1a(_err: Error) -> &'static str { "hi" }
fn err1b(_req: &Request) -> &'static str { "hi" } fn err1b(_req: &Request) -> &'static str { "hi" }
#[error(404)] #[error(404)]
fn err2(_err: Error, _req: &Request) -> &'static str { "hi" } fn err2a(_err: Error, _req: &Request) -> &'static str { "hi" }
#[error(404)]
fn err2b<'r>(_err: Error, _req: &Request<'r>) -> &'r str { "hi" }
#[error(404)]
fn err2c<'a>(_err: Error, _req: &'a Request) -> &'a str { "hi" }
fn main() { fn main() {
rocket::ignite()
.catch(errors![err0, err1a, err1b, err2]);
} }

View File

@ -0,0 +1,16 @@
#![feature(plugin)]
#![plugin(rocket_codegen)]
extern crate rocket;
#[get("/", rank = 1)]
fn get1() -> &'static str { "hi" }
#[get("/", rank = 2)]
fn get2() -> &'static str { "hi" }
#[get("/", rank = 3)]
fn get3() -> &'static str { "hi" }
fn main() {
}

View File

@ -0,0 +1,15 @@
#![feature(plugin, custom_derive)]
#![plugin(rocket_codegen)]
extern crate rocket;
use std::path::PathBuf;
#[post("/<a>/<b..>")]
fn get(a: String, b: PathBuf) -> String {
format!("{}/{}", a, b.to_string_lossy())
}
fn main() {
let _ = routes![get];
}

View File

@ -27,7 +27,7 @@ fn hello(content_type: ContentType, name: String, age: i8) -> data::JSON<String>
} }
#[error(404)] #[error(404)]
fn not_found<'r>(_: Error, request: &'r Request<'r>) -> String { fn not_found(_: Error, request: &Request) -> String {
if !request.content_type().is_json() { if !request.content_type().is_json() {
format!("<p>This server only supports JSON requests, not '{}'.</p>", format!("<p>This server only supports JSON requests, not '{}'.</p>",
request.content_type()) request.content_type())

View File

@ -32,7 +32,7 @@ fn get(name: String) -> Template {
} }
#[error(404)] #[error(404)]
fn not_found<'r>(_: Error, req: &'r Request<'r>) -> Template { fn not_found(req: &Request) -> Template {
let mut map = std::collections::HashMap::new(); let mut map = std::collections::HashMap::new();
map.insert("path", req.uri().as_str()); map.insert("path", req.uri().as_str());
Template::render("404", &map) Template::render("404", &map)

View File

@ -78,7 +78,7 @@ fn get(id: ID) -> Option<JSON<Message>> {
} }
#[error(404)] #[error(404)]
fn not_found<'r>(_: Error, _: &'r Request<'r>) -> JSON<SimpleMap> { fn not_found() -> JSON<SimpleMap> {
JSON(map! { JSON(map! {
"status" => "error", "status" => "error",
"reason" => "Resource was not found." "reason" => "Resource was not found."

View File

@ -3,23 +3,28 @@ extern crate rocket;
use rocket::{Request, Response, Route}; use rocket::{Request, Response, Route};
use rocket::http::Method::*; use rocket::http::Method::*;
fn root<'r>(req: &'r Request<'r>) -> Response<'r> { fn root(req: &Request) -> Response<'static> {
let name = req.get_param(0).unwrap_or("unnamed"); let name = req.get_param(0).unwrap_or("unnamed");
Response::new(format!("Hello, {}!", name)) Response::new(format!("Hello, {}!", name))
} }
fn name<'a>(req: &'a Request) -> Response<'a> {
Response::new(req.get_param(0).unwrap_or("unnamed"))
}
#[allow(dead_code)] #[allow(dead_code)]
fn echo_url<'a>(req: &'a Request<'a>) -> Response<'a> { fn echo_url<'a>(req: &'a Request) -> Response<'a> {
Response::new(req.uri().as_str().split_at(6).1) Response::new(req.uri().as_str().split_at(6).1)
} }
fn main() { fn main() {
let first = Route::new(Get, "/hello", root); let first = Route::new(Get, "/hello", root);
let second = Route::new(Get, "/hello/<any>", root); let second = Route::new(Get, "/hello/<any>", root);
let name = Route::new(Get, "/<name>", name);
let echo = Route::new(Get, "/", echo_url); let echo = Route::new(Get, "/", echo_url);
rocket::ignite() rocket::ignite()
.mount("/", vec![first, second]) .mount("/", vec![first, second, name])
.mount("/echo:<str>", vec![echo]) .mount("/echo:<str>", vec![echo])
.launch(); .launch();
} }

View File

@ -23,7 +23,7 @@ impl Catcher {
Catcher::new_with_default(code, handler, false) Catcher::new_with_default(code, handler, false)
} }
pub fn handle<'r>(&self, err: Error, request: &'r Request<'r>) -> Response<'r> { pub fn handle<'b, 'r>(&self, err: Error, request: &'b Request<'r>) -> Response<'b> {
(self.handler)(err, request) (self.handler)(err, request)
} }
@ -63,7 +63,7 @@ pub mod defaults {
use error::Error; use error::Error;
use http::hyper::StatusCode; use http::hyper::StatusCode;
pub fn not_found<'r>(_error: Error, _request: &'r Request<'r>) -> Response<'r> { pub fn not_found<'r>(_error: Error, _request: &'r Request) -> Response<'r> {
Response::with_status(StatusCode::NotFound, data::HTML(r#" Response::with_status(StatusCode::NotFound, data::HTML(r#"
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
@ -84,7 +84,7 @@ pub mod defaults {
} }
pub fn internal_error<'r>(_error: Error, pub fn internal_error<'r>(_error: Error,
_request: &'r Request<'r>) _request: &'r Request)
-> Response<'r> { -> Response<'r> {
Response::with_status(StatusCode::InternalServerError, data::HTML(r#" Response::with_status(StatusCode::InternalServerError, data::HTML(r#"
<!DOCTYPE html> <!DOCTYPE html>

View File

@ -88,10 +88,10 @@ pub mod handler {
use error::Error; use error::Error;
/// The type of a request handler. /// The type of a request handler.
pub type Handler = for<'r> fn(&'r Request<'r>) -> Response<'r>; pub type Handler = for<'b, 'r: 'b> fn(&'b Request<'r>) -> Response<'b>;
/// The type of an error handler. /// The type of an error handler.
pub type ErrorHandler = for<'r> fn(error: Error, &'r Request<'r>) -> Response<'r>; pub type ErrorHandler = for<'b, 'r: 'b> fn(error: Error, &'b Request<'r>) -> Response<'b>;
} }
#[doc(inline)] pub use response::{Response, Responder}; #[doc(inline)] pub use response::{Response, Responder};

View File

@ -83,9 +83,7 @@ impl<'a> Request<'a> {
/// For example, if the request URI is `"/hello/there/i/am/here"`, then /// For example, if the request URI is `"/hello/there/i/am/here"`, then
/// `request.get_segments::<T>(1)` will attempt to parse the segments /// `request.get_segments::<T>(1)` will attempt to parse the segments
/// `"there/i/am/here"` as type `T`. /// `"there/i/am/here"` as type `T`.
pub fn get_segments<'r: 'a, T: FromSegments<'a>>(&'r self, pub fn get_segments<'r, T: FromSegments<'r>>(&'r self, i: usize) -> Result<T, Error> {
i: usize)
-> Result<T, Error> {
if i >= self.uri().segment_count() { if i >= self.uri().segment_count() {
debug!("{} is >= segment count {}", i, self.uri().segment_count()); debug!("{} is >= segment count {}", i, self.uri().segment_count());
Err(Error::NoKey) Err(Error::NoKey)

View File

@ -35,7 +35,7 @@ impl<'a> Response<'a> {
Response(Box::new(StatusResponse::new(status, body))) Response(Box::new(StatusResponse::new(status, body)))
} }
pub fn forward() -> Response<'a> { pub fn forward() -> Response<'static> {
Response(Box::new(Forward)) Response(Box::new(Forward))
} }
@ -44,20 +44,20 @@ impl<'a> Response<'a> {
Response(Box::new(StatusResponse::new(status_code, body))) Response(Box::new(StatusResponse::new(status_code, body)))
} }
pub fn empty() -> Response<'a> { pub fn empty() -> Response<'static> {
Response(Box::new(Empty::new(StatusCode::Ok))) Response(Box::new(Empty::new(StatusCode::Ok)))
} }
pub fn not_found() -> Response<'a> { pub fn not_found() -> Response<'static> {
Response(Box::new(Empty::new(StatusCode::NotFound))) Response(Box::new(Empty::new(StatusCode::NotFound)))
} }
pub fn server_error(reason: &str) -> Response<'a> { pub fn server_error(reason: &str) -> Response<'static> {
warn_!("internal server error: {}", reason); warn_!("internal server error: {}", reason);
Response(Box::new(Empty::new(StatusCode::InternalServerError))) Response(Box::new(Empty::new(StatusCode::InternalServerError)))
} }
pub fn bad_request(reason: &str) -> Response<'a> { pub fn bad_request(reason: &str) -> Response<'static> {
warn_!("bad request from user: {}", reason); warn_!("bad request from user: {}", reason);
Response(Box::new(Empty::new(StatusCode::BadRequest))) Response(Box::new(Empty::new(StatusCode::BadRequest)))
} }