aboutsummaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
authorKN4CK3R <admin@oldschoolhack.me>2023-07-03 15:33:28 +0200
committerGitHub <noreply@github.com>2023-07-03 15:33:28 +0200
commitc890454769562e0ec2978e123aaf3d9a43e5ef4f (patch)
treea152b5a0356a3da4f83083c5e7fc87214f8bd251 /services
parentf1cb461c1fb23b68ae34ada2de6bad3bfa6ceeca (diff)
downloadgitea-c890454769562e0ec2978e123aaf3d9a43e5ef4f.tar.gz
gitea-c890454769562e0ec2978e123aaf3d9a43e5ef4f.zip
Add direct serving of package content (#25543)
Fixes #24723 Direct serving of content aka HTTP redirect is not mentioned in any of the package registry specs but lots of official registries do that so it should be supported by the usual clients.
Diffstat (limited to 'services')
-rw-r--r--services/packages/packages.go74
1 files changed, 34 insertions, 40 deletions
diff --git a/services/packages/packages.go b/services/packages/packages.go
index 23aa8a5c31..e6d3b0fe5b 100644
--- a/services/packages/packages.go
+++ b/services/packages/packages.go
@@ -9,6 +9,7 @@ import (
"errors"
"fmt"
"io"
+ "net/url"
"strings"
"code.gitea.io/gitea/models/db"
@@ -20,6 +21,7 @@ import (
"code.gitea.io/gitea/modules/notification"
packages_module "code.gitea.io/gitea/modules/packages"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/storage"
"code.gitea.io/gitea/modules/util"
)
@@ -562,70 +564,62 @@ func DeletePackageFile(ctx context.Context, pf *packages_model.PackageFile) erro
}
// GetFileStreamByPackageNameAndVersion returns the content of the specific package file
-func GetFileStreamByPackageNameAndVersion(ctx context.Context, pvi *PackageInfo, pfi *PackageFileInfo) (io.ReadSeekCloser, *packages_model.PackageFile, error) {
+func GetFileStreamByPackageNameAndVersion(ctx context.Context, pvi *PackageInfo, pfi *PackageFileInfo) (io.ReadSeekCloser, *url.URL, *packages_model.PackageFile, error) {
log.Trace("Getting package file stream: %v, %v, %s, %s, %s, %s", pvi.Owner.ID, pvi.PackageType, pvi.Name, pvi.Version, pfi.Filename, pfi.CompositeKey)
pv, err := packages_model.GetVersionByNameAndVersion(ctx, pvi.Owner.ID, pvi.PackageType, pvi.Name, pvi.Version)
if err != nil {
if err == packages_model.ErrPackageNotExist {
- return nil, nil, err
+ return nil, nil, nil, err
}
log.Error("Error getting package: %v", err)
- return nil, nil, err
+ return nil, nil, nil, err
}
return GetFileStreamByPackageVersion(ctx, pv, pfi)
}
-// GetFileStreamByPackageVersionAndFileID returns the content of the specific package file
-func GetFileStreamByPackageVersionAndFileID(ctx context.Context, owner *user_model.User, versionID, fileID int64) (io.ReadSeekCloser, *packages_model.PackageFile, error) {
- log.Trace("Getting package file stream: %v, %v, %v", owner.ID, versionID, fileID)
-
- pv, err := packages_model.GetVersionByID(ctx, versionID)
- if err != nil {
- if err != packages_model.ErrPackageNotExist {
- log.Error("Error getting package version: %v", err)
- }
- return nil, nil, err
- }
-
- p, err := packages_model.GetPackageByID(ctx, pv.PackageID)
- if err != nil {
- log.Error("Error getting package: %v", err)
- return nil, nil, err
- }
-
- if p.OwnerID != owner.ID {
- return nil, nil, packages_model.ErrPackageNotExist
- }
-
- pf, err := packages_model.GetFileForVersionByID(ctx, versionID, fileID)
- if err != nil {
- log.Error("Error getting file: %v", err)
- return nil, nil, err
- }
-
- return GetPackageFileStream(ctx, pf)
-}
-
// GetFileStreamByPackageVersion returns the content of the specific package file
-func GetFileStreamByPackageVersion(ctx context.Context, pv *packages_model.PackageVersion, pfi *PackageFileInfo) (io.ReadSeekCloser, *packages_model.PackageFile, error) {
+func GetFileStreamByPackageVersion(ctx context.Context, pv *packages_model.PackageVersion, pfi *PackageFileInfo) (io.ReadSeekCloser, *url.URL, *packages_model.PackageFile, error) {
pf, err := packages_model.GetFileForVersionByName(ctx, pv.ID, pfi.Filename, pfi.CompositeKey)
if err != nil {
- return nil, nil, err
+ return nil, nil, nil, err
}
return GetPackageFileStream(ctx, pf)
}
// GetPackageFileStream returns the content of the specific package file
-func GetPackageFileStream(ctx context.Context, pf *packages_model.PackageFile) (io.ReadSeekCloser, *packages_model.PackageFile, error) {
+func GetPackageFileStream(ctx context.Context, pf *packages_model.PackageFile) (io.ReadSeekCloser, *url.URL, *packages_model.PackageFile, error) {
pb, err := packages_model.GetBlobByID(ctx, pf.BlobID)
if err != nil {
- return nil, nil, err
+ return nil, nil, nil, err
+ }
+
+ return GetPackageBlobStream(ctx, pf, pb)
+}
+
+// GetPackageBlobStream returns the content of the specific package blob
+// If the storage supports direct serving and it's enabled, only the direct serving url is returned.
+func GetPackageBlobStream(ctx context.Context, pf *packages_model.PackageFile, pb *packages_model.PackageBlob) (io.ReadSeekCloser, *url.URL, *packages_model.PackageFile, error) {
+ key := packages_module.BlobHash256Key(pb.HashSHA256)
+
+ cs := packages_module.NewContentStore()
+
+ var s io.ReadSeekCloser
+ var u *url.URL
+ var err error
+
+ if cs.ShouldServeDirect() {
+ u, err = cs.GetServeDirectURL(key, pf.Name)
+ if err != nil && !errors.Is(err, storage.ErrURLNotSupported) {
+ log.Error("Error getting serve direct url: %v", err)
+ }
+ }
+ if u == nil {
+ s, err = cs.Get(key)
}
- s, err := packages_module.NewContentStore().Get(packages_module.BlobHash256Key(pb.HashSHA256))
if err == nil {
if pf.IsLead {
if err := packages_model.IncrementDownloadCounter(ctx, pf.VersionID); err != nil {
@@ -633,7 +627,7 @@ func GetPackageFileStream(ctx context.Context, pf *packages_model.PackageFile) (
}
}
}
- return s, pf, err
+ return s, u, pf, err
}
// RemoveAllPackages for User