Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Don't die if a charset param exists along w/ mediatype

`application/json; charset=UTF-8` would fail despite being what the library
implicitely expects. Update checks and documentation to make sure we accepts
requests accordingly and reject them otherwise (even for the spec default
of "; charset=ISO-8859-1"
  • Loading branch information...
commit 980f1e60e79256b41505c276d12b1d80c354e7f4 1 parent 178a010
@yannk authored
Showing with 31 additions and 4 deletions.
  1. +14 −3 handler.go
  2. +17 −1 handler_test.go
View
17 handler.go
@@ -48,10 +48,10 @@ package rest
import (
"fmt"
"log"
+ "mime"
"net/http"
"reflect"
"runtime/debug"
- "strings"
)
// Implement the http.Handler interface and act as a router for the defined Routes.
@@ -83,6 +83,7 @@ type ResourceHandler struct {
// If true, the handler does NOT check the request Content-Type. Otherwise, it
// must be set to 'application/json' if the content is non-null.
+ // Note: If a charset parameter exists, it MUST be UTF-8
EnableRelaxedContentType bool
// Custom logger, defaults to log.New(os.Stderr, "", log.LstdFlags)
@@ -192,12 +193,22 @@ func (self *ResourceHandler) app() http.HandlerFunc {
isIndented,
}
+
// check the Content-Type
+ mediatype, params, _ := mime.ParseMediaType(origRequest.Header.Get("Content-Type"))
+ charset, ok := params["charset"]
+ if !ok {
+ charset = "UTF-8"
+ }
+
if self.EnableRelaxedContentType == false &&
origRequest.ContentLength > 0 && // per net/http doc, means that the length is known and non-null
- strings.ToLower(origRequest.Header.Get("Content-Type")) != "application/json" {
+ !(mediatype == "application/json" && charset == "UTF-8") {
- Error(&writer, "Bad Content-Type, expected 'application/json'", http.StatusUnsupportedMediaType)
+ Error(&writer,
+ "Bad Content-Type or charset, expected 'application/json; charset=UTF-8'",
+ http.StatusUnsupportedMediaType,
+ )
return
}
View
18 handler_test.go
@@ -67,7 +67,23 @@ func TestHandler(t *testing.T) {
recorded = test.RunRequest(t, &handler, request)
recorded.CodeIs(415)
recorded.ContentTypeIsJson()
- recorded.BodyIs(`{"Error":"Bad Content-Type, expected 'application/json'"}`)
+ recorded.BodyIs(`{"Error":"Bad Content-Type or charset, expected 'application/json; charset=UTF-8'"}`)
+
+ // broken Content-Type post resource
+ request = test.MakeSimpleRequest("POST", "http://1.2.3.4/r/123", &map[string]string{"Test": "Test"})
+ request.Header.Set("Content-Type", "application/json; charset=ISO-8859-1")
+ recorded = test.RunRequest(t, &handler, request)
+ recorded.CodeIs(415)
+ recorded.ContentTypeIsJson()
+ recorded.BodyIs(`{"Error":"Bad Content-Type or charset, expected 'application/json; charset=UTF-8'"}`)
+
+ // Content-Type post resource with charset
+ request = test.MakeSimpleRequest("POST", "http://1.2.3.4/r/123", &map[string]string{"Test": "Test"})
+ request.Header.Set("Content-Type", "application/json;charset=UTF-8")
+ recorded = test.RunRequest(t, &handler, request)
+ recorded.CodeIs(200)
+ recorded.ContentTypeIsJson()
+ recorded.BodyIs(`{"Test":"Test"}`)
// auto 405 on undefined route (wrong method)
recorded = test.RunRequest(t, &handler, test.MakeSimpleRequest("DELETE", "http://1.2.3.4/r/123", nil))

1 comment on commit 980f1e6

@ant0ine

Thanks! I think it's nice to support Chrome, even with the strict flag on.

But, I think the super strict version of the content-type is "application/json" without the charset.
At least that's what I understand here: http://www.ietf.org/rfc/rfc4627.txt I may be wrong.

In that case, the error message should suggest "application/json"

Error(&writer, "Bad Content-Type, expected 'application/json'", http.StatusUnsupportedMediaType)

Please sign in to comment.
Something went wrong with that request. Please try again.