mirror of
https://github.com/rclone/rclone.git
synced 2025-03-13 06:49:15 +01:00
rcserver: improve content-type check
Some libraries use `application/json; charset=utf-8` as their `Content-Type`, which is valid. However we were not decoding the JSON body in that case, resulting in issues communicating with the rcserver.
This commit is contained in:
parent
401cf81034
commit
65f7eb0fba
@ -209,8 +209,21 @@ func (s *Server) handlePost(w http.ResponseWriter, r *http.Request, path string)
|
|||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
contentType := r.Header.Get("Content-Type")
|
contentType := r.Header.Get("Content-Type")
|
||||||
|
|
||||||
|
var (
|
||||||
|
contentTypeMediaType string
|
||||||
|
contentTypeParams map[string]string
|
||||||
|
)
|
||||||
|
if contentType != "" {
|
||||||
|
var err error
|
||||||
|
contentTypeMediaType, contentTypeParams, err = mime.ParseMediaType(contentType)
|
||||||
|
if err != nil {
|
||||||
|
writeError(path, nil, w, fmt.Errorf("failed to parse Content-Type: %w", err), http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
values := r.URL.Query()
|
values := r.URL.Query()
|
||||||
if contentType == "application/x-www-form-urlencoded" {
|
if contentTypeMediaType == "application/x-www-form-urlencoded" {
|
||||||
// Parse the POST and URL parameters into r.Form, for others r.Form will be empty value
|
// Parse the POST and URL parameters into r.Form, for others r.Form will be empty value
|
||||||
err := r.ParseForm()
|
err := r.ParseForm()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -229,7 +242,13 @@ func (s *Server) handlePost(w http.ResponseWriter, r *http.Request, path string)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Parse a JSON blob from the input
|
// Parse a JSON blob from the input
|
||||||
if contentType == "application/json" {
|
if contentTypeMediaType == "application/json" {
|
||||||
|
// Check the charset is utf-8 or unset
|
||||||
|
if charset, ok := contentTypeParams["charset"]; ok && !strings.EqualFold(charset, "utf-8") {
|
||||||
|
writeError(path, in, w, fmt.Errorf("unsupported charset %q for JSON input", charset), http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
err := json.NewDecoder(r.Body).Decode(&in)
|
err := json.NewDecoder(r.Body).Decode(&in)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
writeError(path, in, w, fmt.Errorf("failed to read input JSON: %w", err), http.StatusBadRequest)
|
writeError(path, in, w, fmt.Errorf("failed to read input JSON: %w", err), http.StatusBadRequest)
|
||||||
|
@ -429,6 +429,18 @@ func TestRC(t *testing.T) {
|
|||||||
"param1": "string",
|
"param1": "string",
|
||||||
"param2": true
|
"param2": true
|
||||||
}
|
}
|
||||||
|
`,
|
||||||
|
}, {
|
||||||
|
Name: "json-mixed-case-content-type",
|
||||||
|
URL: "rc/noop",
|
||||||
|
Method: "POST",
|
||||||
|
Body: `{ "param1":"string", "param2":true }`,
|
||||||
|
ContentType: "ApplicAtion/JsOn",
|
||||||
|
Status: http.StatusOK,
|
||||||
|
Expected: `{
|
||||||
|
"param1": "string",
|
||||||
|
"param2": true
|
||||||
|
}
|
||||||
`,
|
`,
|
||||||
}, {
|
}, {
|
||||||
Name: "json-and-url-params",
|
Name: "json-and-url-params",
|
||||||
@ -459,6 +471,44 @@ func TestRC(t *testing.T) {
|
|||||||
"path": "rc/noop",
|
"path": "rc/noop",
|
||||||
"status": 400
|
"status": 400
|
||||||
}
|
}
|
||||||
|
`,
|
||||||
|
}, {
|
||||||
|
Name: "json-charset",
|
||||||
|
URL: "rc/noop",
|
||||||
|
Method: "POST",
|
||||||
|
Body: `{ "param1":"string", "param2":true }`,
|
||||||
|
ContentType: "application/json; charset=utf-8",
|
||||||
|
Status: http.StatusOK,
|
||||||
|
Expected: `{
|
||||||
|
"param1": "string",
|
||||||
|
"param2": true
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
}, {
|
||||||
|
Name: "json-mixed-case-charset",
|
||||||
|
URL: "rc/noop",
|
||||||
|
Method: "POST",
|
||||||
|
Body: `{ "param1":"string", "param2":true }`,
|
||||||
|
ContentType: "aPPlication/jSoN; charset=UtF-8",
|
||||||
|
Status: http.StatusOK,
|
||||||
|
Expected: `{
|
||||||
|
"param1": "string",
|
||||||
|
"param2": true
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
}, {
|
||||||
|
Name: "json-bad-charset",
|
||||||
|
URL: "rc/noop",
|
||||||
|
Method: "POST",
|
||||||
|
Body: `{ "param1":"string", "param2":true }`,
|
||||||
|
ContentType: "application/json; charset=latin1",
|
||||||
|
Status: http.StatusBadRequest,
|
||||||
|
Expected: `{
|
||||||
|
"error": "unsupported charset \"latin1\" for JSON input",
|
||||||
|
"input": {},
|
||||||
|
"path": "rc/noop",
|
||||||
|
"status": 400
|
||||||
|
}
|
||||||
`,
|
`,
|
||||||
}, {
|
}, {
|
||||||
Name: "form",
|
Name: "form",
|
||||||
@ -498,6 +548,19 @@ func TestRC(t *testing.T) {
|
|||||||
"path": "rc/noop",
|
"path": "rc/noop",
|
||||||
"status": 400
|
"status": 400
|
||||||
}
|
}
|
||||||
|
`,
|
||||||
|
}, {
|
||||||
|
Name: "malformed-content-type",
|
||||||
|
URL: "rc/noop",
|
||||||
|
Method: "POST",
|
||||||
|
ContentType: "malformed/",
|
||||||
|
Status: http.StatusBadRequest,
|
||||||
|
Expected: `{
|
||||||
|
"error": "failed to parse Content-Type: mime: expected token after slash",
|
||||||
|
"input": null,
|
||||||
|
"path": "rc/noop",
|
||||||
|
"status": 400
|
||||||
|
}
|
||||||
`,
|
`,
|
||||||
}}
|
}}
|
||||||
opt := newTestOpt()
|
opt := newTestOpt()
|
||||||
|
Loading…
Reference in New Issue
Block a user