Refactor storage content-type handling of ServeDirectURL (#36804)

* replace raw url.Values by *storage.ServeDirectOptions
* implement content-type in azblob
* implement content-disposition in azblob
* add tests for content types in response
* http.MethodPut for azure now allows implementing servedirect uploads

---------

Signed-off-by: ChristopherHX <christopher.homberger@web.de>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
ChristopherHX
2026-03-22 05:26:13 +01:00
committed by GitHub
parent c8545033cc
commit 0ab612f5ab
24 changed files with 234 additions and 81 deletions
+9 -29
View File
@@ -278,37 +278,16 @@ func (m *MinioStorage) Delete(path string) error {
return convertMinioErr(err)
}
// URL gets the redirect URL to a file. The presigned link is valid for 5 minutes.
func (m *MinioStorage) URL(storePath, name, method string, serveDirectReqParams url.Values) (*url.URL, error) {
// copy serveDirectReqParams
reqParams, err := url.ParseQuery(serveDirectReqParams.Encode())
if err != nil {
return nil, err
}
func (m *MinioStorage) ServeDirectURL(storePath, name, method string, opt *ServeDirectOptions) (*url.URL, error) {
reqParams := url.Values{}
// Here we might not know the real filename, and it's quite inefficient to detect the mine type by pre-fetching the object head.
// So we just do a quick detection by extension name, at least if works for the "View Raw File" for an LFS file on the Web UI.
// Detect content type by extension name, only support the well-known safe types for inline rendering.
// TODO: OBJECT-STORAGE-CONTENT-TYPE: need a complete solution and refactor for Azure in the future
ext := path.Ext(name)
inlineExtMimeTypes := map[string]string{
".png": "image/png",
".jpg": "image/jpeg",
".jpeg": "image/jpeg",
".gif": "image/gif",
".webp": "image/webp",
".avif": "image/avif",
// ATTENTION! Don't support unsafe types like HTML/SVG due to security concerns: they can contain JS code, and maybe they need proper Content-Security-Policy
// HINT: PDF-RENDER-SANDBOX: PDF won't render in sandboxed context, it seems fine to render it inline
".pdf": "application/pdf",
// TODO: refactor with "modules/public/mime_types.go", for example: "DetectWellKnownSafeInlineMimeType"
param := prepareServeDirectOptions(opt, name)
// minio does not ignore empty params
if param.ContentType != "" {
reqParams.Set("response-content-type", param.ContentType)
}
if mimeType, ok := inlineExtMimeTypes[ext]; ok {
reqParams.Set("response-content-type", mimeType)
reqParams.Set("response-content-disposition", "inline")
} else {
reqParams.Set("response-content-disposition", fmt.Sprintf(`attachment; filename="%s"`, quoteEscaper.Replace(name)))
if param.ContentDisposition != "" {
reqParams.Set("response-content-disposition", param.ContentDisposition)
}
expires := 5 * time.Minute
@@ -323,6 +302,7 @@ func (m *MinioStorage) URL(storePath, name, method string, serveDirectReqParams
// IterateObjects iterates across the objects in the miniostorage
func (m *MinioStorage) IterateObjects(dirName string, fn func(path string, obj Object) error) error {
opts := minio.GetObjectOptions{}
// FIXME: this loop is not right and causes resource leaking, see the comment of ListObjects
for mObjInfo := range m.client.ListObjects(m.ctx, m.bucket, minio.ListObjectsOptions{
Prefix: m.buildMinioDirPrefix(dirName),
Recursive: true,