Implement substitution of variables in endpoint paths
This commit is contained in:
parent
5180297d81
commit
62971e63cd
@ -22,7 +22,6 @@ serde = "1.0.8"
|
|||||||
serde_derive = "1.0.8"
|
serde_derive = "1.0.8"
|
||||||
serde_json = "1.0.2"
|
serde_json = "1.0.2"
|
||||||
serde_urlencoded = "0.5.1"
|
serde_urlencoded = "0.5.1"
|
||||||
url = "1.5.1"
|
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
doctest = false
|
doctest = false
|
||||||
|
@ -36,6 +36,61 @@ impl ToTokens for Api {
|
|||||||
tokens
|
tokens
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let set_request_path = if self.request.has_path_fields() {
|
||||||
|
let path_str_quoted = path.as_str();
|
||||||
|
assert!(
|
||||||
|
path_str_quoted.starts_with('"') && path_str_quoted.ends_with('"'),
|
||||||
|
"path needs to be a string literal"
|
||||||
|
);
|
||||||
|
|
||||||
|
let path_str = &path_str_quoted[1 .. path_str_quoted.len() - 1];
|
||||||
|
|
||||||
|
assert!(path_str.starts_with('/'), "path needs to start with '/'");
|
||||||
|
assert!(
|
||||||
|
path_str.chars().filter(|c| *c == ':').count() == self.request.path_field_count(),
|
||||||
|
"number of declared path parameters needs to match amount of placeholders in path"
|
||||||
|
);
|
||||||
|
|
||||||
|
let request_path_init_fields = self.request.request_path_init_fields();
|
||||||
|
|
||||||
|
let mut tokens = quote! {
|
||||||
|
let request_path = RequestPath {
|
||||||
|
#request_path_init_fields
|
||||||
|
};
|
||||||
|
|
||||||
|
// This `unwrap()` can only fail when the url is a
|
||||||
|
// cannot-be-base url like `mailto:` or `data:`, which is not
|
||||||
|
// the case for our placeholder url.
|
||||||
|
let mut path_segments = url.path_segments_mut().unwrap();
|
||||||
|
};
|
||||||
|
|
||||||
|
for segment in path_str[1..].split('/') {
|
||||||
|
tokens.append(quote! {
|
||||||
|
path_segments.push
|
||||||
|
});
|
||||||
|
|
||||||
|
tokens.append("(");
|
||||||
|
|
||||||
|
if segment.starts_with(':') {
|
||||||
|
tokens.append("&request_path.");
|
||||||
|
tokens.append(&segment[1..]);
|
||||||
|
tokens.append(".to_string()");
|
||||||
|
} else {
|
||||||
|
tokens.append("\"");
|
||||||
|
tokens.append(segment);
|
||||||
|
tokens.append("\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
tokens.append(");");
|
||||||
|
}
|
||||||
|
|
||||||
|
tokens
|
||||||
|
} else {
|
||||||
|
quote! {
|
||||||
|
url.set_path(metadata.path);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let set_request_query = if self.request.has_query_fields() {
|
let set_request_query = if self.request.has_query_fields() {
|
||||||
let request_query_init_fields = self.request.request_query_init_fields();
|
let request_query_init_fields = self.request.request_query_init_fields();
|
||||||
|
|
||||||
@ -159,8 +214,9 @@ impl ToTokens for Api {
|
|||||||
// the calling code. Previously (with hyper::Uri) this was
|
// the calling code. Previously (with hyper::Uri) this was
|
||||||
// not required, but Url::parse only accepts absolute urls.
|
// not required, but Url::parse only accepts absolute urls.
|
||||||
let mut url = ::url::Url::parse("http://invalid-host-please-change/").unwrap();
|
let mut url = ::url::Url::parse("http://invalid-host-please-change/").unwrap();
|
||||||
url.set_path(metadata.path);
|
|
||||||
#set_request_query
|
{ #set_request_path }
|
||||||
|
{ #set_request_query }
|
||||||
|
|
||||||
let mut hyper_request = ::hyper::Request::new(
|
let mut hyper_request = ::hyper::Request::new(
|
||||||
metadata.method,
|
metadata.method,
|
||||||
@ -168,7 +224,7 @@ impl ToTokens for Api {
|
|||||||
url.into_string().parse().unwrap(),
|
url.into_string().parse().unwrap(),
|
||||||
);
|
);
|
||||||
|
|
||||||
#add_body_to_request
|
{ #add_body_to_request }
|
||||||
|
|
||||||
Ok(hyper_request)
|
Ok(hyper_request)
|
||||||
}
|
}
|
||||||
|
@ -11,10 +11,18 @@ impl Request {
|
|||||||
self.fields.iter().any(|field| field.is_body())
|
self.fields.iter().any(|field| field.is_body())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn has_path_fields(&self) -> bool {
|
||||||
|
self.fields.iter().any(|field| field.is_path())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn has_query_fields(&self) -> bool {
|
pub fn has_query_fields(&self) -> bool {
|
||||||
self.fields.iter().any(|field| field.is_query())
|
self.fields.iter().any(|field| field.is_query())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn path_field_count(&self) -> usize {
|
||||||
|
self.fields.iter().filter(|field| field.is_path()).count()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn newtype_body_field(&self) -> Option<&Field> {
|
pub fn newtype_body_field(&self) -> Option<&Field> {
|
||||||
for request_field in self.fields.iter() {
|
for request_field in self.fields.iter() {
|
||||||
match *request_field {
|
match *request_field {
|
||||||
@ -32,6 +40,10 @@ impl Request {
|
|||||||
self.struct_init_fields(RequestFieldKind::Body)
|
self.struct_init_fields(RequestFieldKind::Body)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn request_path_init_fields(&self) -> Tokens {
|
||||||
|
self.struct_init_fields(RequestFieldKind::Path)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn request_query_init_fields(&self) -> Tokens {
|
pub fn request_query_init_fields(&self) -> Tokens {
|
||||||
self.struct_init_fields(RequestFieldKind::Query)
|
self.struct_init_fields(RequestFieldKind::Query)
|
||||||
}
|
}
|
||||||
@ -178,9 +190,32 @@ impl ToTokens for Request {
|
|||||||
tokens.append("}");
|
tokens.append("}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.has_path_fields() {
|
||||||
|
tokens.append(quote! {
|
||||||
|
/// Data in the request path.
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct RequestPath
|
||||||
|
});
|
||||||
|
|
||||||
|
tokens.append("{");
|
||||||
|
|
||||||
|
for request_field in self.fields.iter() {
|
||||||
|
match *request_field {
|
||||||
|
RequestField::Path(ref field) => {
|
||||||
|
field.to_tokens(&mut tokens);
|
||||||
|
|
||||||
|
tokens.append(",");
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tokens.append("}");
|
||||||
|
}
|
||||||
|
|
||||||
if self.has_query_fields() {
|
if self.has_query_fields() {
|
||||||
tokens.append(quote! {
|
tokens.append(quote! {
|
||||||
/// Data in the request url's query parameters
|
/// Data in the request url's query parameters.
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
struct RequestQuery
|
struct RequestQuery
|
||||||
});
|
});
|
||||||
@ -237,6 +272,10 @@ impl RequestField {
|
|||||||
self.kind() == RequestFieldKind::Body
|
self.kind() == RequestFieldKind::Body
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_path(&self) -> bool {
|
||||||
|
self.kind() == RequestFieldKind::Path
|
||||||
|
}
|
||||||
|
|
||||||
fn is_query(&self) -> bool {
|
fn is_query(&self) -> bool {
|
||||||
self.kind() == RequestFieldKind::Query
|
self.kind() == RequestFieldKind::Query
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user