Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion modules/actions/artifacts.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func IsArtifactV4(art *actions_model.ActionArtifact) bool {

func DownloadArtifactV4ServeDirectOnly(ctx *context.Base, art *actions_model.ActionArtifact) (bool, error) {
if setting.Actions.ArtifactStorage.ServeDirect() {
u, err := storage.ActionsArtifacts.URL(art.StoragePath, art.ArtifactPath, nil)
u, err := storage.ActionsArtifacts.URL(art.StoragePath, art.ArtifactPath, ctx.Req.Method, nil)
if u != nil && err == nil {
ctx.Redirect(u.String(), http.StatusFound)
return true, nil
Expand Down
4 changes: 2 additions & 2 deletions modules/packages/content_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ func (s *ContentStore) ShouldServeDirect() bool {
return setting.Packages.Storage.ServeDirect()
}

func (s *ContentStore) GetServeDirectURL(key BlobHash256Key, filename string, reqParams url.Values) (*url.URL, error) {
return s.store.URL(KeyToRelativePath(key), filename, reqParams)
func (s *ContentStore) GetServeDirectURL(key BlobHash256Key, filename, method string, reqParams url.Values) (*url.URL, error) {
return s.store.URL(KeyToRelativePath(key), filename, method, reqParams)
}

// FIXME: Workaround to be removed in v1.20
Expand Down
2 changes: 1 addition & 1 deletion modules/storage/azureblob.go
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ func (a *AzureBlobStorage) Delete(path string) error {
}

// URL gets the redirect URL to a file. The presigned link is valid for 5 minutes.
func (a *AzureBlobStorage) URL(path, name string, reqParams url.Values) (*url.URL, error) {
func (a *AzureBlobStorage) URL(path, name, _ string, reqParams url.Values) (*url.URL, error) {
blobClient := a.getBlobClient(path)

startTime := time.Now()
Expand Down
2 changes: 1 addition & 1 deletion modules/storage/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func (s discardStorage) Delete(_ string) error {
return fmt.Errorf("%s", s)
}

func (s discardStorage) URL(_, _ string, _ url.Values) (*url.URL, error) {
func (s discardStorage) URL(_, _, _ string, _ url.Values) (*url.URL, error) {
return nil, fmt.Errorf("%s", s)
}

Expand Down
2 changes: 1 addition & 1 deletion modules/storage/helper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func Test_discardStorage(t *testing.T) {
assert.Error(t, err, string(tt))
}
{
got, err := tt.URL("path", "name", nil)
got, err := tt.URL("path", "name", "GET", nil)
assert.Nil(t, got)
assert.Errorf(t, err, string(tt))
}
Expand Down
2 changes: 1 addition & 1 deletion modules/storage/local.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ func (l *LocalStorage) Delete(path string) error {
}

// URL gets the redirect URL to a file
func (l *LocalStorage) URL(path, name string, reqParams url.Values) (*url.URL, error) {
func (l *LocalStorage) URL(path, name, _ string, reqParams url.Values) (*url.URL, error) {
return nil, ErrURLNotSupported
}

Expand Down
9 changes: 7 additions & 2 deletions modules/storage/minio.go
Original file line number Diff line number Diff line change
Expand Up @@ -279,15 +279,20 @@ func (m *MinioStorage) Delete(path string) error {
}

// URL gets the redirect URL to a file. The presigned link is valid for 5 minutes.
func (m *MinioStorage) URL(path, name string, serveDirectReqParams url.Values) (*url.URL, error) {
func (m *MinioStorage) URL(path, name, method string, serveDirectReqParams url.Values) (*url.URL, error) {
// copy serveDirectReqParams
reqParams, err := url.ParseQuery(serveDirectReqParams.Encode())
if err != nil {
return nil, err
}
// 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?
reqParams.Set("response-content-disposition", "attachment; filename=\""+quoteEscaper.Replace(name)+"\"")
u, err := m.client.PresignedGetObject(m.ctx, m.bucket, m.buildMinioPath(path), 5*time.Minute, reqParams)
expires := 5 * time.Minute
if method == http.MethodHead {
u, err := m.client.PresignedHeadObject(m.ctx, m.bucket, m.buildMinioPath(path), expires, reqParams)
return u, convertMinioErr(err)
}
u, err := m.client.PresignedGetObject(m.ctx, m.bucket, m.buildMinioPath(path), expires, reqParams)
return u, convertMinioErr(err)
}

Expand Down
2 changes: 1 addition & 1 deletion modules/storage/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ type ObjectStorage interface {
Save(path string, r io.Reader, size int64) (int64, error)
Stat(path string) (os.FileInfo, error)
Delete(path string) error
URL(path, name string, reqParams url.Values) (*url.URL, error)
URL(path, name, method string, reqParams url.Values) (*url.URL, error)
IterateObjects(path string, iterator func(path string, obj Object) error) error
}

Expand Down
2 changes: 1 addition & 1 deletion routers/api/actions/artifacts.go
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,7 @@ func (ar artifactRoutes) getDownloadArtifactURL(ctx *ArtifactContext) {
for _, artifact := range artifacts {
var downloadURL string
if setting.Actions.ArtifactStorage.ServeDirect() {
u, err := ar.fs.URL(artifact.StoragePath, artifact.ArtifactName, nil)
u, err := ar.fs.URL(artifact.StoragePath, artifact.ArtifactName, ctx.Req.Method, nil)
if err != nil && !errors.Is(err, storage.ErrURLNotSupported) {
log.Error("Error getting serve direct url: %v", err)
}
Expand Down
2 changes: 1 addition & 1 deletion routers/api/actions/artifactsv4.go
Original file line number Diff line number Diff line change
Expand Up @@ -517,7 +517,7 @@ func (r *artifactV4Routes) getSignedArtifactURL(ctx *ArtifactContext) {
respData := GetSignedArtifactURLResponse{}

if setting.Actions.ArtifactStorage.ServeDirect() {
u, err := storage.ActionsArtifacts.URL(artifact.StoragePath, artifact.ArtifactPath, nil)
u, err := storage.ActionsArtifacts.URL(artifact.StoragePath, artifact.ArtifactPath, ctx.Req.Method, nil)
if u != nil && err == nil {
respData.SignedUrl = u.String()
}
Expand Down
3 changes: 2 additions & 1 deletion routers/api/packages/alpine/alpine.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ func GetRepositoryFile(ctx *context.Context) {
Filename: alpine_service.IndexArchiveFilename,
CompositeKey: fmt.Sprintf("%s|%s|%s", ctx.PathParam("branch"), ctx.PathParam("repository"), ctx.PathParam("architecture")),
},
ctx.Req.Method,
)
if err != nil {
if errors.Is(err, util.ErrNotExist) {
Expand Down Expand Up @@ -216,7 +217,7 @@ func DownloadPackageFile(ctx *context.Context) {
}
}

s, u, pf, err := packages_service.OpenFileForDownload(ctx, pfs[0])
s, u, pf, err := packages_service.OpenFileForDownload(ctx, pfs[0], ctx.Req.Method)
if err != nil {
if errors.Is(err, util.ErrNotExist) {
apiError(ctx, http.StatusNotFound, err)
Expand Down
2 changes: 1 addition & 1 deletion routers/api/packages/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ func CommonRoutes() *web.Router {
r.Group("/{packagename}/{packageversion}", func() {
r.Delete("", reqPackageAccess(perm.AccessModeWrite), generic.DeletePackage)
r.Group("/{filename}", func() {
r.Get("", generic.DownloadPackageFile)
r.Methods("HEAD,GET", "", generic.DownloadPackageFile)
r.Group("", func() {
r.Put("", generic.UploadPackage)
r.Delete("", generic.DeletePackageFile)
Expand Down
2 changes: 1 addition & 1 deletion routers/api/packages/arch/arch.go
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ func GetPackageOrRepositoryFile(ctx *context.Context) {
return
}

s, u, pf, err := packages_service.OpenFileForDownload(ctx, pfs[0])
s, u, pf, err := packages_service.OpenFileForDownload(ctx, pfs[0], ctx.Req.Method)
if err != nil {
if errors.Is(err, util.ErrNotExist) {
apiError(ctx, http.StatusNotFound, err)
Expand Down
1 change: 1 addition & 0 deletions routers/api/packages/cargo/cargo.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ func DownloadPackageFile(ctx *context.Context) {
&packages_service.PackageFileInfo{
Filename: strings.ToLower(fmt.Sprintf("%s-%s.crate", ctx.PathParam("package"), ctx.PathParam("version"))),
},
ctx.Req.Method,
)
if err != nil {
if errors.Is(err, packages_model.ErrPackageNotExist) || errors.Is(err, packages_model.ErrPackageFileNotExist) {
Expand Down
2 changes: 1 addition & 1 deletion routers/api/packages/chef/chef.go
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ func DownloadPackage(ctx *context.Context) {

pf := pd.Files[0].File

s, u, _, err := packages_service.OpenFileForDownload(ctx, pf)
s, u, _, err := packages_service.OpenFileForDownload(ctx, pf, ctx.Req.Method)
if err != nil {
apiError(ctx, http.StatusInternalServerError, err)
return
Expand Down
1 change: 1 addition & 0 deletions routers/api/packages/composer/composer.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ func DownloadPackageFile(ctx *context.Context) {
&packages_service.PackageFileInfo{
Filename: ctx.PathParam("filename"),
},
ctx.Req.Method,
)
if err != nil {
if errors.Is(err, packages_model.ErrPackageNotExist) || errors.Is(err, packages_model.ErrPackageFileNotExist) {
Expand Down
1 change: 1 addition & 0 deletions routers/api/packages/conan/conan.go
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,7 @@ func downloadFile(ctx *context.Context, fileFilter container.Set[string], fileKe
Filename: filename,
CompositeKey: fileKey,
},
ctx.Req.Method,
)
if err != nil {
if errors.Is(err, packages_model.ErrPackageNotExist) || errors.Is(err, packages_model.ErrPackageFileNotExist) {
Expand Down
2 changes: 1 addition & 1 deletion routers/api/packages/conda/conda.go
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ func DownloadPackageFile(ctx *context.Context) {

pf := pfs[0]

s, u, _, err := packages_service.OpenFileForDownload(ctx, pf)
s, u, _, err := packages_service.OpenFileForDownload(ctx, pf, ctx.Req.Method)
if err != nil {
apiError(ctx, http.StatusInternalServerError, err)
return
Expand Down
2 changes: 1 addition & 1 deletion routers/api/packages/container/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -710,7 +710,7 @@ func DeleteManifest(ctx *context.Context) {
func serveBlob(ctx *context.Context, pfd *packages_model.PackageFileDescriptor) {
serveDirectReqParams := make(url.Values)
serveDirectReqParams.Set("response-content-type", pfd.Properties.GetByName(container_module.PropertyMediaType))
s, u, _, err := packages_service.OpenBlobForDownload(ctx, pfd.File, pfd.Blob, serveDirectReqParams)
s, u, _, err := packages_service.OpenBlobForDownload(ctx, pfd.File, pfd.Blob, ctx.Req.Method, serveDirectReqParams)
if err != nil {
apiError(ctx, http.StatusInternalServerError, err)
return
Expand Down
2 changes: 1 addition & 1 deletion routers/api/packages/cran/cran.go
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ func downloadPackageFile(ctx *context.Context, opts *cran_model.SearchOptions) {
return
}

s, u, _, err := packages_service.OpenFileForDownload(ctx, pf)
s, u, _, err := packages_service.OpenFileForDownload(ctx, pf, ctx.Req.Method)
if err != nil {
if errors.Is(err, util.ErrNotExist) {
apiError(ctx, http.StatusNotFound, err)
Expand Down
4 changes: 3 additions & 1 deletion routers/api/packages/debian/debian.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ func GetRepositoryFile(ctx *context.Context) {
Filename: ctx.PathParam("filename"),
CompositeKey: key,
},
ctx.Req.Method,
)
if err != nil {
if errors.Is(err, packages_model.ErrPackageNotExist) || errors.Is(err, packages_model.ErrPackageFileNotExist) {
Expand Down Expand Up @@ -106,7 +107,7 @@ func GetRepositoryFileByHash(ctx *context.Context) {
return
}

s, u, pf, err := packages_service.OpenFileForDownload(ctx, pfs[0])
s, u, pf, err := packages_service.OpenFileForDownload(ctx, pfs[0], ctx.Req.Method)
if err != nil {
if errors.Is(err, util.ErrNotExist) {
apiError(ctx, http.StatusNotFound, err)
Expand Down Expand Up @@ -222,6 +223,7 @@ func DownloadPackageFile(ctx *context.Context) {
Filename: fmt.Sprintf("%s_%s_%s.deb", name, version, ctx.PathParam("architecture")),
CompositeKey: fmt.Sprintf("%s|%s", ctx.PathParam("distribution"), ctx.PathParam("component")),
},
ctx.Req.Method,
)
if err != nil {
if errors.Is(err, util.ErrNotExist) {
Expand Down
1 change: 1 addition & 0 deletions routers/api/packages/generic/generic.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ func DownloadPackageFile(ctx *context.Context) {
&packages_service.PackageFileInfo{
Filename: ctx.PathParam("filename"),
},
ctx.Req.Method,
)
if err != nil {
if errors.Is(err, packages_model.ErrPackageNotExist) || errors.Is(err, packages_model.ErrPackageFileNotExist) {
Expand Down
2 changes: 1 addition & 1 deletion routers/api/packages/goproxy/goproxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ func DownloadPackageFile(ctx *context.Context) {
return
}

s, u, _, err := packages_service.OpenFileForDownload(ctx, pfs[0])
s, u, _, err := packages_service.OpenFileForDownload(ctx, pfs[0], ctx.Req.Method)
if err != nil {
if errors.Is(err, util.ErrNotExist) {
apiError(ctx, http.StatusNotFound, err)
Expand Down
1 change: 1 addition & 0 deletions routers/api/packages/helm/helm.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ func DownloadPackageFile(ctx *context.Context) {
&packages_service.PackageFileInfo{
Filename: filename,
},
ctx.Req.Method,
)
if err != nil {
if errors.Is(err, packages_model.ErrPackageFileNotExist) {
Expand Down
2 changes: 1 addition & 1 deletion routers/api/packages/maven/maven.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ func servePackageFile(ctx *context.Context, params parameters, serveContent bool
return
}

s, u, _, err := packages_service.OpenBlobForDownload(ctx, pf, pb, nil)
s, u, _, err := packages_service.OpenBlobForDownload(ctx, pf, pb, ctx.Req.Method, nil)
if err != nil {
apiError(ctx, http.StatusInternalServerError, err)
return
Expand Down
2 changes: 2 additions & 0 deletions routers/api/packages/npm/npm.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ func DownloadPackageFile(ctx *context.Context) {
&packages_service.PackageFileInfo{
Filename: filename,
},
ctx.Req.Method,
)
if err != nil {
if errors.Is(err, packages_model.ErrPackageNotExist) || errors.Is(err, packages_model.ErrPackageFileNotExist) {
Expand Down Expand Up @@ -138,6 +139,7 @@ func DownloadPackageFileByName(ctx *context.Context) {
&packages_service.PackageFileInfo{
Filename: filename,
},
ctx.Req.Method,
)
if err != nil {
if errors.Is(err, packages_model.ErrPackageFileNotExist) {
Expand Down
3 changes: 2 additions & 1 deletion routers/api/packages/nuget/nuget.go
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,7 @@ func DownloadPackageFile(ctx *context.Context) {
&packages_service.PackageFileInfo{
Filename: filename,
},
ctx.Req.Method,
)
if err != nil {
if errors.Is(err, packages_model.ErrPackageNotExist) || errors.Is(err, packages_model.ErrPackageFileNotExist) {
Expand Down Expand Up @@ -669,7 +670,7 @@ func DownloadSymbolFile(ctx *context.Context) {
return
}

s, u, pf, err := packages_service.OpenFileForDownload(ctx, pfs[0])
s, u, pf, err := packages_service.OpenFileForDownload(ctx, pfs[0], ctx.Req.Method)
if err != nil {
if errors.Is(err, packages_model.ErrPackageNotExist) || errors.Is(err, packages_model.ErrPackageFileNotExist) {
apiError(ctx, http.StatusNotFound, err)
Expand Down
2 changes: 1 addition & 1 deletion routers/api/packages/pub/pub.go
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ func DownloadPackageFile(ctx *context.Context) {

pf := pd.Files[0].File

s, u, _, err := packages_service.OpenFileForDownload(ctx, pf)
s, u, _, err := packages_service.OpenFileForDownload(ctx, pf, ctx.Req.Method)
if err != nil {
apiError(ctx, http.StatusInternalServerError, err)
return
Expand Down
1 change: 1 addition & 0 deletions routers/api/packages/pypi/pypi.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ func DownloadPackageFile(ctx *context.Context) {
&packages_service.PackageFileInfo{
Filename: filename,
},
ctx.Req.Method,
)
if err != nil {
if errors.Is(err, packages_model.ErrPackageNotExist) || errors.Is(err, packages_model.ErrPackageFileNotExist) {
Expand Down
2 changes: 2 additions & 0 deletions routers/api/packages/rpm/rpm.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ func GetRepositoryFile(ctx *context.Context) {
Filename: ctx.PathParam("filename"),
CompositeKey: ctx.PathParam("group"),
},
ctx.Req.Method,
)
if err != nil {
if errors.Is(err, util.ErrNotExist) {
Expand Down Expand Up @@ -232,6 +233,7 @@ func DownloadPackageFile(ctx *context.Context) {
Filename: fmt.Sprintf("%s-%s.%s.rpm", name, version, ctx.PathParam("architecture")),
CompositeKey: ctx.PathParam("group"),
},
ctx.Req.Method,
)
if err != nil {
if errors.Is(err, util.ErrNotExist) {
Expand Down
1 change: 1 addition & 0 deletions routers/api/packages/rubygems/rubygems.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ func DownloadPackageFile(ctx *context.Context) {
&packages_service.PackageFileInfo{
Filename: filename,
},
ctx.Req.Method,
)
if err != nil {
if errors.Is(err, packages_model.ErrPackageFileNotExist) {
Expand Down
2 changes: 1 addition & 1 deletion routers/api/packages/swift/swift.go
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,7 @@ func DownloadPackageFile(ctx *context.Context) {

pf := pd.Files[0].File

s, u, _, err := packages_service.OpenFileForDownload(ctx, pf)
s, u, _, err := packages_service.OpenFileForDownload(ctx, pf, ctx.Req.Method)
if err != nil {
apiError(ctx, http.StatusInternalServerError, err)
return
Expand Down
1 change: 1 addition & 0 deletions routers/api/packages/vagrant/vagrant.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ func DownloadPackageFile(ctx *context.Context) {
&packages_service.PackageFileInfo{
Filename: ctx.PathParam("provider"),
},
ctx.Req.Method,
)
if err != nil {
if errors.Is(err, packages_model.ErrPackageNotExist) || errors.Is(err, packages_model.ErrPackageFileNotExist) {
Expand Down
4 changes: 2 additions & 2 deletions routers/api/v1/repo/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ func GetRawFileOrLFS(ctx *context.APIContext) {

if setting.LFS.Storage.ServeDirect() {
// If we have a signed url (S3, object storage), redirect to this directly.
u, err := storage.LFS.URL(pointer.RelativePath(), blob.Name(), nil)
u, err := storage.LFS.URL(pointer.RelativePath(), blob.Name(), ctx.Req.Method, nil)
if u != nil && err == nil {
ctx.Redirect(u.String())
return
Expand Down Expand Up @@ -331,7 +331,7 @@ func download(ctx *context.APIContext, archiveName string, archiver *repo_model.
rPath := archiver.RelativePath()
if setting.RepoArchive.Storage.ServeDirect() {
// If we have a signed url (S3, object storage), redirect to this directly.
u, err := storage.RepoArchives.URL(rPath, downloadName, nil)
u, err := storage.RepoArchives.URL(rPath, downloadName, ctx.Req.Method, nil)
if u != nil && err == nil {
ctx.Redirect(u.String())
return
Expand Down
2 changes: 1 addition & 1 deletion routers/web/base.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func avatarStorageHandler(storageSetting *setting.Storage, prefix string, objSto
rPath := strings.TrimPrefix(req.URL.Path, "/"+prefix+"/")
rPath = util.PathJoinRelX(rPath)

u, err := objStore.URL(rPath, path.Base(rPath), nil)
u, err := objStore.URL(rPath, path.Base(rPath), req.Method, nil)
if err != nil {
if os.IsNotExist(err) || errors.Is(err, os.ErrNotExist) {
log.Warn("Unable to find %s %s", prefix, rPath)
Expand Down
2 changes: 1 addition & 1 deletion routers/web/repo/attachment.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ func ServeAttachment(ctx *context.Context, uuid string) {

if setting.Attachment.Storage.ServeDirect() {
// If we have a signed url (S3, object storage), redirect to this directly.
u, err := storage.Attachments.URL(attach.RelativePath(), attach.Name, nil)
u, err := storage.Attachments.URL(attach.RelativePath(), attach.Name, ctx.Req.Method, nil)

if u != nil && err == nil {
ctx.Redirect(u.String())
Expand Down
2 changes: 1 addition & 1 deletion routers/web/repo/download.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ func ServeBlobOrLFS(ctx *context.Context, blob *git.Blob, lastModified *time.Tim

if setting.LFS.Storage.ServeDirect() {
// If we have a signed url (S3, object storage, blob storage), redirect to this directly.
u, err := storage.LFS.URL(pointer.RelativePath(), blob.Name(), nil)
u, err := storage.LFS.URL(pointer.RelativePath(), blob.Name(), ctx.Req.Method, nil)
if u != nil && err == nil {
ctx.Redirect(u.String())
return nil
Expand Down
Loading