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()
|
||||
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()
|
||||
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
|
||||
err := r.ParseForm()
|
||||
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
|
||||
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)
|
||||
if err != nil {
|
||||
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",
|
||||
"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",
|
||||
@ -459,6 +471,44 @@ func TestRC(t *testing.T) {
|
||||
"path": "rc/noop",
|
||||
"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",
|
||||
@ -498,6 +548,19 @@ func TestRC(t *testing.T) {
|
||||
"path": "rc/noop",
|
||||
"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()
|
||||
|
Loading…
Reference in New Issue
Block a user