|
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