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  }