package webutility import ( "bytes" "encoding/json" "fmt" "io" "net/http" "net/url" ) // StatusRecorder ... type StatusRecorder struct { writer http.ResponseWriter status int size int } // NewStatusRecorder ... func NewStatusRecorder(w http.ResponseWriter) *StatusRecorder { return &StatusRecorder{ writer: w, status: 0, size: 0, } } // WriteHeader is a wrapper http.ResponseWriter interface func (r *StatusRecorder) WriteHeader(code int) { r.status = code r.writer.WriteHeader(code) } // Write is a wrapper for http.ResponseWriter interface func (r *StatusRecorder) Write(in []byte) (int, error) { r.size = len(in) return r.writer.Write(in) } // Header is a wrapper for http.ResponseWriter interface func (r *StatusRecorder) Header() http.Header { return r.writer.Header() } // Status ... func (r *StatusRecorder) Status() int { return r.status } // Size ... func (r *StatusRecorder) Size() int { return r.size } // NotFoundHandlerFunc writes HTTP error 404 to w. func NotFoundHandlerFunc(w http.ResponseWriter, req *http.Request) { SetDefaultHeaders(w) if req.Method == "OPTIONS" { return } NotFound(w, req, fmt.Sprintf("Resource you requested was not found: %s", req.URL.String())) } // SetContentType ... func SetContentType(w http.ResponseWriter, ctype string) { w.Header().Set("Content-Type", ctype) } // SetResponseStatus ... func SetResponseStatus(w http.ResponseWriter, status int) { w.WriteHeader(status) } // WriteResponse ... func WriteResponse(w http.ResponseWriter, content []byte) { w.Write(content) } // SetDefaultHeaders set's default headers for an HTTP response. func SetDefaultHeaders(w http.ResponseWriter) { w.Header().Set("Access-Control-Allow-Origin", "*") w.Header().Set("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE, OPTIONS") w.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization") SetContentType(w, "application/json; charset=utf-8") } // GetLocale ... func GetLocale(req *http.Request, dflt string) string { loc := req.FormValue("locale") if loc == "" { return dflt } return loc } // Success ... func Success(w http.ResponseWriter, payload interface{}, code int) { w.WriteHeader(code) if payload != nil { json.NewEncoder(w).Encode(payload) } } // OK ... func OK(w http.ResponseWriter, payload interface{}) { Success(w, payload, http.StatusOK) } // Created ... func Created(w http.ResponseWriter, payload interface{}) { Success(w, payload, http.StatusCreated) } type weberror struct { Request string `json:"request"` Error string `json:"error"` } // Error ... func Error(w http.ResponseWriter, r *http.Request, code int, err string) { werr := weberror{Error: err, Request: r.Method + " " + r.RequestURI} w.WriteHeader(code) json.NewEncoder(w).Encode(werr) } // BadRequest ... func BadRequest(w http.ResponseWriter, r *http.Request, err string) { Error(w, r, http.StatusBadRequest, err) } // Unauthorized ... func Unauthorized(w http.ResponseWriter, r *http.Request, err string) { Error(w, r, http.StatusUnauthorized, err) } // Forbidden ... func Forbidden(w http.ResponseWriter, r *http.Request, err string) { Error(w, r, http.StatusForbidden, err) } // NotFound ... func NotFound(w http.ResponseWriter, r *http.Request, err string) { Error(w, r, http.StatusNotFound, err) } // Conflict ... func Conflict(w http.ResponseWriter, r *http.Request, err string) { Error(w, r, http.StatusConflict, err) } // InternalServerError ... func InternalServerError(w http.ResponseWriter, r *http.Request, err string) { Error(w, r, http.StatusInternalServerError, err) } // DecodeJSON decodes JSON data from r to v. // Returns an error if it fails. func DecodeJSON(r io.Reader, v interface{}) error { return json.NewDecoder(r).Decode(v) } func GetJSON(url string, v interface{}, params url.Values, headers http.Header) (status int, err error) { p := params.Encode() if p != "" { url += "?" + p } req, err := http.NewRequest(http.MethodGet, url, nil) if err != nil { return 0, err } if headers != nil { for k, head := range headers { for i, h := range head { if i == 0 { req.Header.Set(k, h) } else { req.Header.Add(k, h) } } } } resp, err := http.DefaultClient.Do(req) if err != nil { return 0, err } status = resp.StatusCode return status, DecodeJSON(resp.Body, v) } func PostJSON(url string, v, r interface{}, params url.Values, headers http.Header) (status int, err error) { buffer := bytes.NewBuffer(make([]byte, 0)) json.NewEncoder(buffer).Encode(v) p := params.Encode() if p != "" { url += "?" + p } req, err := http.NewRequest(http.MethodPost, url, buffer) if err != nil { return 0, err } if headers != nil { for k, head := range headers { for i, h := range head { if i == 0 { req.Header.Set(k, h) } else { req.Header.Add(k, h) } } } } req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { return 0, err } status = resp.StatusCode return status, DecodeJSON(resp.Body, r) }