Update request/response header logic for new style.
This commit is contained in:
parent
f0f4f9bd17
commit
c9454caff1
@ -10,7 +10,7 @@ You define the endpoint's metadata, request fields, and response fields, and the
|
|||||||
Here is an example that shows most of the macro's functionality.
|
Here is an example that shows most of the macro's functionality.
|
||||||
|
|
||||||
``` rust
|
``` rust
|
||||||
#![feature(associated_consts, proc_macro, try_from)]
|
#![feature(proc_macro, try_from)]
|
||||||
|
|
||||||
extern crate futures;
|
extern crate futures;
|
||||||
extern crate http;
|
extern crate http;
|
||||||
|
@ -99,7 +99,7 @@ impl ToTokens for Api {
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
tokens.append_all(quote! {
|
tokens.append_all(quote! {
|
||||||
("#segment");
|
(#segment);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -125,6 +125,18 @@ impl ToTokens for Api {
|
|||||||
Tokens::new()
|
Tokens::new()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let add_headers_to_request = if self.request.has_header_fields() {
|
||||||
|
let mut header_tokens = quote! {
|
||||||
|
let headers = http_request.headers_mut();
|
||||||
|
};
|
||||||
|
|
||||||
|
header_tokens.append_all(self.request.add_headers_to_request());
|
||||||
|
|
||||||
|
header_tokens
|
||||||
|
} else {
|
||||||
|
Tokens::new()
|
||||||
|
};
|
||||||
|
|
||||||
let add_body_to_request = if let Some(field) = self.request.newtype_body_field() {
|
let add_body_to_request = if let Some(field) = self.request.newtype_body_field() {
|
||||||
let field_name = field.ident.expect("expected field to have an identifier");
|
let field_name = field.ident.expect("expected field to have an identifier");
|
||||||
|
|
||||||
@ -211,7 +223,7 @@ impl ToTokens for Api {
|
|||||||
|
|
||||||
#request_types
|
#request_types
|
||||||
|
|
||||||
impl ::std::convert::TryFrom<Request> for ::http::Request {
|
impl<T> ::std::convert::TryFrom<Request> for ::http::Request<T> {
|
||||||
type Error = ::ruma_api::Error;
|
type Error = ::ruma_api::Error;
|
||||||
|
|
||||||
#[allow(unused_mut, unused_variables)]
|
#[allow(unused_mut, unused_variables)]
|
||||||
@ -232,6 +244,8 @@ impl ToTokens for Api {
|
|||||||
url.into_string().parse().unwrap(),
|
url.into_string().parse().unwrap(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
{ #add_headers_to_request }
|
||||||
|
|
||||||
{ #add_body_to_request }
|
{ #add_body_to_request }
|
||||||
|
|
||||||
Ok(http_request)
|
Ok(http_request)
|
||||||
@ -240,12 +254,12 @@ impl ToTokens for Api {
|
|||||||
|
|
||||||
#response_types
|
#response_types
|
||||||
|
|
||||||
impl ::futures::future::FutureFrom<::http::Response> for Response {
|
impl<T> ::futures::future::FutureFrom<::http::Response<T>> for Response {
|
||||||
type Future = Box<_Future<Item = Self, Error = Self::Error>>;
|
type Future = Box<_Future<Item = Self, Error = Self::Error>>;
|
||||||
type Error = ::ruma_api::Error;
|
type Error = ::ruma_api::Error;
|
||||||
|
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
fn future_from(http_response: ::http::Response)
|
fn future_from(http_response: ::http::Response<T>)
|
||||||
-> Box<_Future<Item = Self, Error = Self::Error>> {
|
-> Box<_Future<Item = Self, Error = Self::Error>> {
|
||||||
#extract_headers
|
#extract_headers
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use quote::{ToTokens, Tokens};
|
use quote::{ToTokens, Tokens};
|
||||||
use syn::spanned::Spanned;
|
use syn::spanned::Spanned;
|
||||||
use syn::{Field, Meta, NestedMeta};
|
use syn::{Field, Ident, Lit, Meta, NestedMeta};
|
||||||
|
|
||||||
use api::strip_serde_attrs;
|
use api::strip_serde_attrs;
|
||||||
|
|
||||||
@ -9,10 +9,31 @@ pub struct Request {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Request {
|
impl Request {
|
||||||
|
pub fn add_headers_to_request(&self) -> Tokens {
|
||||||
|
self.header_fields().fold(Tokens::new(), |mut header_tokens, request_field| {
|
||||||
|
let (field, header_name_string) = match request_field {
|
||||||
|
RequestField::Header(field, header_name_string) => (field, header_name_string),
|
||||||
|
_ => panic!("expected request field to be header variant"),
|
||||||
|
};
|
||||||
|
|
||||||
|
let field_name = &field.ident;
|
||||||
|
let header_name = Ident::from(header_name_string.as_ref());
|
||||||
|
|
||||||
|
header_tokens.append_all(quote! {
|
||||||
|
headers.append(::http::header::#header_name, request.#field_name);
|
||||||
|
});
|
||||||
|
|
||||||
|
header_tokens
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub fn has_body_fields(&self) -> bool {
|
pub fn has_body_fields(&self) -> bool {
|
||||||
self.fields.iter().any(|field| field.is_body())
|
self.fields.iter().any(|field| field.is_body())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn has_header_fields(&self) -> bool {
|
||||||
|
self.fields.iter().any(|field| field.is_header())
|
||||||
|
}
|
||||||
pub fn has_path_fields(&self) -> bool {
|
pub fn has_path_fields(&self) -> bool {
|
||||||
self.fields.iter().any(|field| field.is_path())
|
self.fields.iter().any(|field| field.is_path())
|
||||||
}
|
}
|
||||||
@ -21,6 +42,10 @@ impl Request {
|
|||||||
self.fields.iter().any(|field| field.is_query())
|
self.fields.iter().any(|field| field.is_query())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn header_fields(&self) -> impl Iterator<Item = &RequestField> {
|
||||||
|
self.fields.iter().filter(|field| field.is_header())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn path_field_count(&self) -> usize {
|
pub fn path_field_count(&self) -> usize {
|
||||||
self.fields.iter().filter(|field| field.is_path()).count()
|
self.fields.iter().filter(|field| field.is_path()).count()
|
||||||
}
|
}
|
||||||
@ -72,6 +97,7 @@ impl From<Vec<Field>> for Request {
|
|||||||
|
|
||||||
let fields = fields.into_iter().map(|mut field| {
|
let fields = fields.into_iter().map(|mut field| {
|
||||||
let mut field_kind = RequestFieldKind::Body;
|
let mut field_kind = RequestFieldKind::Body;
|
||||||
|
let mut header = None;
|
||||||
|
|
||||||
field.attrs = field.attrs.into_iter().filter(|attr| {
|
field.attrs = field.attrs.into_iter().filter(|attr| {
|
||||||
let meta = attr.interpret_meta()
|
let meta = attr.interpret_meta()
|
||||||
@ -103,7 +129,14 @@ impl From<Vec<Field>> for Request {
|
|||||||
}
|
}
|
||||||
Meta::NameValue(name_value) => {
|
Meta::NameValue(name_value) => {
|
||||||
match name_value.ident.as_ref() {
|
match name_value.ident.as_ref() {
|
||||||
"header" => field_kind = RequestFieldKind::Header,
|
"header" => {
|
||||||
|
match name_value.lit {
|
||||||
|
Lit::Str(lit_str) => header = Some(lit_str.value()),
|
||||||
|
_ => panic!("ruma_api! header attribute's value must be a string literal"),
|
||||||
|
}
|
||||||
|
|
||||||
|
field_kind = RequestFieldKind::Header;
|
||||||
|
}
|
||||||
_ => panic!("ruma_api! name/value pair attribute on requests must be: header"),
|
_ => panic!("ruma_api! name/value pair attribute on requests must be: header"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -126,7 +159,7 @@ impl From<Vec<Field>> for Request {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
RequestField::new(field_kind, field)
|
RequestField::new(field_kind, field, header)
|
||||||
}).collect();
|
}).collect();
|
||||||
|
|
||||||
Request {
|
Request {
|
||||||
@ -267,17 +300,17 @@ impl ToTokens for Request {
|
|||||||
|
|
||||||
pub enum RequestField {
|
pub enum RequestField {
|
||||||
Body(Field),
|
Body(Field),
|
||||||
Header(Field),
|
Header(Field, String),
|
||||||
NewtypeBody(Field),
|
NewtypeBody(Field),
|
||||||
Path(Field),
|
Path(Field),
|
||||||
Query(Field),
|
Query(Field),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RequestField {
|
impl RequestField {
|
||||||
fn new(kind: RequestFieldKind, field: Field) -> RequestField {
|
fn new(kind: RequestFieldKind, field: Field, header: Option<String>) -> RequestField {
|
||||||
match kind {
|
match kind {
|
||||||
RequestFieldKind::Body => RequestField::Body(field),
|
RequestFieldKind::Body => RequestField::Body(field),
|
||||||
RequestFieldKind::Header => RequestField::Header(field),
|
RequestFieldKind::Header => RequestField::Header(field, header.expect("missing header name")),
|
||||||
RequestFieldKind::NewtypeBody => RequestField::NewtypeBody(field),
|
RequestFieldKind::NewtypeBody => RequestField::NewtypeBody(field),
|
||||||
RequestFieldKind::Path => RequestField::Path(field),
|
RequestFieldKind::Path => RequestField::Path(field),
|
||||||
RequestFieldKind::Query => RequestField::Query(field),
|
RequestFieldKind::Query => RequestField::Query(field),
|
||||||
@ -286,11 +319,11 @@ impl RequestField {
|
|||||||
|
|
||||||
fn kind(&self) -> RequestFieldKind {
|
fn kind(&self) -> RequestFieldKind {
|
||||||
match *self {
|
match *self {
|
||||||
RequestField::Body(_) => RequestFieldKind::Body,
|
RequestField::Body(..) => RequestFieldKind::Body,
|
||||||
RequestField::Header(_) => RequestFieldKind::Header,
|
RequestField::Header(..) => RequestFieldKind::Header,
|
||||||
RequestField::NewtypeBody(_) => RequestFieldKind::NewtypeBody,
|
RequestField::NewtypeBody(..) => RequestFieldKind::NewtypeBody,
|
||||||
RequestField::Path(_) => RequestFieldKind::Path,
|
RequestField::Path(..) => RequestFieldKind::Path,
|
||||||
RequestField::Query(_) => RequestFieldKind::Query,
|
RequestField::Query(..) => RequestFieldKind::Query,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -298,6 +331,10 @@ impl RequestField {
|
|||||||
self.kind() == RequestFieldKind::Body
|
self.kind() == RequestFieldKind::Body
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_header(&self) -> bool {
|
||||||
|
self.kind() == RequestFieldKind::Header
|
||||||
|
}
|
||||||
|
|
||||||
fn is_path(&self) -> bool {
|
fn is_path(&self) -> bool {
|
||||||
self.kind() == RequestFieldKind::Path
|
self.kind() == RequestFieldKind::Path
|
||||||
}
|
}
|
||||||
@ -309,7 +346,7 @@ impl RequestField {
|
|||||||
fn field(&self) -> &Field {
|
fn field(&self) -> &Field {
|
||||||
match *self {
|
match *self {
|
||||||
RequestField::Body(ref field) => field,
|
RequestField::Body(ref field) => field,
|
||||||
RequestField::Header(ref field) => field,
|
RequestField::Header(ref field, _) => field,
|
||||||
RequestField::NewtypeBody(ref field) => field,
|
RequestField::NewtypeBody(ref field) => field,
|
||||||
RequestField::Path(ref field) => field,
|
RequestField::Path(ref field) => field,
|
||||||
RequestField::Query(ref field) => field,
|
RequestField::Query(ref field) => field,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use quote::{ToTokens, Tokens};
|
use quote::{ToTokens, Tokens};
|
||||||
use syn::spanned::Spanned;
|
use syn::spanned::Spanned;
|
||||||
use syn::{Field, Meta, NestedMeta};
|
use syn::{Field, Ident, Lit, Meta, NestedMeta};
|
||||||
|
|
||||||
use api::strip_serde_attrs;
|
use api::strip_serde_attrs;
|
||||||
|
|
||||||
@ -34,13 +34,13 @@ impl Response {
|
|||||||
#field_name: response_body.#field_name,
|
#field_name: response_body.#field_name,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
ResponseField::Header(ref field) => {
|
ResponseField::Header(ref field, ref header) => {
|
||||||
let field_name = field.ident.expect("expected field to have an identifier");
|
let field_name = field.ident.expect("expected field to have an identifier");
|
||||||
let field_type = &field.ty;
|
let header_name = Ident::from(header.as_ref());
|
||||||
let span = field.span();
|
let span = field.span();
|
||||||
|
|
||||||
tokens.append_all(quote_spanned! {span=>
|
tokens.append_all(quote_spanned! {span=>
|
||||||
#field_name: headers.remove::<#field_type>()
|
#field_name: headers.remove(::http::header::#header_name)
|
||||||
.expect("missing expected request header"),
|
.expect("missing expected request header"),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -80,6 +80,7 @@ impl From<Vec<Field>> for Response {
|
|||||||
|
|
||||||
let fields = fields.into_iter().map(|mut field| {
|
let fields = fields.into_iter().map(|mut field| {
|
||||||
let mut field_kind = ResponseFieldKind::Body;
|
let mut field_kind = ResponseFieldKind::Body;
|
||||||
|
let mut header = None;
|
||||||
|
|
||||||
field.attrs = field.attrs.into_iter().filter(|attr| {
|
field.attrs = field.attrs.into_iter().filter(|attr| {
|
||||||
let meta = attr.interpret_meta()
|
let meta = attr.interpret_meta()
|
||||||
@ -109,7 +110,14 @@ impl From<Vec<Field>> for Response {
|
|||||||
}
|
}
|
||||||
Meta::NameValue(name_value) => {
|
Meta::NameValue(name_value) => {
|
||||||
match name_value.ident.as_ref() {
|
match name_value.ident.as_ref() {
|
||||||
"header" => field_kind = ResponseFieldKind::Header,
|
"header" => {
|
||||||
|
match name_value.lit {
|
||||||
|
Lit::Str(lit_str) => header = Some(lit_str.value()),
|
||||||
|
_ => panic!("ruma_api! header attribute's value must be a string literal"),
|
||||||
|
}
|
||||||
|
|
||||||
|
field_kind = ResponseFieldKind::Header;
|
||||||
|
}
|
||||||
_ => panic!("ruma_api! name/value pair attribute on requests must be: header"),
|
_ => panic!("ruma_api! name/value pair attribute on requests must be: header"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -133,7 +141,7 @@ impl From<Vec<Field>> for Response {
|
|||||||
return ResponseField::Body(field);
|
return ResponseField::Body(field);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ResponseFieldKind::Header => ResponseField::Header(field),
|
ResponseFieldKind::Header => ResponseField::Header(field, header.expect("missing header name")),
|
||||||
ResponseFieldKind::NewtypeBody => ResponseField::NewtypeBody(field),
|
ResponseFieldKind::NewtypeBody => ResponseField::NewtypeBody(field),
|
||||||
}
|
}
|
||||||
}).collect();
|
}).collect();
|
||||||
@ -220,7 +228,7 @@ impl ToTokens for Response {
|
|||||||
|
|
||||||
pub enum ResponseField {
|
pub enum ResponseField {
|
||||||
Body(Field),
|
Body(Field),
|
||||||
Header(Field),
|
Header(Field, String),
|
||||||
NewtypeBody(Field),
|
NewtypeBody(Field),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -228,21 +236,21 @@ impl ResponseField {
|
|||||||
fn field(&self) -> &Field {
|
fn field(&self) -> &Field {
|
||||||
match *self {
|
match *self {
|
||||||
ResponseField::Body(ref field) => field,
|
ResponseField::Body(ref field) => field,
|
||||||
ResponseField::Header(ref field) => field,
|
ResponseField::Header(ref field, _) => field,
|
||||||
ResponseField::NewtypeBody(ref field) => field,
|
ResponseField::NewtypeBody(ref field) => field,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_body(&self) -> bool {
|
fn is_body(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
ResponseField::Body(_) => true,
|
ResponseField::Body(..) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_header(&self) -> bool {
|
fn is_header(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
ResponseField::Header(_) => true,
|
ResponseField::Header(..) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#![feature(associated_consts, proc_macro, try_from)]
|
#![feature(proc_macro, try_from)]
|
||||||
|
|
||||||
extern crate futures;
|
extern crate futures;
|
||||||
extern crate http;
|
extern crate http;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user