fix(lagoon/attach): store non-inline uploads with Content-Disposition attachment (quick-261028-rqe)
- attach.IsInlineContentType: the shared inline raster list (JPEG, PNG, GIF, WebP, AVIF), parameters and case ignored, false for empty or unparsable values - writeBlob stores Content-Disposition: attachment for every other type, so a public bucket or CDN makes the browser download HTML, SVG, PDF or plain text; content_type and thumbnails are unchanged - driver tests on memblob and fileblob, Postgres-backed Store assertion, lagoon README and the storage and attachments pages
This commit is contained in:
44
modules/lagoon/attach/inline.go
Normal file
44
modules/lagoon/attach/inline.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package attach
|
||||
|
||||
import (
|
||||
"mime"
|
||||
"strings"
|
||||
|
||||
"gocloud.dev/blob"
|
||||
)
|
||||
|
||||
// inlineContentTypes are the raster image types a browser may show inline
|
||||
// from an upload.
|
||||
var inlineContentTypes = map[string]bool{
|
||||
"image/avif": true,
|
||||
"image/gif": true,
|
||||
"image/jpeg": true,
|
||||
"image/png": true,
|
||||
"image/webp": true,
|
||||
}
|
||||
|
||||
// attachmentDisposition is the Content-Disposition stored with a non-inline
|
||||
// upload. It is the bare value with no filename parameter: the client's file
|
||||
// name never reaches blob metadata or a response header.
|
||||
const attachmentDisposition = "attachment"
|
||||
|
||||
// IsInlineContentType reports whether contentType, with parameters and case
|
||||
// ignored, is a raster image a browser may show inline from an upload (JPEG,
|
||||
// PNG, GIF, WebP, AVIF). An empty or unparsable value is not. Store stores
|
||||
// every other type, SVG, PDF, HTML and plain text included, with
|
||||
// Content-Disposition: attachment, and the surf uploads route serves it as a
|
||||
// download.
|
||||
func IsInlineContentType(contentType string) bool {
|
||||
mediaType, _, err := mime.ParseMediaType(contentType)
|
||||
return err == nil && inlineContentTypes[strings.ToLower(mediaType)]
|
||||
}
|
||||
|
||||
// uploadWriterOptions are the blob writer options of an upload: the content
|
||||
// type, plus the attachment disposition when the type is not inline.
|
||||
func uploadWriterOptions(contentType string) *blob.WriterOptions {
|
||||
opts := &blob.WriterOptions{ContentType: contentType}
|
||||
if !IsInlineContentType(contentType) {
|
||||
opts.ContentDisposition = attachmentDisposition
|
||||
}
|
||||
return opts
|
||||
}
|
||||
Reference in New Issue
Block a user