package ginext import ( "fmt" "github.com/gin-gonic/gin" "gogs.mikescher.com/BlackForestBytes/goext/exerr" json "gogs.mikescher.com/BlackForestBytes/goext/gojson" ) type HTTPResponse interface { Write(g *gin.Context) } type jsonHTTPResponse struct { statusCode int data any } func (j jsonHTTPResponse) Write(g *gin.Context) { g.Render(j.statusCode, json.GoJsonRender{Data: j.data, NilSafeSlices: true, NilSafeMaps: true}) } type emptyHTTPResponse struct { statusCode int } func (j emptyHTTPResponse) Write(g *gin.Context) { g.Status(j.statusCode) } type textHTTPResponse struct { statusCode int data string } func (j textHTTPResponse) Write(g *gin.Context) { g.String(j.statusCode, "%s", j.data) } type dataHTTPResponse struct { statusCode int data []byte contentType string } func (j dataHTTPResponse) Write(g *gin.Context) { g.Data(j.statusCode, j.contentType, j.data) } type fileHTTPResponse struct { mimetype string filepath string filename *string } func (j fileHTTPResponse) Write(g *gin.Context) { g.Header("Content-Type", j.mimetype) // if we don't set it here gin does weird file-sniffing later... if j.filename != nil { g.Header("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", *j.filename)) } g.File(j.filepath) } type redirectHTTPResponse struct { statusCode int url string } func (j redirectHTTPResponse) Write(g *gin.Context) { g.Redirect(j.statusCode, j.url) } type jsonAPIErrResponse struct { err *exerr.ExErr } func (j jsonAPIErrResponse) Write(g *gin.Context) { j.err.Output(g) } func Status(sc int) HTTPResponse { return &emptyHTTPResponse{statusCode: sc} } func JSON(sc int, data any) HTTPResponse { return &jsonHTTPResponse{statusCode: sc, data: data} } func Data(sc int, contentType string, data []byte) HTTPResponse { return &dataHTTPResponse{statusCode: sc, contentType: contentType, data: data} } func Text(sc int, data string) HTTPResponse { return &textHTTPResponse{statusCode: sc, data: data} } func File(mimetype string, filepath string) HTTPResponse { return &fileHTTPResponse{mimetype: mimetype, filepath: filepath} } func Download(mimetype string, filepath string, filename string) HTTPResponse { return &fileHTTPResponse{mimetype: mimetype, filepath: filepath, filename: &filename} } func Redirect(sc int, newURL string) HTTPResponse { return &redirectHTTPResponse{statusCode: sc, url: newURL} } func APIError(g *gin.Context, e error) HTTPResponse { return &jsonAPIErrResponse{ err: exerr.FromError(e), } } func NotImplemented(g *gin.Context) HTTPResponse { return APIError(g, exerr.New(exerr.TypeNotImplemented, "").Build()) }