Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@

https://github.com/oxidecomputer/dropshot/compare/v0.16.2\...HEAD[Full list of commits]

* https://github.com/oxidecomputer/dropshot/pull/1382[#1382] Allow 2 more `SharedExtractor`s to be used with the `endpoint` macro

== 0.16.2 (released 2025-05-21)

https://github.com/oxidecomputer/dropshot/compare/v0.16.1\...v0.16.2[Full list of commits]
Expand Down
4 changes: 3 additions & 1 deletion dropshot/src/extractor/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,9 @@ macro_rules! impl_rqextractor_for_tuple {
}
}}

// Implement `RequestExtractor` for any tuple consisting of 0-2 shared
// Implement `RequestExtractor` for any tuple consisting of 0-4 shared
// extractors and exactly one exclusive extractor.
impl_rqextractor_for_tuple!(S1);
impl_rqextractor_for_tuple!(S1, S2);
impl_rqextractor_for_tuple!(S1, S2, S3);
impl_rqextractor_for_tuple!(S1, S2, S3, S4);
8 changes: 8 additions & 0 deletions dropshot/src/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -680,6 +680,14 @@ impl_HttpHandlerFunc_for_func_with_params!();
impl_HttpHandlerFunc_for_func_with_params!((0, T0));
impl_HttpHandlerFunc_for_func_with_params!((0, T1), (1, T2));
impl_HttpHandlerFunc_for_func_with_params!((0, T1), (1, T2), (2, T3));
impl_HttpHandlerFunc_for_func_with_params!((0, T1), (1, T2), (2, T3), (3, T4));
impl_HttpHandlerFunc_for_func_with_params!(
(0, T1),
(1, T2),
(2, T3),
(3, T4),
(4, T5)
);

/// `RouteHandler` abstracts an `HttpHandlerFunc<FuncParams, ResponseType>` in a
/// way that allows callers to invoke the handler without knowing the handler's
Expand Down
2 changes: 1 addition & 1 deletion dropshot/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@
//!
//! `Query` and `Path` impl `SharedExtractor`. `TypedBody`, `UntypedBody`,
//! `StreamingBody`, and `RawRequest` impl `ExclusiveExtractor`. Your function
//! may accept 0-3 extractors, but only one can be `ExclusiveExtractor`, and it
//! may accept 0-5 extractors, but only one can be `ExclusiveExtractor`, and it
//! must be the last one. Otherwise, the order of extractor arguments does not
//! matter.
//!
Expand Down
74 changes: 74 additions & 0 deletions dropshot/tests/integration-tests/openapi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -616,6 +616,78 @@ async fn handler30(
todo!();
}

#[derive(Deserialize, JsonSchema)]
struct PathArgs31 {
#[expect(unused)]
aa: String,
}

#[derive(Deserialize, JsonSchema)]
struct Headers31 {
#[expect(unused)]
header_a: String,
}

#[derive(Deserialize, JsonSchema)]
struct Query31 {
#[expect(unused)]
query_a: String,
}

#[endpoint {
method = GET,
path = "/testing/{aa}",
tags = ["it"]
}]
async fn handler31(
_: RequestContext<()>,
_: Path<PathArgs31>,
_: Header<Headers31>,
_: Query<Query31>,
_: UntypedBody,
) -> Result<HttpResponseOk<CoolStruct>, HttpError> {
todo!();
}

#[derive(Debug, Clone, Serialize, JsonSchema)]
pub struct CustomShared32 {
pub a: String,
}

#[async_trait::async_trait]
impl dropshot::SharedExtractor for CustomShared32 {
async fn from_request<Context: dropshot::ServerContext>(
_rqctx: &RequestContext<Context>,
) -> Result<Self, HttpError> {
Ok(Self { a: "test".to_string() })
}

fn metadata(
_body_content_type: dropshot::ApiEndpointBodyContentType,
) -> dropshot::ExtractorMetadata {
dropshot::ExtractorMetadata {
extension_mode: dropshot::ExtensionMode::None,
parameters: vec![],
}
}
}

#[endpoint {
method = GET,
path = "/testing32/{aa}",
tags = ["it"]
}]
async fn handler32(
_: RequestContext<()>,
_: Path<PathArgs31>,
_: Header<Headers31>,
_: Query<Query31>,
_: CustomShared32,
_: UntypedBody,
) -> Result<HttpResponseOk<CoolStruct>, HttpError> {
todo!();
}

fn make_api(
maybe_tag_config: Option<TagConfig>,
) -> Result<ApiDescription<()>, ApiDescriptionRegisterError> {
Expand Down Expand Up @@ -655,6 +727,8 @@ fn make_api(
api.register(handler28)?;
api.register(handler29)?;
api.register(handler30)?;
api.register(handler31)?;
api.register(handler32)?;
Ok(api)
}

Expand Down
126 changes: 126 additions & 0 deletions dropshot/tests/test_openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -764,6 +764,69 @@
}
}
},
"/testing/{aa}": {
"get": {
"tags": [
"it"
],
"operationId": "handler31",
"parameters": [
{
"in": "path",
"name": "aa",
"required": true,
"schema": {
"type": "string"
}
},
{
"in": "header",
"name": "header_a",
"required": true,
"schema": {
"type": "string"
}
},
{
"in": "query",
"name": "query_a",
"required": true,
"schema": {
"type": "string"
}
}
],
"requestBody": {
"content": {
"application/octet-stream": {
"schema": {
"type": "string",
"format": "binary"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "successful operation",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CoolStruct"
}
}
}
},
"4XX": {
"$ref": "#/components/responses/Error"
},
"5XX": {
"$ref": "#/components/responses/Error"
}
}
}
},
"/testing/{aa}/{bb}": {
"put": {
"tags": [
Expand Down Expand Up @@ -808,6 +871,69 @@
}
}
},
"/testing32/{aa}": {
"get": {
"tags": [
"it"
],
"operationId": "handler32",
"parameters": [
{
"in": "path",
"name": "aa",
"required": true,
"schema": {
"type": "string"
}
},
{
"in": "header",
"name": "header_a",
"required": true,
"schema": {
"type": "string"
}
},
{
"in": "query",
"name": "query_a",
"required": true,
"schema": {
"type": "string"
}
}
],
"requestBody": {
"content": {
"application/octet-stream": {
"schema": {
"type": "string",
"format": "binary"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "successful operation",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CoolStruct"
}
}
}
},
"4XX": {
"$ref": "#/components/responses/Error"
},
"5XX": {
"$ref": "#/components/responses/Error"
}
}
}
},
"/thing_with_headers": {
"get": {
"tags": [
Expand Down
Loading
Loading