Setting a Header
A common requirement when creating HTTP servers is to be able to set headers on a response. Go offers great support for creating, reading, updating, and deleting headers. In the following example, suppose that the 250server will send some JSON. By setting the Content-Type header, the server can inform the client that JSON data is being sent. Through the ResponseWriter, a handler function can add a header as follows:
w.Header().Set("Content-Type", "application/json; charset=utf-8")
Provided this is before the response is written to the client, the header will be added to the response. In Listing 18.3, the header is added before the JSON content is sent. Note that for simplicity the JSON is set as a string, but normally data would be read from somewhere and then encoded to JSON.
LISTING 18.3 Adding a Header to a Response
1: package main 2: 3: import ( 4: "net/http" 5: ) 6: 7: func helloWorld(w http.ResponseWriter, r *http.Request) { 8: if r.URL.Path != "/" { 9: http.NotFound(w, r) 10: return 11: } 12: w.Header().Set("Content-Type", "application/json; charset=utf-8") 13: w.Write([]byte(`{"hello": "world"}`)) 14: } 15: 16: func main() { 17: http.HandleFunc("/", helloWorld) 18: http.ListenAndServe(":8000", nil) 19: }
Responding with Different Content Types
HTTP servers typically respond to clients with multiple content types. Some content types in common usage include text/plain, text/html, application/json, and application/xml. If a server supports multiple content types, a client may request a content type using an Accept header. This means the same URL can serve a browser with HTML or an API client with JSON. With a small modification, the example that you have been working through can now respond with multiple content types by examining the Accept header sent by the client, as shown in Listing 18.4.
LISTING 18.4 Responding with Different Content Types
1: package main 2: 3: import ( 4: "net/http" 5: ) 6: 7: func helloWorld(w http.ResponseWriter, r *http.Request) { 8: if r.URL.Path != "/" { 9: http.NotFound(w, r) 10: return 11: } 12: switch r.Header.Get("Accept") { 13: case "application/json": 14: w.Header().Set("Content-Type", "application/json; charset=utf-8") 15: w.Write([]byte(`{"message": "Hello World"}`)) 16: case "application/xml": 17: w.Header().Set("Content-Type", "application/xml; charset=utf-8") 18: w.Write([]byte(`<?xml version="1.0" encoding="utf-
8"?><Message>Hello World</Message>`) 19: default: 20: w.Header().Set("Content-Type", "text/plain; charset=utf-8") 21: w.Write([]byte("Hello World\n")) 22: } 23: 24: } 25: 26: func main() { 27: http.HandleFunc("/", helloWorld) 28: http.ListenAndServe(":8000", nil) 29: }
The amendments to the example may be explained as follows:
In the helloWorld function, a switch statement is added that examines the Accept header from the client.
Depending on the contents of the Accept header, a switch statement is used to set the response accordingly.
If no header is found, the server defaults to sending a plain text response.