diff --git a/CHANGELOG.next.toml b/CHANGELOG.next.toml index 3f5cea1331..6fd2ee4a8c 100644 --- a/CHANGELOG.next.toml +++ b/CHANGELOG.next.toml @@ -15,3 +15,11 @@ message = "A feature, `aws-lambda`, has been added to generated SDKs to re-expor references = ["smithy-rs#3643"] meta = { "breaking" = false, "bug" = true, "tada" = false, "target" = "server" } author = "drganjoo" + +[[smithy-rs]] +message = """ +Content-Type header validation now ignores parameter portion of media types. +""" +references = ["smithy-rs#3471","smithy-rs#3724"] +meta = { "breaking" = false, "tada" = false, "bug" = true, target = "server" } +authors = ["djedward"] diff --git a/codegen-core/common-test-models/rest-xml-extras.smithy b/codegen-core/common-test-models/rest-xml-extras.smithy new file mode 100644 index 0000000000..5a47976009 --- /dev/null +++ b/codegen-core/common-test-models/rest-xml-extras.smithy @@ -0,0 +1,53 @@ +$version: "2.0" + +namespace aws.protocoltests.restxml + +use aws.api#service +use aws.protocols#restXml +use smithy.test#httpRequestTests + +/// A REST XML service that sends XML requests and responses. +@service(sdkId: "Rest Xml Protocol") +@restXml +@title("Sample Rest Xml Protocol Service") +service RestXmlExtras { + version: "2024-04-15", + operations: [ + ContentTypeParameters + ] +} + +/// The example tests how servers must support requests +/// containing a `Content-Type` header with parameters. +@http(uri: "/ContentTypeParameters", method: "PUT") +operation ContentTypeParameters { + input: ContentTypeParametersInput, + output: ContentTypeParametersOutput +} + +apply ContentTypeParameters @httpRequestTests([ + { + id: "RestXmlMustSupportParametersInContentType", + documentation: "A server should ignore parameters added to the content type", + protocol: restXml, + method: "PUT", + headers: { + "Content-Type": "application/xml; charset=utf-8" + }, + uri: "/ContentTypeParameters", + body: "5", + bodyMediaType: "application/xml", + params: { + value: 5, + }, + appliesTo: "server" + } +]) + +@input +structure ContentTypeParametersInput { + value: Integer, +} + +@output +structure ContentTypeParametersOutput {} diff --git a/codegen-server-test/build.gradle.kts b/codegen-server-test/build.gradle.kts index 509b921877..36d942c840 100644 --- a/codegen-server-test/build.gradle.kts +++ b/codegen-server-test/build.gradle.kts @@ -100,6 +100,11 @@ val allCodegenTests = "../codegen-core/common-test-models".let { commonModels -> "pokemon-service-awsjson-server-sdk", imports = listOf("$commonModels/pokemon-awsjson.smithy", "$commonModels/pokemon-common.smithy"), ), + CodegenTest( + "aws.protocoltests.restxml#RestXmlExtras", + "rest_xml_extras", + imports = listOf("$commonModels/rest-xml-extras.smithy"), + ), ) } diff --git a/rust-runtime/Cargo.lock b/rust-runtime/Cargo.lock index 77ff2b31d0..b808989551 100644 --- a/rust-runtime/Cargo.lock +++ b/rust-runtime/Cargo.lock @@ -465,7 +465,7 @@ version = "0.60.3" [[package]] name = "aws-smithy-http-server" -version = "0.62.0" +version = "0.62.1" dependencies = [ "aws-smithy-http 0.60.9", "aws-smithy-json 0.60.7", diff --git a/rust-runtime/aws-smithy-http-server/Cargo.toml b/rust-runtime/aws-smithy-http-server/Cargo.toml index c1b40cad68..3fefabbe9a 100644 --- a/rust-runtime/aws-smithy-http-server/Cargo.toml +++ b/rust-runtime/aws-smithy-http-server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "aws-smithy-http-server" -version = "0.62.0" +version = "0.62.1" authors = ["Smithy Rust Server "] edition = "2021" license = "Apache-2.0" @@ -29,7 +29,7 @@ http = "0.2" http-body = "0.4" hyper = { version = "0.14.26", features = ["server", "http1", "http2", "tcp", "stream"] } lambda_http = { version = "0.8.0", optional = true } -mime = "0.3.4" +mime = "0.3.17" nom = "7" once_cell = "1.13" pin-project-lite = "0.2" diff --git a/rust-runtime/aws-smithy-http-server/src/protocol/mod.rs b/rust-runtime/aws-smithy-http-server/src/protocol/mod.rs index e7eb963e98..27a16d9f18 100644 --- a/rust-runtime/aws-smithy-http-server/src/protocol/mod.rs +++ b/rust-runtime/aws-smithy-http-server/src/protocol/mod.rs @@ -93,7 +93,7 @@ fn content_type_header_classifier( (Some(actual_content_type), Some(expected_content_type)) => { let expected_mime = parse_expected_mime(expected_content_type); let found_mime = parse_mime(actual_content_type)?; - if expected_mime != found_mime { + if expected_mime != found_mime.essence_str() { Err(MissingContentTypeReason::UnexpectedMimeType { expected_mime: Some(expected_mime), found_mime: Some(found_mime), @@ -241,6 +241,13 @@ mod tests { )); } + #[test] + fn valid_content_type_header_classifier_http_params() { + let request = req_content_type_smithy("application/json; charset=utf-8"); + let result = content_type_header_classifier_smithy(&request, APPLICATION_JSON); + assert!(result.is_ok()); + } + #[test] fn valid_accept_header_classifier_multiple_values() { let valid_request = req_accept("text/strings, application/json, invalid");