github.com/grafviktor/keep-my-secret@v0.9.10-0.20230908165355-19f35cce90e5/internal/api/utils/http.go (about)

     1  package utils
     2  
     3  import (
     4  	"encoding/json"
     5  	"errors"
     6  	"io"
     7  	"net/http"
     8  )
     9  
    10  // JSONResponse is a convenience structure to marshal generic JSON responses and requests
    11  type JSONResponse struct {
    12  	Error   bool        `json:"error"`
    13  	Message string      `json:"message"`
    14  	Data    interface{} `json:"data,omitempty"`
    15  }
    16  
    17  // WriteJSON writes a JSON response to the client
    18  // w - http.ResponseWriter
    19  // status - http status code
    20  // data - data to be marshaled into JSON
    21  // headers - optional headers to be written to the response
    22  func WriteJSON(w http.ResponseWriter, status int, data interface{}, headers ...http.Header) error {
    23  	out, err := json.Marshal(data)
    24  	if err != nil {
    25  		return err
    26  	}
    27  
    28  	if len(headers) > 0 {
    29  		for key, value := range headers[0] {
    30  			w.Header()[key] = value
    31  		}
    32  	}
    33  
    34  	w.Header().Set("Content-Type", "application/json")
    35  	w.WriteHeader(status)
    36  	_, err = w.Write(out)
    37  	if err != nil {
    38  		return err
    39  	}
    40  
    41  	return nil
    42  }
    43  
    44  // ReadJSON writes a response to the client
    45  // w - http.ResponseWriter
    46  // r - http.Request
    47  // data - data to be marshaled into JSON
    48  func ReadJSON(w http.ResponseWriter, r *http.Request, data interface{}) error {
    49  	maxBytes := 1024 * 1024 // one megabyte
    50  	r.Body = http.MaxBytesReader(w, r.Body, int64(maxBytes))
    51  
    52  	dec := json.NewDecoder(r.Body)
    53  	dec.DisallowUnknownFields()
    54  
    55  	err := dec.Decode(data)
    56  	if err != nil {
    57  		return err
    58  	}
    59  
    60  	err = dec.Decode(&struct{}{})
    61  	if !errors.Is(err, io.EOF) {
    62  		return errors.New("body must only contain a single JSON value")
    63  	}
    64  
    65  	return nil
    66  }