Skip to content

Commit 0dd901c

Browse files
Replace mime crate with mediatype crate
1 parent faf0648 commit 0dd901c

File tree

5 files changed

+51
-62
lines changed

5 files changed

+51
-62
lines changed

codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerCargoDependency.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ object ServerCargoDependency {
1818
val AsyncTrait: CargoDependency = CargoDependency("async-trait", CratesIo("0.1"))
1919
val FormUrlEncoded: CargoDependency = CargoDependency("form_urlencoded", CratesIo("1"))
2020
val FuturesUtil: CargoDependency = CargoDependency("futures-util", CratesIo("0.3"))
21-
val Mime: CargoDependency = CargoDependency("mime", CratesIo("0.3"))
21+
val MediaType: CargoDependency = CargoDependency("mediatype", CratesIo("0.19.15"))
2222
val Nom: CargoDependency = CargoDependency("nom", CratesIo("7"))
2323
val OnceCell: CargoDependency = CargoDependency("once_cell", CratesIo("1.13"))
2424
val PinProjectLite: CargoDependency = CargoDependency("pin-project-lite", CratesIo("0.2"))

codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/ServerHttpBoundProtocolGenerator.kt

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ class ServerHttpBoundProtocolTraitImplGenerator(
185185
"header_util" to RuntimeType.smithyHttp(runtimeConfig).resolve("header"),
186186
"Hyper" to RuntimeType.Hyper,
187187
"LazyStatic" to RuntimeType.LazyStatic,
188-
"Mime" to ServerCargoDependency.Mime.toType(),
188+
"MediaType" to ServerCargoDependency.MediaType.toType(),
189189
"Nom" to ServerCargoDependency.Nom.toType(),
190190
"OnceCell" to RuntimeType.OnceCell,
191191
"PercentEncoding" to RuntimeType.PercentEncoding,
@@ -237,18 +237,16 @@ class ServerHttpBoundProtocolTraitImplGenerator(
237237
}
238238
val verifyAcceptHeaderStaticContentTypeInit = writable {
239239
httpBindingResolver.responseContentType(operationShape)?.also { contentType ->
240-
val init = when (contentType) {
241-
"application/json" -> "const $staticContentType: #{Mime}::Mime = #{Mime}::APPLICATION_JSON;"
242-
"application/octet-stream" -> "const $staticContentType: #{Mime}::Mime = #{Mime}::APPLICATION_OCTET_STREAM;"
243-
"application/x-www-form-urlencoded" -> "const $staticContentType: #{Mime}::Mime = #{Mime}::APPLICATION_WWW_FORM_URLENCODED;"
244-
else ->
245-
"""
246-
static $staticContentType: #{OnceCell}::sync::Lazy<#{Mime}::Mime> = #{OnceCell}::sync::Lazy::new(|| {
247-
${contentType.dq()}.parse::<#{Mime}::Mime>().expect("BUG: MIME parsing failed, content_type is not valid")
248-
});
249-
"""
250-
}
251-
rustTemplate(init, *codegenScope)
240+
val (type, subtype) = contentType.split('/')
241+
rustTemplate(
242+
"""
243+
const $staticContentType: #{MediaType}::MediaType = #{MediaType}::MediaType::new(
244+
#{MediaType}::Name::new_unchecked(${type.dq()}),
245+
#{MediaType}::Name::new_unchecked(${subtype.dq()})
246+
);
247+
""",
248+
*codegenScope,
249+
)
252250
}
253251
}
254252
// This checks for the expected `Content-Type` header if the `@httpPayload` trait is present, as dictated by

rust-runtime/aws-smithy-http-server/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ http = "0.2"
3030
http-body = "0.4"
3131
hyper = { version = "0.14.26", features = ["server", "http1", "http2", "tcp", "stream"] }
3232
lambda_http = { version = "0.8.0", optional = true }
33-
mime = "0.3.4"
33+
mediatype = "0.19.15"
3434
nom = "7"
3535
once_cell = "1.13"
3636
pin-project-lite = "0.2"

rust-runtime/aws-smithy-http-server/src/protocol/mod.rs

Lines changed: 35 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,8 @@ pub mod test_helpers {
4040
}
4141

4242
#[allow(clippy::result_large_err)]
43-
fn parse_mime(content_type: &str) -> Result<mime::Mime, MissingContentTypeReason> {
44-
content_type
45-
.parse::<mime::Mime>()
46-
.map_err(MissingContentTypeReason::MimeParseError)
43+
fn parse_mime(content_type: &str) -> Result<mediatype::MediaType, MissingContentTypeReason> {
44+
mediatype::MediaType::parse(content_type).map_err(MissingContentTypeReason::MimeParseError)
4745
}
4846

4947
/// When there are no modeled inputs,
@@ -52,15 +50,11 @@ fn parse_mime(content_type: &str) -> Result<mime::Mime, MissingContentTypeReason
5250
pub fn content_type_header_empty_body_no_modeled_input(
5351
headers: &SmithyHeaders,
5452
) -> Result<(), MissingContentTypeReason> {
55-
if headers.contains_key(http::header::CONTENT_TYPE) {
56-
let found_mime = headers
57-
.get(http::header::CONTENT_TYPE)
58-
.unwrap() // The header is present, `unwrap` will not panic.
59-
.parse::<mime::Mime>()
60-
.map_err(MissingContentTypeReason::MimeParseError)?;
53+
if let Some(header) = headers.get(http::header::CONTENT_TYPE) {
54+
let found_mime = parse_mime(header)?;
6155
Err(MissingContentTypeReason::UnexpectedMimeType {
6256
expected_mime: None,
63-
found_mime: Some(found_mime),
57+
found_mime: Some(found_mime.into()),
6458
})
6559
} else {
6660
Ok(())
@@ -102,28 +96,28 @@ fn content_type_header_classifier(
10296
let found_mime = parse_mime(content_type)?;
10397
// There is a `content-type` header.
10498
// If there is an implied content type, they must match.
105-
if let Some(expected_content_type) = expected_content_type {
106-
let expected_mime = expected_content_type
107-
.parse::<mime::Mime>()
108-
// `expected_content_type` comes from the codegen.
109-
.expect("BUG: MIME parsing failed, `expected_content_type` is not valid. Please file a bug report under https://github.com/smithy-lang/smithy-rs/issues");
110-
if expected_content_type != found_mime {
111-
return Err(MissingContentTypeReason::UnexpectedMimeType {
112-
expected_mime: Some(expected_mime),
113-
found_mime: Some(found_mime),
114-
});
115-
}
116-
} else {
99+
100+
let Some(expected_content_type) = expected_content_type else {
117101
// `content-type` header and no modeled input (mismatch).
118102
return Err(MissingContentTypeReason::UnexpectedMimeType {
119103
expected_mime: None,
120-
found_mime: Some(found_mime),
104+
found_mime: Some(found_mime.into()),
105+
})
106+
};
107+
108+
let expected_mime = mediatype::MediaType::parse(expected_content_type)
109+
// `expected_content_type` comes from the codegen.
110+
.expect("BUG: MIME parsing failed, `expected_content_type` is not valid. Please file a bug report under https://github.com/smithy-lang/smithy-rs/issues");
111+
if expected_mime != found_mime {
112+
return Err(MissingContentTypeReason::UnexpectedMimeType {
113+
expected_mime: Some(expected_mime.into()),
114+
found_mime: Some(found_mime.into()),
121115
});
122116
}
123117
Ok(())
124118
}
125119

126-
pub fn accept_header_classifier(headers: &HeaderMap, content_type: &mime::Mime) -> bool {
120+
pub fn accept_header_classifier(headers: &HeaderMap, content_type: &mediatype::MediaType) -> bool {
127121
if !headers.contains_key(http::header::ACCEPT) {
128122
return true;
129123
}
@@ -143,15 +137,15 @@ pub fn accept_header_classifier(headers: &HeaderMap, content_type: &mime::Mime)
143137
*/
144138
.flat_map(|s| s.split(',').map(|typ| typ.split(';').next().unwrap().trim()))
145139
})
146-
.filter_map(|h| h.parse::<mime::Mime>().ok())
140+
.filter_map(|h| mediatype::MediaType::parse(h).ok())
147141
.any(|mim| {
148-
let typ = content_type.type_();
149-
let subtype = content_type.subtype();
142+
let typ = content_type.ty;
143+
let subtype = content_type.subty;
150144
// Accept: */*, type/*, type/subtype
151-
match (mim.type_(), mim.subtype()) {
152-
(t, s) if t == typ && s == subtype => true,
153-
(t, mime::STAR) if t == typ => true,
154-
(mime::STAR, mime::STAR) => true,
145+
match (mim.ty.as_str(), mim.subty.as_str()) {
146+
(t, s) if typ == t && subtype == s => true,
147+
(t, "*") if typ == t => true,
148+
("*", "*") => true,
155149
_ => false,
156150
}
157151
})
@@ -221,11 +215,8 @@ mod tests {
221215
expected_mime,
222216
found_mime,
223217
} => {
224-
assert_eq!(
225-
expected_mime.unwrap(),
226-
"application/json".parse::<mime::Mime>().unwrap()
227-
);
228-
assert_eq!(found_mime, invalid_mime.parse::<mime::Mime>().ok());
218+
assert_eq!(expected_mime.unwrap(), mediatype::media_type!(APPLICATION / JSON));
219+
assert_eq!(found_mime, invalid_mime.parse::<mediatype::MediaTypeBuf>().ok());
229220
}
230221
_ => panic!("Unexpected `MissingContentTypeReason`: {}", e),
231222
},
@@ -262,7 +253,7 @@ mod tests {
262253
let valid_request = req_accept("text/strings, application/json, invalid");
263254
assert!(accept_header_classifier(
264255
&valid_request,
265-
&"application/json".parse().unwrap()
256+
&mediatype::MediaType::parse("application/json").unwrap()
266257
));
267258
}
268259

@@ -271,7 +262,7 @@ mod tests {
271262
let invalid_request = req_accept("text/invalid, invalid, invalid/invalid");
272263
assert!(!accept_header_classifier(
273264
&invalid_request,
274-
&"application/json".parse().unwrap()
265+
&mediatype::media_type!(APPLICATION / JSON)
275266
));
276267
}
277268

@@ -280,7 +271,7 @@ mod tests {
280271
let valid_request = req_accept("application/*");
281272
assert!(accept_header_classifier(
282273
&valid_request,
283-
&"application/json".parse().unwrap()
274+
&mediatype::media_type!(APPLICATION / JSON)
284275
));
285276
}
286277

@@ -289,15 +280,15 @@ mod tests {
289280
let valid_request = req_accept("*/*");
290281
assert!(accept_header_classifier(
291282
&valid_request,
292-
&"application/json".parse().unwrap()
283+
&mediatype::media_type!(APPLICATION / JSON)
293284
));
294285
}
295286

296287
#[test]
297288
fn valid_empty_accept_header_classifier() {
298289
assert!(accept_header_classifier(
299290
&HeaderMap::new(),
300-
&"application/json".parse().unwrap()
291+
&mediatype::media_type!(APPLICATION / JSON)
301292
));
302293
}
303294

@@ -306,7 +297,7 @@ mod tests {
306297
let valid_request = req_accept("application/json; q=30, */*");
307298
assert!(accept_header_classifier(
308299
&valid_request,
309-
&"application/json".parse().unwrap()
300+
&mediatype::media_type!(APPLICATION / JSON)
310301
));
311302
}
312303

@@ -315,7 +306,7 @@ mod tests {
315306
let valid_request = req_accept("application/json");
316307
assert!(accept_header_classifier(
317308
&valid_request,
318-
&"application/json".parse().unwrap()
309+
&mediatype::media_type!(APPLICATION / JSON)
319310
));
320311
}
321312
}

rust-runtime/aws-smithy-http-server/src/rejection.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@ pub enum MissingContentTypeReason {
1616
#[error("`Content-Type` header value is not a valid HTTP header value: {0}")]
1717
ToStrError(http::header::ToStrError),
1818
#[error("invalid `Content-Type` header value mime type: {0}")]
19-
MimeParseError(mime::FromStrError),
19+
MimeParseError(mediatype::MediaTypeError),
2020
#[error("unexpected `Content-Type` header value; expected {expected_mime:?}, found {found_mime:?}")]
2121
UnexpectedMimeType {
22-
expected_mime: Option<mime::Mime>,
23-
found_mime: Option<mime::Mime>,
22+
expected_mime: Option<mediatype::MediaTypeBuf>,
23+
found_mime: Option<mediatype::MediaTypeBuf>,
2424
},
2525
}
2626

0 commit comments

Comments
 (0)