Skip to content

runtime.MarshalerForRequest: Content-Type should have been parsed before querying mimeMap #1505

Closed
@movsb

Description

🐛 Bug Report

The Content-Type header field of http.Request may have parameters (MDN):

Content-Type: text/html; charset=UTF-8
Content-Type: multipart/form-data; boundary=something

But when we register a mime into mimeMap, we don't care them:

var m your.MsgPackMarshaler
mux := runtime.NewServeMux(
    runtime.WithMarshalerOption("application/x-msgpack", m),
)

A Content-Type with parameters causes no match:

for _, contentTypeVal := range r.Header[contentTypeHeader] {
if m, ok := mux.marshalers.mimeMap[contentTypeVal]; ok {
inbound = m
break
}
}

To Reproduce

Upload a file and we can see that Content-Type gets different parameters, every time:

$ curl -vF file=@go.mod localhost:2564/v3/ping 
*   Trying ::1...
* TCP_NODELAY set
* Connection failed
* connect to ::1 port 2564 failed: Connection refused
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 2564 (#0)
> POST /v3/ping HTTP/1.1
> Host: localhost:2564
> User-Agent: curl/7.64.1
> Accept: */*
> Content-Length: 1312
> Content-Type: multipart/form-data; boundary=------------------------574891a52a1a9324
> Expect: 100-continue
> 
< HTTP/1.1 100 Continue
* We are completely uploaded and fine
< HTTP/1.1 200 OK
< Content-Type: multipart/form-data
< Date: Mon, 06 Jul 2020 17:19:45 GMT
< Content-Length: 15
< 
* Connection #0 to host localhost left intact
{"pong":"pong"}* Closing connection 0

Expected behavior

Parse Content-Type before querying mimeMap:

diff --git a/runtime/marshaler_registry.go b/runtime/marshaler_registry.go
index 5cc53ae..17e63e4 100644
--- a/runtime/marshaler_registry.go
+++ b/runtime/marshaler_registry.go
@@ -2,6 +2,7 @@ package runtime
 
 import (
 	"errors"
+	"mime"
 	"net/http"
 )
 
@@ -31,7 +32,11 @@ func MarshalerForRequest(mux *ServeMux, r *http.Request) (inbound Marshaler, out
 	}
 
 	for _, contentTypeVal := range r.Header[contentTypeHeader] {
-		if m, ok := mux.marshalers.mimeMap[contentTypeVal]; ok {
+		contentType, _, err := mime.ParseMediaType(contentTypeVal)
+		if err != nil {
+			continue
+		}
+		if m, ok := mux.marshalers.mimeMap[contentType]; ok {
 			inbound = m
 			break
 		}

Actual Behavior

No marshaler was found.

Your Environment

Any.

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions