Improve mime type parsing

This commit is contained in:
Daniel 2023-10-03 11:21:35 +02:00
parent 1f542005cc
commit 3232f2d644
2 changed files with 19 additions and 18 deletions

View file

@ -98,8 +98,7 @@ func DumpToHTTPResponse(w http.ResponseWriter, r *http.Request, t interface{}) e
// MimeLoad loads the given data into the interface based on the given mime type. // MimeLoad loads the given data into the interface based on the given mime type.
func MimeLoad(data []byte, mimeType string, t interface{}) (format uint8, err error) { func MimeLoad(data []byte, mimeType string, t interface{}) (format uint8, err error) {
// Find format. // Find format.
mimeType = cleanMimeType(mimeType) format = FormatFromMime(mimeType)
format = MimeTypeToFormat[mimeType]
if format == 0 { if format == 0 {
return 0, ErrIncompatibleFormat return 0, ErrIncompatibleFormat
} }
@ -112,9 +111,9 @@ func MimeLoad(data []byte, mimeType string, t interface{}) (format uint8, err er
// MimeDump dumps the given interface based on the given mime type accept header. // MimeDump dumps the given interface based on the given mime type accept header.
func MimeDump(t any, accept string) (data []byte, mimeType string, format uint8, err error) { func MimeDump(t any, accept string) (data []byte, mimeType string, format uint8, err error) {
// Find format. // Find format.
accept = cleanMimeType(accept) accept = extractMimeType(accept)
switch accept { switch accept {
case "", "*", "*/*": case "", "*":
format = DefaultSerializationFormat format = DefaultSerializationFormat
default: default:
format = MimeTypeToFormat[accept] format = MimeTypeToFormat[accept]
@ -132,17 +131,20 @@ func MimeDump(t any, accept string) (data []byte, mimeType string, format uint8,
// FormatFromMime returns the format for the given mime type. // FormatFromMime returns the format for the given mime type.
// Will return AUTO format for unsupported or unrecognized mime types. // Will return AUTO format for unsupported or unrecognized mime types.
func FormatFromMime(mimeType string) (format uint8) { func FormatFromMime(mimeType string) (format uint8) {
return MimeTypeToFormat[cleanMimeType(mimeType)] return MimeTypeToFormat[extractMimeType(mimeType)]
} }
func cleanMimeType(mimeType string) string { func extractMimeType(mimeType string) string {
if strings.Contains(mimeType, ",") { if strings.Contains(mimeType, ",") {
mimeType, _, _ = strings.Cut(mimeType, ",") mimeType, _, _ = strings.Cut(mimeType, ",")
} }
if strings.Contains(mimeType, ";") { if strings.Contains(mimeType, ";") {
mimeType, _, _ = strings.Cut(mimeType, ";") mimeType, _, _ = strings.Cut(mimeType, ";")
} }
return mimeType if strings.Contains(mimeType, "/") {
_, mimeType, _ = strings.Cut(mimeType, "/")
}
return strings.ToLower(mimeType)
} }
// Format and MimeType mappings. // Format and MimeType mappings.
@ -154,12 +156,10 @@ var (
YAML: "application/yaml", YAML: "application/yaml",
} }
MimeTypeToFormat = map[string]uint8{ MimeTypeToFormat = map[string]uint8{
"application/cbor": CBOR, "cbor": CBOR,
"application/json": JSON, "json": JSON,
"application/msgpack": MsgPack, "msgpack": MsgPack,
"application/yaml": YAML, "yaml": YAML,
"text/json": JSON, "yml": YAML,
"text/yaml": YAML,
"text/yml": YAML,
} }
) )

View file

@ -24,12 +24,13 @@ func TestMimeTypes(t *testing.T) {
// Test assumptions. // Test assumptions.
for mimeType, mimeTypeCleaned := range map[string]string{ for mimeType, mimeTypeCleaned := range map[string]string{
"application/xml, image/webp": "application/xml", "application/xml, image/webp": "xml",
"application/xml;q=0.9, image/webp": "application/xml", "application/xml;q=0.9, image/webp": "xml",
"*": "*", "*": "*",
"*/*": "*/*", "*/*": "*",
"text/yAMl": "yaml",
} { } {
cleaned := cleanMimeType(mimeType) cleaned := extractMimeType(mimeType)
assert.Equal(t, mimeTypeCleaned, cleaned, "assumption for %q should hold", mimeType) assert.Equal(t, mimeTypeCleaned, cleaned, "assumption for %q should hold", mimeType)
} }
} }