Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Special HTML chars encoded in JSON respones? #693

Closed
ffigiel opened this issue Aug 31, 2016 · 11 comments
Closed

Special HTML chars encoded in JSON respones? #693

ffigiel opened this issue Aug 31, 2016 · 11 comments

Comments

@ffigiel
Copy link
Contributor

ffigiel commented Aug 31, 2016

I've noticed that, in responses from gin.Context.JSON, special html characters get escaped, while other unicode characters are treated normally.

Here's a handler to reproduce this:

func Hello(c *gin.Context) {
    c.JSON(200, map[string]string{
        "message": "<foo> zażółć gęślą jaźń",
    })
}
$ curl localhost:3000/api/v1/
{"message":"\u003cfoo\u003e zażółć gęślą jaźń"}
@ffigiel ffigiel changed the title pecial chars encoding in JSON respones? Special HTML chars encoded in JSON respones? Aug 31, 2016
@Raphael2048
Copy link

It's just because the curl treat the response as a html,the response is actually right in fact.

@ffigiel
Copy link
Contributor Author

ffigiel commented Aug 31, 2016

hmm I don't think so. Python requests library shows escaped characters in the response as well.

In [2]: r = requests.get('http://localhost:3000/api/v1/')

In [3]: r.content.decode('utf-8')
Out[4]: u'{"message":"\\u003cfoo\\u003e za\u017c\xf3\u0142\u0107 g\u0119\u015bl\u0105 ja\u017a\u0144"}\n'

In [4]: print r.content.decode('utf-8')
{"message":"\u003cfoo\u003e zażółć gęślą jaźń"}

@stxml
Copy link

stxml commented Aug 31, 2016

That's normal. Check json.Marshal(). You can use your own Encoder and SetEscapeHTML(false)

@ffigiel
Copy link
Contributor Author

ffigiel commented Aug 31, 2016

I see, thanks @stxml! Looks like this is the reason:

func (*Encoder) SetEscapeHTML
SetEscapeHTML specifies whether problematic HTML characters should be escaped inside JSON quoted strings. The default behavior is to escape &, <, and > to \u0026, \u003c, and \u003e to avoid certain safety problems that can arise when embedding JSON in HTML.

How can I disable this behavior in my snippet?

@stxml
Copy link

stxml commented Aug 31, 2016

A. make a PR that lets you set this option in gin, or
B. use this code

// copied from render.go
func writeContentType(w http.ResponseWriter, value []string) {
    header := w.Header()
    if val := header["Content-Type"]; len(val) == 0 {
        header["Content-Type"] = value
    }
}

func JSONgoesToHTML(c *gin.Context, code int, obj interface{}) {
    c.Status(code)
    writeContentType(c.Writer, []string{"application/json; charset=utf-8"})
    enc := json.NewEncoder(c.Writer)
    enc.SetEscapeHTML(false) // this is missing in gin
    if err := enc.Encode(obj); err != nil {
        panic(err)
    }
}

@ffigiel
Copy link
Contributor Author

ffigiel commented Aug 31, 2016

I'd love to submit a PR since I'm new to Go! ✨ Would it make sense implement this as an option to engine config? Which file should I look at, apart from render/json.go?

@stxml
Copy link

stxml commented Aug 31, 2016

I don't think it should be an engine option, since rendering is more dynamic and the engine shouldn't care if you write JSON, XML, etc.

Maybe add a new type in json.go:
NoEscapeJSON struct {
Data interface{}
}

Implement the Render() interface and add a convenience function to context, like c.XML(). Not like c.JSON(), because that doesn't even use Render

@ffigiel
Copy link
Contributor Author

ffigiel commented Aug 31, 2016

I see that SetEscapeHTML has been added just recently to 1.7. How can I handle that?

@ffigiel
Copy link
Contributor Author

ffigiel commented Aug 31, 2016

also I see that render/render_test.go tests aren't being run! Oops

@stxml
Copy link

stxml commented Aug 31, 2016

Don't really know how to handle the 1.7 dependency. Go should really have some Availability documentation.

appleboy pushed a commit that referenced this issue Aug 20, 2018
@silveirasc
Copy link

On the return I used c.String (200, string (json))

my json rode with marshal:

json, _: = json.Marshal (customer)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants