package ginext import ( "github.com/gin-gonic/gin" "gogs.mikescher.com/BlackForestBytes/goext/exerr" "gogs.mikescher.com/BlackForestBytes/goext/langext" "io" "net/http" "time" ) type seekableResponse struct { data io.ReadSeeker contentType string filename string headers []headerval cookies []cookieval } func (j seekableResponse) Write(g *gin.Context) { g.Header("Content-Type", j.contentType) // if we don't set it here http.ServeContent does weird sniffing later... for _, v := range j.headers { g.Header(v.Key, v.Val) } for _, v := range j.cookies { g.SetCookie(v.name, v.value, v.maxAge, v.path, v.domain, v.secure, v.httpOnly) } http.ServeContent(g.Writer, g.Request, j.filename, time.Unix(0, 0), j.data) if clsr, ok := j.data.(io.ReadSeekCloser); ok { err := clsr.Close() if err != nil { exerr.Wrap(err, "failed to close io.ReadSeerkClose in ginext.Seekable").Str("filename", j.filename).Print() } } } func (j seekableResponse) WithHeader(k string, v string) HTTPResponse { j.headers = append(j.headers, headerval{k, v}) return j } func (j seekableResponse) WithCookie(name string, value string, maxAge int, path string, domain string, secure bool, httpOnly bool) HTTPResponse { j.cookies = append(j.cookies, cookieval{name, value, maxAge, path, domain, secure, httpOnly}) return j } func (j seekableResponse) IsSuccess() bool { return true } func (j seekableResponse) Statuscode() int { return 200 } func (j seekableResponse) BodyString(*gin.Context) *string { return langext.Ptr("(seekable)") } func (j seekableResponse) ContentType() string { return j.contentType } func (j seekableResponse) Headers() []string { return langext.ArrMap(j.headers, func(v headerval) string { return v.Key + "=" + v.Val }) } func Seekable(filename string, contentType string, data io.ReadSeeker) HTTPResponse { return &seekableResponse{filename: filename, contentType: contentType, data: data} }