Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add direct serving of package content #25543

Merged
merged 12 commits into from
Jul 3, 2023
10 changes: 10 additions & 0 deletions modules/packages/content_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ package packages

import (
"io"
"net/url"
"path"
"strings"

"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/storage"
"code.gitea.io/gitea/modules/util"
)
Expand All @@ -31,6 +33,14 @@ func (s *ContentStore) Get(key BlobHash256Key) (storage.Object, error) {
return s.store.Open(KeyToRelativePath(key))
}

func (s *ContentStore) ShouldServeDirect() bool {
return setting.Packages.Storage.MinioConfig.ServeDirect
}

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

// FIXME: Workaround to be removed in v1.20
// https://github.com/go-gitea/gitea/issues/19586
func (s *ContentStore) Has(key BlobHash256Key) error {
Expand Down
16 changes: 14 additions & 2 deletions routers/api/packages/alpine/alpine.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ func GetRepositoryFile(ctx *context.Context) {
return
}

s, pf, err := packages_service.GetFileStreamByPackageVersion(
s, u, pf, err := packages_service.GetFileStreamByPackageVersion(
ctx,
pv,
&packages_service.PackageFileInfo{
Expand All @@ -84,6 +84,12 @@ func GetRepositoryFile(ctx *context.Context) {
}
return
}

if u != nil {
ctx.Redirect(u.String())
return
}

defer s.Close()

ctx.ServeContent(s, &context.ServeHeaderOptions{
Expand Down Expand Up @@ -200,7 +206,7 @@ func DownloadPackageFile(ctx *context.Context) {
return
}

s, pf, err := packages_service.GetPackageFileStream(ctx, pfs[0])
s, u, pf, err := packages_service.GetPackageFileStream(ctx, pfs[0])
if err != nil {
if errors.Is(err, util.ErrNotExist) {
apiError(ctx, http.StatusNotFound, err)
Expand All @@ -209,6 +215,12 @@ func DownloadPackageFile(ctx *context.Context) {
}
return
}

if u != nil {
ctx.Redirect(u.String())
return
}

defer s.Close()

ctx.ServeContent(s, &context.ServeHeaderOptions{
Expand Down
8 changes: 7 additions & 1 deletion routers/api/packages/cargo/cargo.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ func ListOwners(ctx *context.Context) {

// DownloadPackageFile serves the content of a package
func DownloadPackageFile(ctx *context.Context) {
s, pf, err := packages_service.GetFileStreamByPackageNameAndVersion(
s, u, pf, err := packages_service.GetFileStreamByPackageNameAndVersion(
ctx,
&packages_service.PackageInfo{
Owner: ctx.Package.Owner,
Expand All @@ -185,6 +185,12 @@ func DownloadPackageFile(ctx *context.Context) {
apiError(ctx, http.StatusInternalServerError, err)
return
}

if u != nil {
ctx.Redirect(u.String())
return
}

defer s.Close()

ctx.ServeContent(s, &context.ServeHeaderOptions{
Expand Down
8 changes: 7 additions & 1 deletion routers/api/packages/chef/chef.go
Original file line number Diff line number Diff line change
Expand Up @@ -341,11 +341,17 @@ func DownloadPackage(ctx *context.Context) {

pf := pd.Files[0].File

s, _, err := packages_service.GetPackageFileStream(ctx, pf)
s, u, _, err := packages_service.GetPackageFileStream(ctx, pf)
if err != nil {
apiError(ctx, http.StatusInternalServerError, err)
return
}

if u != nil {
ctx.Redirect(u.String())
return
}

defer s.Close()

ctx.ServeContent(s, &context.ServeHeaderOptions{
Expand Down
8 changes: 7 additions & 1 deletion routers/api/packages/composer/composer.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ func PackageMetadata(ctx *context.Context) {

// DownloadPackageFile serves the content of a package
func DownloadPackageFile(ctx *context.Context) {
s, pf, err := packages_service.GetFileStreamByPackageNameAndVersion(
s, u, pf, err := packages_service.GetFileStreamByPackageNameAndVersion(
ctx,
&packages_service.PackageInfo{
Owner: ctx.Package.Owner,
Expand All @@ -182,6 +182,12 @@ func DownloadPackageFile(ctx *context.Context) {
apiError(ctx, http.StatusInternalServerError, err)
return
}

if u != nil {
ctx.Redirect(u.String())
return
}

defer s.Close()

ctx.ServeContent(s, &context.ServeHeaderOptions{
Expand Down
8 changes: 7 additions & 1 deletion routers/api/packages/conan/conan.go
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,7 @@ func downloadFile(ctx *context.Context, fileFilter container.Set[string], fileKe
return
}

s, pf, err := packages_service.GetFileStreamByPackageNameAndVersion(
s, u, pf, err := packages_service.GetFileStreamByPackageNameAndVersion(
ctx,
&packages_service.PackageInfo{
Owner: ctx.Package.Owner,
Expand All @@ -474,6 +474,12 @@ func downloadFile(ctx *context.Context, fileFilter container.Set[string], fileKe
apiError(ctx, http.StatusInternalServerError, err)
return
}

if u != nil {
ctx.Redirect(u.String())
return
}

defer s.Close()

ctx.ServeContent(s, &context.ServeHeaderOptions{
Expand Down
8 changes: 7 additions & 1 deletion routers/api/packages/conda/conda.go
Original file line number Diff line number Diff line change
Expand Up @@ -292,11 +292,17 @@ func DownloadPackageFile(ctx *context.Context) {

pf := pfs[0]

s, _, err := packages_service.GetPackageFileStream(ctx, pf)
s, u, _, err := packages_service.GetPackageFileStream(ctx, pf)
if err != nil {
apiError(ctx, http.StatusInternalServerError, err)
return
}

if u != nil {
ctx.Redirect(u.String())
return
}

defer s.Close()

ctx.ServeContent(s, &context.ServeHeaderOptions{
Expand Down
64 changes: 32 additions & 32 deletions routers/api/packages/container/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -482,22 +482,7 @@ func GetBlob(ctx *context.Context) {
return
}

s, _, err := packages_service.GetPackageFileStream(ctx, blob.File)
if err != nil {
apiError(ctx, http.StatusInternalServerError, err)
return
}
defer s.Close()

setResponseHeaders(ctx.Resp, &containerHeaders{
ContentDigest: blob.Properties.GetByName(container_module.PropertyDigest),
ContentType: blob.Properties.GetByName(container_module.PropertyMediaType),
ContentLength: blob.Blob.Size,
Status: http.StatusOK,
})
if _, err := io.Copy(ctx.Resp, s); err != nil {
log.Error("Error whilst copying content to response: %v", err)
}
serveBlob(ctx, blob)
}

// https://github.com/opencontainers/distribution-spec/blob/main/spec.md#deleting-blobs
Expand Down Expand Up @@ -636,22 +621,7 @@ func GetManifest(ctx *context.Context) {
return
}

s, _, err := packages_service.GetPackageFileStream(ctx, manifest.File)
if err != nil {
apiError(ctx, http.StatusInternalServerError, err)
return
}
defer s.Close()

setResponseHeaders(ctx.Resp, &containerHeaders{
ContentDigest: manifest.Properties.GetByName(container_module.PropertyDigest),
ContentType: manifest.Properties.GetByName(container_module.PropertyMediaType),
ContentLength: manifest.Blob.Size,
Status: http.StatusOK,
})
if _, err := io.Copy(ctx.Resp, s); err != nil {
log.Error("Error whilst copying content to response: %v", err)
}
serveBlob(ctx, manifest)
}

// https://github.com/opencontainers/distribution-spec/blob/main/spec.md#deleting-tags
Expand Down Expand Up @@ -686,6 +656,36 @@ func DeleteManifest(ctx *context.Context) {
})
}

func serveBlob(ctx *context.Context, pfd *packages_model.PackageFileDescriptor) {
s, u, _, err := packages_service.GetPackageFileStream(ctx, pfd.File)
if err != nil {
apiError(ctx, http.StatusInternalServerError, err)
return
}

headers := &containerHeaders{
ContentDigest: pfd.Properties.GetByName(container_module.PropertyDigest),
ContentType: pfd.Properties.GetByName(container_module.PropertyMediaType),
ContentLength: pfd.Blob.Size,
Status: http.StatusOK,
}

if u != nil {
headers.Status = http.StatusTemporaryRedirect
headers.Location = u.String()

setResponseHeaders(ctx.Resp, headers)
return
}

defer s.Close()

setResponseHeaders(ctx.Resp, headers)
if _, err := io.Copy(ctx.Resp, s); err != nil {
log.Error("Error whilst copying content to response: %v", err)
}
}

// https://github.com/opencontainers/distribution-spec/blob/main/spec.md#content-discovery
func GetTagList(ctx *context.Context) {
image := ctx.Params("image")
Expand Down
8 changes: 7 additions & 1 deletion routers/api/packages/cran/cran.go
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ func downloadPackageFile(ctx *context.Context, opts *cran_model.SearchOptions) {
return
}

s, _, err := packages_service.GetPackageFileStream(ctx, pf)
s, u, _, err := packages_service.GetPackageFileStream(ctx, pf)
if err != nil {
if errors.Is(err, util.ErrNotExist) {
apiError(ctx, http.StatusNotFound, err)
Expand All @@ -258,6 +258,12 @@ func downloadPackageFile(ctx *context.Context, opts *cran_model.SearchOptions) {
}
return
}

if u != nil {
ctx.Redirect(u.String())
return
}

defer s.Close()

ctx.ServeContent(s, &context.ServeHeaderOptions{
Expand Down
24 changes: 21 additions & 3 deletions routers/api/packages/debian/debian.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func GetRepositoryFile(ctx *context.Context) {
key += "|" + component + "|" + architecture
}

s, pf, err := packages_service.GetFileStreamByPackageVersion(
s, u, pf, err := packages_service.GetFileStreamByPackageVersion(
ctx,
pv,
&packages_service.PackageFileInfo{
Expand All @@ -75,6 +75,12 @@ func GetRepositoryFile(ctx *context.Context) {
}
return
}

if u != nil {
ctx.Redirect(u.String())
return
}

defer s.Close()

ctx.ServeContent(s, &context.ServeHeaderOptions{
Expand Down Expand Up @@ -110,7 +116,7 @@ func GetRepositoryFileByHash(ctx *context.Context) {
return
}

s, pf, err := packages_service.GetPackageFileStream(ctx, pfs[0])
s, u, pf, err := packages_service.GetPackageFileStream(ctx, pfs[0])
if err != nil {
if errors.Is(err, util.ErrNotExist) {
apiError(ctx, http.StatusNotFound, err)
Expand All @@ -119,6 +125,12 @@ func GetRepositoryFileByHash(ctx *context.Context) {
}
return
}

if u != nil {
ctx.Redirect(u.String())
return
}

defer s.Close()

ctx.ServeContent(s, &context.ServeHeaderOptions{
Expand Down Expand Up @@ -217,7 +229,7 @@ func DownloadPackageFile(ctx *context.Context) {
name := ctx.Params("name")
version := ctx.Params("version")

s, pf, err := packages_service.GetFileStreamByPackageNameAndVersion(
s, u, pf, err := packages_service.GetFileStreamByPackageNameAndVersion(
ctx,
&packages_service.PackageInfo{
Owner: ctx.Package.Owner,
Expand All @@ -238,6 +250,12 @@ func DownloadPackageFile(ctx *context.Context) {
}
return
}

if u != nil {
ctx.Redirect(u.String())
return
}

defer s.Close()

ctx.ServeContent(s, &context.ServeHeaderOptions{
Expand Down
8 changes: 7 additions & 1 deletion routers/api/packages/generic/generic.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func apiError(ctx *context.Context, status int, obj interface{}) {

// DownloadPackageFile serves the specific generic package.
func DownloadPackageFile(ctx *context.Context) {
s, pf, err := packages_service.GetFileStreamByPackageNameAndVersion(
s, u, pf, err := packages_service.GetFileStreamByPackageNameAndVersion(
ctx,
&packages_service.PackageInfo{
Owner: ctx.Package.Owner,
Expand All @@ -50,6 +50,12 @@ func DownloadPackageFile(ctx *context.Context) {
apiError(ctx, http.StatusInternalServerError, err)
return
}

if u != nil {
ctx.Redirect(u.String())
return
}

defer s.Close()

ctx.ServeContent(s, &context.ServeHeaderOptions{
Expand Down
8 changes: 7 additions & 1 deletion routers/api/packages/goproxy/goproxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ func DownloadPackageFile(ctx *context.Context) {
return
}

s, _, err := packages_service.GetPackageFileStream(ctx, pfs[0])
s, u, _, err := packages_service.GetPackageFileStream(ctx, pfs[0])
if err != nil {
if errors.Is(err, util.ErrNotExist) {
apiError(ctx, http.StatusNotFound, err)
Expand All @@ -114,6 +114,12 @@ func DownloadPackageFile(ctx *context.Context) {
}
return
}

if u != nil {
ctx.Redirect(u.String())
return
}

defer s.Close()

ctx.ServeContent(s, &context.ServeHeaderOptions{
Expand Down
Loading