Skip to content

Commit 1c77825

Browse files
lifegpcwxiaoguang
authored andcommitted
Allow to display embed images/pdfs when SERVE_DIRECT was enabled on MinIO storage (go-gitea#35882)
Releated issue: go-gitea#30487 --------- Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
1 parent db876d8 commit 1c77825

File tree

3 files changed

+31
-5
lines changed

3 files changed

+31
-5
lines changed

modules/storage/azureblob.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,7 @@ func (a *AzureBlobStorage) Delete(path string) error {
250250
func (a *AzureBlobStorage) URL(path, name, _ string, reqParams url.Values) (*url.URL, error) {
251251
blobClient := a.getBlobClient(path)
252252

253+
// TODO: OBJECT-STORAGE-CONTENT-TYPE: "browser inline rendering images/PDF" needs proper Content-Type header from storage
253254
startTime := time.Now()
254255
u, err := blobClient.GetSASURL(sas.BlobPermissions{
255256
Read: true,

modules/storage/minio.go

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -279,20 +279,44 @@ func (m *MinioStorage) Delete(path string) error {
279279
}
280280

281281
// URL gets the redirect URL to a file. The presigned link is valid for 5 minutes.
282-
func (m *MinioStorage) URL(path, name, method string, serveDirectReqParams url.Values) (*url.URL, error) {
282+
func (m *MinioStorage) URL(storePath, name, method string, serveDirectReqParams url.Values) (*url.URL, error) {
283283
// copy serveDirectReqParams
284284
reqParams, err := url.ParseQuery(serveDirectReqParams.Encode())
285285
if err != nil {
286286
return nil, err
287287
}
288-
// TODO it may be good to embed images with 'inline' like ServeData does, but we don't want to have to read the file, do we?
289-
reqParams.Set("response-content-disposition", "attachment; filename=\""+quoteEscaper.Replace(name)+"\"")
288+
289+
// Here we might not know the real filename, and it's quite inefficient to detect the mine type by pre-fetching the object head.
290+
// 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.
291+
// Detect content type by extension name, only support the well-known safe types for inline rendering.
292+
// TODO: OBJECT-STORAGE-CONTENT-TYPE: need a complete solution and refactor for Azure in the future
293+
ext := path.Ext(name)
294+
inlineExtMimeTypes := map[string]string{
295+
".png": "image/png",
296+
".jpg": "image/jpeg",
297+
".jpeg": "image/jpeg",
298+
".gif": "image/gif",
299+
".webp": "image/webp",
300+
".avif": "image/avif",
301+
// 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
302+
// HINT: PDF-RENDER-SANDBOX: PDF won't render in sandboxed context, it seems fine to render it inline
303+
".pdf": "application/pdf",
304+
305+
// TODO: refactor with "modules/public/mime_types.go", for example: "DetectWellKnownSafeInlineMimeType"
306+
}
307+
if mimeType, ok := inlineExtMimeTypes[ext]; ok {
308+
reqParams.Set("response-content-type", mimeType)
309+
reqParams.Set("response-content-disposition", "inline")
310+
} else {
311+
reqParams.Set("response-content-disposition", fmt.Sprintf(`attachment; filename="%s"`, quoteEscaper.Replace(name)))
312+
}
313+
290314
expires := 5 * time.Minute
291315
if method == http.MethodHead {
292-
u, err := m.client.PresignedHeadObject(m.ctx, m.bucket, m.buildMinioPath(path), expires, reqParams)
316+
u, err := m.client.PresignedHeadObject(m.ctx, m.bucket, m.buildMinioPath(storePath), expires, reqParams)
293317
return u, convertMinioErr(err)
294318
}
295-
u, err := m.client.PresignedGetObject(m.ctx, m.bucket, m.buildMinioPath(path), expires, reqParams)
319+
u, err := m.client.PresignedGetObject(m.ctx, m.bucket, m.buildMinioPath(storePath), expires, reqParams)
296320
return u, convertMinioErr(err)
297321
}
298322

routers/web/repo/view.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ func getFileReader(ctx gocontext.Context, repoID int64, blob *git.Blob) (buf []b
9595

9696
meta, err := git_model.GetLFSMetaObjectByOid(ctx, repoID, pointer.Oid)
9797
if err != nil { // fallback to a plain file
98+
fi.lfsMeta = &pointer
9899
log.Warn("Unable to access LFS pointer %s in repo %d: %v", pointer.Oid, repoID, err)
99100
return buf, dataRc, fi, nil
100101
}

0 commit comments

Comments
 (0)