Documentation
¶
Overview ¶
Package httputil provides small HTTP helpers shared across handlers.
Index ¶
- func ParamID(c echo.Context, name, resource string) (int, error)
- func ServeFile(c echo.Context, path string, notFound error, opts ...ServeOption) error
- func ServeStream(c echo.Context, body io.Reader, size int64, opts ...ServeOption) error
- func SetAttachmentFilename(w http.ResponseWriter, filename string)
- type ServeOption
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ParamID ¶ added in v0.1.0
ParamID parses the numeric path parameter name as a row ID. A value that is not a positive integer names no row, so it returns errcodes.NotFound(resource), the same 404 as a well-formed ID with no row behind it.
func ServeFile ¶ added in v0.1.0
ServeFile serves the file at path through http.ServeContent, which handles Range, If-Range, and conditional GETs. It differs from echo's c.File in two ways. Only a missing file or a directory returns notFound; c.File turns every open failure, including a permission error, into echo's generic 404, and here any other failure is a server fault. And the headers the options set are written only after the open succeeds, so a failure goes out as a plain JSON error rather than one cached for a year, typed as an image, or saved as the book.
A Range header with a unit other than bytes is ignored, as RFC 9110 section 14.2 requires, and the whole file is served with 200. A malformed bytes range, or one that starts past the end, is answered 416 by ServeContent.
func ServeStream ¶ added in v0.2.0
ServeStream sends body, a file still being written, as a whole-file 200 with the headers the options set (WithETag is ignored). size is the file's exact length, sent as Content-Length, or -1 when it is not known yet, in which case the response is chunked. A Range header is ignored, since bytes past what has been written do not exist yet; once the file is complete it is served with ServeFile, which handles Range. Each read is flushed to the client as it arrives, so a slow writer never leaves bytes sitting in a buffer. A nil body, as for HEAD, sends the headers alone.
Call it only once body is ready to read: the headers are sent first, so an error from body can only cut the response short. It does that by closing the connection, since a chunked response that simply ended would look complete to the client.
func SetAttachmentFilename ¶
func SetAttachmentFilename(w http.ResponseWriter, filename string)
SetAttachmentFilename writes a Content-Disposition: attachment header that works across the spectrum of HTTP clients per RFC 6266 / RFC 5987.
For ASCII-only filenames, only the legacy quoted form is emitted. When the filename contains anything outside printable ASCII, both a sanitized ASCII fallback (filename=) and a percent-encoded UTF-8 form (filename*=) are emitted; per RFC 6266 §4.3 modern clients prefer filename* while legacy clients ignore the unknown parameter and use the ASCII fallback.
This matters for OPDS clients like KOReader's "Use server filenames" mode, which parses the header to name the downloaded file on the device.
Types ¶
type ServeOption ¶ added in v0.1.0
type ServeOption func(*serveOptions)
ServeOption sets a header on a file ServeFile serves. Options apply only once the file has opened, so an error response never carries them.
func WithAttachment ¶ added in v0.1.0
func WithAttachment(filename string) ServeOption
WithAttachment sends the file as a download named filename, through SetAttachmentFilename (an escaped ASCII fallback plus filename* for names outside printable ASCII). An empty filename sends no Content-Disposition, which overrides an earlier WithAttachment.
func WithCacheControl ¶ added in v0.1.0
func WithCacheControl(value string) ServeOption
WithCacheControl sets the Cache-Control header.
func WithContentType ¶ added in v0.1.0
func WithContentType(contentType string) ServeOption
WithContentType sets the Content-Type instead of deriving it from the extension. Pass the type for the file type (models.FileTypeMimeType) for a book download, since the host mime table may not know .epub, .cbz, or .m4b. An empty type leaves the extension-based type in place.
func WithETag ¶ added in v0.1.0
func WithETag(etag string) ServeOption
WithETag sets an ETag and makes it the only validator: Last-Modified is omitted and If-Modified-Since ignored, while If-None-Match still answers 304. Use it when the file served at a URL can change without its mtime changing, as for a book cover selected from several files.