api-macros: Make Response header fields override any defaults

This commit is contained in:
Devin Ragotzy 2020-11-01 05:04:34 -08:00 committed by GitHub
parent 60bd16ccfc
commit c15382ca41
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 58 additions and 10 deletions

View File

@ -289,10 +289,13 @@ impl ToTokens for Api {
let mut resp_builder = #ruma_api_import::exports::http::Response::builder() let mut resp_builder = #ruma_api_import::exports::http::Response::builder()
.header(#ruma_api_import::exports::http::header::CONTENT_TYPE, "application/json"); .header(#ruma_api_import::exports::http::header::CONTENT_TYPE, "application/json");
let mut headers =
resp_builder.headers_mut().expect("`http::ResponseBuilder` is in unusable state");
#serialize_response_headers #serialize_response_headers
// Since we require header names to come from the `http::header` module, // This cannot fail because we parse each header value
// this cannot fail. // checking for errors as each value is inserted and
// we only allow keys from the `http::header` module.
let response = resp_builder.body(#body).unwrap(); let response = resp_builder.body(#body).unwrap();
Ok(response) Ok(response)
} }

View File

@ -123,17 +123,19 @@ impl Response {
{ {
quote! { quote! {
if let Some(header) = response.#field_name { if let Some(header) = response.#field_name {
resp_builder = resp_builder.header( headers
.insert(
#import_path::exports::http::header::#header_name, #import_path::exports::http::header::#header_name,
header, header.parse()?,
); );
} }
} }
} }
_ => quote! { _ => quote! {
resp_builder = resp_builder.header( headers
.insert(
#import_path::exports::http::header::#header_name, #import_path::exports::http::header::#header_name,
response.#field_name, response.#field_name.parse()?,
); );
}, },
}; };

View File

@ -0,0 +1,42 @@
use std::convert::TryFrom;
use http::header::{Entry, CONTENT_TYPE};
use ruma_api::ruma_api;
ruma_api! {
metadata: {
description: "Does something.",
method: GET,
name: "no_fields",
path: "/_matrix/my/endpoint",
rate_limited: false,
authentication: None,
}
request: {
#[ruma_api(header = LOCATION)]
pub location: Option<String>,
}
response: {
#[ruma_api(header = CONTENT_TYPE)]
pub stuff: String,
}
}
#[test]
fn content_type_override() {
let res = Response { stuff: "magic".into() };
let mut http_res = http::Response::<Vec<u8>>::try_from(res).unwrap();
// Test that we correctly replaced the default content type,
// not adding another content-type header.
assert_eq!(
match http_res.headers_mut().entry(CONTENT_TYPE) {
Entry::Occupied(occ) => occ.iter().count(),
_ => 0,
},
1
);
assert_eq!(http_res.headers().get("content-type").unwrap(), "magic");
}

View File

@ -14,6 +14,7 @@ ruma_api! {
#[ruma_api(header = LOCATION)] #[ruma_api(header = LOCATION)]
pub location: Option<String>, pub location: Option<String>,
} }
response: { response: {
#[ruma_api(header = LOCATION)] #[ruma_api(header = LOCATION)]
pub stuff: Option<String>, pub stuff: Option<String>,