Use full URI in codegen routes; log query params in routes.

This commit is contained in:
Sergio Benitez 2017-02-05 01:11:29 -08:00
parent ecd72f686e
commit e966925455
4 changed files with 33 additions and 26 deletions

View File

@ -45,7 +45,7 @@ trait RouteGenerateExt {
fn generate_query_statement(&self, ecx: &ExtCtxt) -> Option<Stmt>;
fn generate_param_statements(&self, ecx: &ExtCtxt) -> Vec<Stmt>;
fn generate_fn_arguments(&self, ecx: &ExtCtxt) -> Vec<TokenTree>;
fn explode(&self, ecx: &ExtCtxt) -> (&String, Path, P<Expr>, P<Expr>);
fn explode(&self, ecx: &ExtCtxt) -> (&str, Path, P<Expr>, P<Expr>);
}
impl RouteGenerateExt for RouteParams {
@ -217,8 +217,8 @@ impl RouteGenerateExt for RouteParams {
sep_by_tok(ecx, &args, token::Comma)
}
fn explode(&self, ecx: &ExtCtxt) -> (&String, Path, P<Expr>, P<Expr>) {
let path = &self.path.node;
fn explode(&self, ecx: &ExtCtxt) -> (&str, Path, P<Expr>, P<Expr>) {
let path = &self.uri.node.as_str();
let method = method_to_path(ecx, self.method.node);
let format = self.format.as_ref().map(|kv| kv.value().clone());
let content_type = option_as_expr(ecx, &content_type_to_expr(ecx, format));

View File

@ -9,6 +9,7 @@ use utils::{span, MetaItemExt, SpanExt, is_valid_ident};
use super::{Function, ParamIter};
use super::keyvalue::KVSpanned;
use rocket::http::{Method, ContentType};
use rocket::http::uri::URI;
/// This structure represents the parsed `route` attribute.
///
@ -20,7 +21,7 @@ use rocket::http::{Method, ContentType};
pub struct RouteParams {
pub annotated_fn: Function,
pub method: Spanned<Method>,
pub path: Spanned<String>,
pub uri: Spanned<URI<'static>>,
pub data_param: Option<KVSpanned<Ident>>,
pub query_param: Option<Spanned<Ident>>,
pub format: Option<KVSpanned<ContentType>>,
@ -69,7 +70,7 @@ impl RouteParams {
}
// Parse the required path and optional query parameters.
let (path, query) = parse_path(ecx, &attr_params[0]);
let (uri, query) = parse_path(ecx, &attr_params[0]);
// Parse all of the optional parameters.
let mut seen_keys = HashSet::new();
@ -115,7 +116,7 @@ impl RouteParams {
RouteParams {
method: method,
path: path,
uri: uri,
data_param: data,
query_param: query,
format: format,
@ -127,7 +128,7 @@ impl RouteParams {
pub fn path_params<'s, 'a, 'c: 'a>(&'s self,
ecx: &'a ExtCtxt<'c>)
-> ParamIter<'s, 'a, 'c> {
ParamIter::new(ecx, self.path.node.as_str(), self.path.span.trim(1))
ParamIter::new(ecx, self.uri.node.path(), self.uri.span.trim(1))
}
}
@ -150,12 +151,12 @@ pub fn kv_from_nested(item: &NestedMetaItem) -> Option<KVSpanned<LitKind>> {
})
}
fn param_string_to_ident(ecx: &ExtCtxt, s: Spanned<&str>) -> Option<Ident> {
fn param_string_to_ident(ecx: &ExtCtxt, s: Spanned<&str>) -> Option<Spanned<Ident>> {
let string = s.node;
if string.starts_with('<') && string.ends_with('>') {
let param = &string[1..(string.len() - 1)];
if is_valid_ident(param) {
return Some(Ident::from_str(param));
return Some(span(Ident::from_str(param), s.span.trim(1)));
}
ecx.span_err(s.span, "parameter name must be alphanumeric");
@ -186,16 +187,14 @@ fn parse_method(ecx: &ExtCtxt, meta_item: &NestedMetaItem) -> Spanned<Method> {
dummy_spanned(Method::Get)
}
fn parse_path(ecx: &ExtCtxt, meta_item: &NestedMetaItem) -> (Spanned<String>, Option<Spanned<Ident>>) {
fn parse_path(ecx: &ExtCtxt, meta_item: &NestedMetaItem)
-> (Spanned<URI<'static>>, Option<Spanned<Ident>>) {
let from_string = |string: &str, sp: Span| {
if let Some(q) = string.find('?') {
let path = span(string[..q].to_string(), sp);
let q_str = span(&string[(q + 1)..], sp);
let query = param_string_to_ident(ecx, q_str).map(|i| span(i, sp));
return (path, query);
} else {
return (span(string.to_string(), sp), None)
}
let query_param = string.find('?')
.map(|i| span(&string[(i + 1)..], sp.trim_left(i + 1)))
.and_then(|spanned_q_param| param_string_to_ident(ecx, spanned_q_param));
(span(URI::from(string.to_string()), sp), query_param)
};
let sp = meta_item.span();
@ -217,7 +216,7 @@ fn parse_path(ecx: &ExtCtxt, meta_item: &NestedMetaItem) -> (Spanned<String>, Op
.emit();
}
(dummy_spanned("".to_string()), None)
(dummy_spanned(URI::new("")), None)
}
fn parse_opt<O, T, F>(ecx: &ExtCtxt, kv: &KVSpanned<T>, f: F) -> Option<KVSpanned<O>>
@ -230,8 +229,8 @@ fn parse_data(ecx: &ExtCtxt, kv: &KVSpanned<LitKind>) -> Ident {
let mut ident = Ident::from_str("unknown");
if let LitKind::Str(ref s, _) = *kv.value() {
ident = Ident::from_str(&s.as_str());
if let Some(ident) = param_string_to_ident(ecx, span(&s.as_str(), kv.value.span)) {
return ident;
if let Some(id) = param_string_to_ident(ecx, span(&s.as_str(), kv.value.span)) {
return id.node;
}
}

View File

@ -5,9 +5,17 @@ pub trait SpanExt {
/// Trim the span on the left and right by `length`.
fn trim(self, length: u32) -> Span;
/// Trim the span on the left by `length`.
fn trim_left(self, length: usize) -> Span;
}
impl SpanExt for Span {
fn trim_left(mut self, length: usize) -> Span {
self.lo = self.lo + BytePos(length as u32);
self
}
fn shorten_to(mut self, to_length: usize) -> Span {
self.hi = self.lo + BytePos(to_length as u32);
self

View File

@ -276,11 +276,11 @@ impl<'a> fmt::Display for URI<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// If this is the root path, then there are "zero" segments.
if self.as_str().starts_with('/') && self.segment_count() == 0 {
return write!(f, "/");
}
for segment in self.segments() {
write!(f, "/{}", segment)?;
write!(f, "/")?;
} else {
for segment in self.segments() {
write!(f, "/{}", segment)?;
}
}
if let Some(query_str) = self.query() {