Skip to content

Commit 784399a

Browse files
authored
Introduce structured and unstructured response headers (#283)
1 parent 8e668f8 commit 784399a

File tree

14 files changed

+976
-106
lines changed

14 files changed

+976
-106
lines changed

CHANGELOG.adoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ https://github.com/oxidecomputer/dropshot/compare/v0.6.0\...HEAD[Full list of co
2525
* https://github.com/oxidecomputer/dropshot/pull/198[#198] Responses that used `()` (the unit type) as their `Body` type parameter previously (and inaccurately) were represented in OpenAPI as an empty `responseBody`. They are now more accurately represented as a body whose value is `null` (4 bytes). We encourage those use cases to instead use either `HttpResponseUpdatedNoContent` or `HttpResponseDeleted` both of which have empty response bodies. If there are other situations where you would like a response type with no body, please file an issue.
2626
* https://github.com/oxidecomputer/dropshot/pull/252[#252] Endpoints specified with the `#[endpoint ..]` attribute macro now use the first line of a doc comment as the OpenAPI `summary` and subsequent lines as the `description`. Previously all lines were used as the `description`.
2727
* https://github.com/oxidecomputer/dropshot/pull/260[#260] Pulls in a newer serde that changes error messages around parsing NonZeroU32.
28+
* https://github.com/oxidecomputer/dropshot/pull/283[#283] Add support for response headers with the `HttpResponseHeaders` type. Headers may either be defined by a struct type parameter (in which case they appear in the OpenAPI output) or *ad-hoc* added via `HttpResponseHeaders::headers_mut()`.
2829

2930
== 0.6.0 (released 2021-11-18)
3031

dropshot/src/api_description.rs

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -134,17 +134,16 @@ impl ApiEndpointParameter {
134134

135135
pub fn new_body(
136136
content_type: ApiEndpointBodyContentType,
137-
description: Option<String>,
138137
required: bool,
139138
schema: ApiSchemaGenerator,
140139
examples: Vec<String>,
141140
) -> Self {
142141
Self {
143142
metadata: ApiEndpointParameterMetadata::Body(content_type),
144-
description,
145143
required,
146144
schema,
147145
examples,
146+
description: None,
148147
}
149148
}
150149
}
@@ -179,12 +178,21 @@ impl ApiEndpointBodyContentType {
179178
}
180179
}
181180

181+
#[derive(Debug)]
182+
pub struct ApiEndpointHeader {
183+
pub name: String,
184+
pub description: Option<String>,
185+
pub schema: ApiSchemaGenerator,
186+
pub required: bool,
187+
}
188+
182189
/**
183190
* Metadata for an API endpoint response: type information and status code.
184191
*/
185-
#[derive(Debug)]
192+
#[derive(Debug, Default)]
186193
pub struct ApiEndpointResponse {
187194
pub schema: Option<ApiSchemaGenerator>,
195+
pub headers: Vec<ApiEndpointHeader>,
188196
pub success: Option<StatusCode>,
189197
pub description: Option<String>,
190198
}
@@ -603,6 +611,45 @@ impl<Context: ServerContext> ApiDescription<Context> {
603611
);
604612
}
605613

614+
let headers = endpoint
615+
.response
616+
.headers
617+
.iter()
618+
.map(|header| {
619+
let schema = match &header.schema {
620+
ApiSchemaGenerator::Static {
621+
schema,
622+
dependencies,
623+
} => {
624+
definitions.extend(dependencies.clone());
625+
j2oas_schema(None, schema)
626+
}
627+
_ => {
628+
unimplemented!(
629+
"this may happen for complex types"
630+
)
631+
}
632+
};
633+
634+
(
635+
header.name.clone(),
636+
openapiv3::ReferenceOr::Item(openapiv3::Header {
637+
description: header.description.clone(),
638+
style: openapiv3::HeaderStyle::Simple,
639+
required: header.required,
640+
deprecated: None,
641+
format:
642+
openapiv3::ParameterSchemaOrContent::Schema(
643+
schema,
644+
),
645+
example: None,
646+
examples: indexmap::IndexMap::new(),
647+
extensions: indexmap::IndexMap::new(),
648+
}),
649+
)
650+
})
651+
.collect();
652+
606653
let response = openapiv3::Response {
607654
description: if let Some(description) =
608655
&endpoint.response.description
@@ -614,7 +661,8 @@ impl<Context: ServerContext> ApiDescription<Context> {
614661
// by OpenAPI.
615662
"".to_string()
616663
},
617-
content: content,
664+
content,
665+
headers,
618666
..Default::default()
619667
};
620668

0 commit comments

Comments
 (0)