package response import ( "fmt" "io" "net/http" "github.com/gin-gonic/gin" ) func Write(c *gin.Context, res Response) { w := c.Writer // w.Header() must be set before ResponseWriter.WriteHeader is called // or redirect is attempted hdrs := w.Header() for _, ck := range res.getCookies() { hdrs.Add("Set-Cookie", ck.String()) } if ct, ok := res.getContentType(); ok { hdrs.Add("Content-Type", ct) } if code, to, ok := res.GetRedirect(); ok { http.Redirect(w, c.Request, to, code.Int()) return } // the body is written after the status header, but it's read here // first, because if an error is incurred, an error status header will // need to be written. body, bodySet, err := res.getBody() if err != nil { http.Error( w, fmt.Sprintf("Failed to construct response body: %v", err.Error()), http.StatusInternalServerError, ) return } if status, ok := res.GetStatus(); ok { w.WriteHeader(status) } if bodySet { // will automatically set the status header, // if w.WriteHeader wasn't already called io.Copy(w, body) } } func WriteError(c *gin.Context, err error) { c.String(GetStatusFromError(err), err.Error()) } func GetStatusFromError(err error) int { status := http.StatusInternalServerError if e, ok := GetError(err); ok { if status, ok = e.GetStatus(); !ok { status = http.StatusInternalServerError } } return status }