github.com/prysmaticlabs/prysm@v1.4.4/shared/prometheus/content_negotiation.go (about) 1 package prometheus 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "fmt" 7 "net/http" 8 9 "github.com/golang/gddo/httputil" 10 ) 11 12 const ( 13 contentTypePlainText = "text/plain" 14 contentTypeJSON = "application/json" 15 ) 16 17 // generatedResponse is a container for response output. 18 type generatedResponse struct { 19 // Err is protocol error, if any. 20 Err string `json:"error"` 21 22 // Data is response output, if any. 23 Data interface{} `json:"data"` 24 } 25 26 // negotiateContentType parses "Accept:" header and returns preferred content type string. 27 func negotiateContentType(r *http.Request) string { 28 contentTypes := []string{ 29 contentTypePlainText, 30 contentTypeJSON, 31 } 32 return httputil.NegotiateContentType(r, contentTypes, contentTypePlainText) 33 } 34 35 // writeResponse is content-type aware response writer. 36 func writeResponse(w http.ResponseWriter, r *http.Request, response generatedResponse) error { 37 switch negotiateContentType(r) { 38 case contentTypePlainText: 39 buf, ok := response.Data.(bytes.Buffer) 40 if !ok { 41 return fmt.Errorf("unexpected data: %v", response.Data) 42 } 43 if _, err := w.Write(buf.Bytes()); err != nil { 44 return fmt.Errorf("could not write response body: %w", err) 45 } 46 case contentTypeJSON: 47 w.Header().Set("Content-Type", contentTypeJSON) 48 if err := json.NewEncoder(w).Encode(response); err != nil { 49 return err 50 } 51 } 52 return nil 53 }