diff --git a/rpc/http.go b/rpc/http.go index af79858e2..674166fb3 100644 --- a/rpc/http.go +++ b/rpc/http.go @@ -36,11 +36,15 @@ import ( ) const ( - contentType = "application/json" maxRequestContentLength = 1024 * 512 ) -var nullAddr, _ = net.ResolveTCPAddr("tcp", "127.0.0.1:0") +var ( + // https://www.jsonrpc.org/historical/json-rpc-over-http.html#id13 + acceptedContentTypes = []string{"application/json", "application/json-rpc", "application/jsonrequest"} + contentType = acceptedContentTypes[0] + nullAddr, _ = net.ResolveTCPAddr("tcp", "127.0.0.1:0") +) type httpConn struct { client *http.Client @@ -263,12 +267,21 @@ func validateRequest(r *http.Request) (int, error) { err := fmt.Errorf("content length too large (%d>%d)", r.ContentLength, maxRequestContentLength) return http.StatusRequestEntityTooLarge, err } - mt, _, err := mime.ParseMediaType(r.Header.Get("content-type")) - if r.Method != http.MethodOptions && (err != nil || mt != contentType) { - err := fmt.Errorf("invalid content type, only %s is supported", contentType) - return http.StatusUnsupportedMediaType, err + // Allow OPTIONS (regardless of content-type) + if r.Method == http.MethodOptions { + return 0, nil } - return 0, nil + // Check content-type + if mt, _, err := mime.ParseMediaType(r.Header.Get("content-type")); err == nil { + for _, accepted := range acceptedContentTypes { + if accepted == mt { + return 0, nil + } + } + } + // Invalid content-type + err := fmt.Errorf("invalid content type, only %s is supported", contentType) + return http.StatusUnsupportedMediaType, err } func newCorsHandler(srv *Server, allowedOrigins []string) http.Handler {