This question has been asked before but that answer applies to python applications. I'd like to know how to fix the issue for go applications.
I've deployed a web service on Google App Engine which is consumed by mobile clients. Using the function below, I send the response either as XML or JSON (as requested by the client)
func (api *API) Respond(w http.ResponseWriter, r *http.Request, body interface{}, status int) {
var contentType string
var content []byte
var err error
if r.Header.Get("Accept") == "application/xml" {
contentType = "application/xml; charset=UTF-8"
content, err = xml.Marshal(body)
} else {
contentType = "application/json; charset=UTF-8"
content, err = json.MarshalIndent(body, "", " ")
}
if err != nil {
panic(err)
}
w.WriteHeader(status)
w.Header().Set("Content-Type", contentType)
w.Write(content)
}
In either case, however, the client device receives a Content-Type of text/html
. How can I fix this? Here's the app.yam file for my application:
application: wks-api
version: 3
runtime: go
api_version: go1
handlers:
- url: /.*
script: api
Look at the documentation in https://golang.org/pkg/net/http/#ResponseWriter , and I quote:
Changing the header after a call to WriteHeader (or Write) has no effect
Now look at your code:
w.WriteHeader(status)
w.Header().Set("Content-Type", contentType)
as you see, you are indeed "Changing the header after a call to WriteHeader" -- hence, it "has no effect".
So, do your "changing the header" before that call instead:
w.Header().Set("Content-Type", contentType)
w.WriteHeader(status)
I don't think this is at all specific to app engine -- it should apply to any use of http
in Go.
See information from http/header:
WriteHeader sends an HTTP response header with status code. If WriteHeader is not called explicitly, the first call to Write will trigger an implicit WriteHeader(http.StatusOK). Thus explicit calls to WriteHeader are mainly used to send error codes.
first try settings the header then send it