Files
inventory-plus-plus/internal/server/response/write.go
T

128 lines
2.1 KiB
Go

package response
import (
"fmt"
"io"
"net/http"
"github.com/gin-gonic/gin"
)
func HandleResponses(c *gin.Context) {
c.Next()
if len(c.Errors) > 0 || c.Writer.Written() {
return
}
v, ok := c.Get(responseKey{})
if !ok {
return
}
res, ok := v.(Response)
if !ok {
return
}
writeResponse(c, res)
}
func HandleErrors(c *gin.Context) {
c.Next()
if len(c.Errors) == 0 || c.Writer.Written() {
return
}
var (
err ErrorResponse
ok bool
)
for _, e := range c.Errors {
if err, ok = GetError(e); ok {
break
}
}
if !ok {
return
}
status, ok := err.GetStatus()
if !ok {
status = http.StatusInternalServerError
}
if h, ok := err.GetHTML(); ok {
c.Status(status)
c.Header("Content-Type", "text/html")
c.Writer.Write(h)
return
}
msg, ok := err.GetMsg()
if !ok {
msg = err.Error()
}
c.String(status, msg)
}
func writeResponse(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 _, hdr := range res.getHeaders() {
hdrs.Add(hdr[0], hdr[1])
}
for _, ck := range res.getCookies() {
hdrs.Add("Set-Cookie", ck.String())
}
if ct, ok := res.getContentType(); ok {
hdrs.Set("Content-Type", ct)
}
if code, to, ok := res.GetRedirect(); ok {
c.Redirect(code.Int(), to)
c.Abort()
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 GetStatusFromError(err error) int {
status := http.StatusInternalServerError
if e, ok := GetError(err); ok {
if status, ok = e.GetStatus(); !ok {
status = http.StatusInternalServerError
}
}
return status
}