packages/http.go (114 lines of code) (raw):

// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one // or more contributor license agreements. Licensed under the Elastic License 2.0; // you may not use this file except in compliance with the Elastic License 2.0. package packages import ( "net/http" "os" "go.elastic.co/apm/v2" "go.uber.org/zap" "github.com/prometheus/client_golang/prometheus" "github.com/elastic/package-registry/archiver" "github.com/elastic/package-registry/metrics" ) const ( localLocationPrometheusLabel = "local" remoteLocationPrometheusLabel = "remote" artifactComponentPrometheusLabel = "artifacts" staticComponentPrometheusLabel = "statics" signatureComponentPrometheusLabel = "signatures" ) // ServePackage is used by artifactsHandler to serve packages and signatures. func ServePackage(logger *zap.Logger, w http.ResponseWriter, r *http.Request, p *Package) { span, _ := apm.StartSpan(r.Context(), "ServePackage", "app") defer span.End() if p.RemoteResolver() != nil { p.RemoteResolver().ArtifactsHandler(w, r, p) metrics.StorageRequestsTotal.With( prometheus.Labels{"location": remoteLocationPrometheusLabel, "component": artifactComponentPrometheusLabel}, ).Inc() return } serveLocalPackage(logger, w, r, p, p.BasePath) metrics.StorageRequestsTotal.With( prometheus.Labels{"location": localLocationPrometheusLabel, "component": artifactComponentPrometheusLabel}, ).Inc() } // ServePackageSignature is used by signaturesHandler to serve signatures. func ServePackageSignature(logger *zap.Logger, w http.ResponseWriter, r *http.Request, p *Package) { span, _ := apm.StartSpan(r.Context(), "ServePackageSignature", "app") defer span.End() if p.RemoteResolver() != nil { p.RemoteResolver().SignaturesHandler(w, r, p) metrics.StorageRequestsTotal.With( prometheus.Labels{"location": remoteLocationPrometheusLabel, "component": signatureComponentPrometheusLabel}, ).Inc() return } serveLocalPackage(logger, w, r, p, p.BasePath+".sig") metrics.StorageRequestsTotal.With( prometheus.Labels{"location": localLocationPrometheusLabel, "component": signatureComponentPrometheusLabel}, ).Inc() } func serveLocalPackage(logger *zap.Logger, w http.ResponseWriter, r *http.Request, p *Package, packagePath string) { span, _ := apm.StartSpan(r.Context(), "ServePackage", "app") defer span.End() logger = logger.With(zap.String("file.name", packagePath)) f, err := os.Stat(packagePath) if err != nil { logger.Error("stat package path failed", zap.Error(err)) http.Error(w, "internal server error", http.StatusInternalServerError) return } if f.IsDir() { w.Header().Set("Content-Type", "application/zip") err = archiver.ArchivePackage(w, archiver.PackageProperties{ Name: p.Name, Version: p.Version, Path: packagePath, }) if err != nil { logger.Error("archiving package path failed", zap.Error(err)) } return } http.ServeFile(w, r, packagePath) } // ServePackageResource is used by staticHandler. func ServePackageResource(logger *zap.Logger, w http.ResponseWriter, r *http.Request, p *Package, packageFilePath string) { span, _ := apm.StartSpan(r.Context(), "ServePackage", "app") defer span.End() if p.RemoteResolver() != nil { p.RemoteResolver().StaticHandler(w, r, p, packageFilePath) metrics.StorageRequestsTotal.With( prometheus.Labels{"location": remoteLocationPrometheusLabel, "component": staticComponentPrometheusLabel}, ).Inc() return } logger = logger.With(zap.String("file.name", packageFilePath)) fs, err := p.fs() if os.IsNotExist(err) { http.Error(w, "resource not found", http.StatusNotFound) return } if err != nil { logger.Error("failed to open filesystem", zap.Error(err)) http.Error(w, "internal server error", http.StatusInternalServerError) return } stat, err := fs.Stat(packageFilePath) if os.IsNotExist(err) { http.Error(w, "resource not found", http.StatusNotFound) return } if err != nil { logger.Error("stat failed", zap.Error(err)) http.Error(w, "internal server error", http.StatusInternalServerError) return } f, err := fs.Open(packageFilePath) if err != nil { logger.Error("failed to open file", zap.Error(err)) http.Error(w, "internal server error", http.StatusInternalServerError) return } defer f.Close() http.ServeContent(w, r, packageFilePath, stat.ModTime(), f) metrics.StorageRequestsTotal.With( prometheus.Labels{"location": localLocationPrometheusLabel, "component": staticComponentPrometheusLabel}, ).Inc() }