|
1 | 1 | """OpenAPI core templating media types finders module"""
|
2 | 2 |
|
3 | 3 | import fnmatch
|
| 4 | +import re |
4 | 5 | from typing import Mapping
|
5 | 6 | from typing import Tuple
|
6 | 7 |
|
@@ -38,12 +39,32 @@ def find(self, mimetype: str) -> MediaType:
|
38 | 39 | raise MediaTypeNotFound(mimetype, list(self.content.keys()))
|
39 | 40 |
|
40 | 41 | def _parse_mimetype(self, mimetype: str) -> Tuple[str, Mapping[str, str]]:
|
41 |
| - mimetype_parts = mimetype.split("; ") |
42 |
| - mime_type = mimetype_parts[0] |
| 42 | + mimetype_parts = mimetype.split(";") |
| 43 | + mime_type = mimetype_parts[0].lower().rstrip() |
43 | 44 | parameters = {}
|
44 | 45 | if len(mimetype_parts) > 1:
|
45 | 46 | parameters_list = (
|
46 |
| - param_str.split("=") for param_str in mimetype_parts[1:] |
| 47 | + self._parse_parameter(param_str) |
| 48 | + for param_str in mimetype_parts[1:] |
47 | 49 | )
|
48 | 50 | parameters = dict(parameters_list)
|
49 | 51 | return mime_type, parameters
|
| 52 | + |
| 53 | + def _parse_parameter(self, parameter: str) -> Tuple[str, str]: |
| 54 | + """Parse a parameter according to RFC 9110. |
| 55 | +
|
| 56 | + See https://www.rfc-editor.org/rfc/rfc9110.html#name-parameters |
| 57 | +
|
| 58 | + Important points: |
| 59 | + * parameter names are case-insensitive |
| 60 | + * parameter values are case-sensitive |
| 61 | + except "charset" which is case-insensitive |
| 62 | + https://www.rfc-editor.org/rfc/rfc2046#section-4.1.2 |
| 63 | + """ |
| 64 | + name, value = parameter.split("=") |
| 65 | + name = name.lower().lstrip() |
| 66 | + # remove surrounding quotes from value |
| 67 | + value = re.sub('^"(.*)"$', r"\1", value, count=1) |
| 68 | + if name == "charset": |
| 69 | + value = value.lower() |
| 70 | + return name, value.rstrip() |
0 commit comments