mirror of
https://github.com/git-pkgs/proxy.git
synced 2026-11-11 00:29:15 -05:00
* feat(storage): expose efficient seek for local files Open file-backed artifacts with os.Open so local readers support efficient seeking. Leave cloud storage readers unchanged. Keep the legacy sidecar mapping test focused on fileblob's reader: Blob.Open now reads local files directly and no longer consults the sidecar. Continue checking sidecar cleanup and post-store reads. * feat(handler): preserve efficient seek through integrity checks Keep the cache result's single Reader field and preserve io.Seeker when the underlying storage reader supports efficient seeking. Sequential reads continue through whole-object integrity verification. A successful seek switches subsequent reads to the source for range responses, where full-object verification is not possible. Test both modes and verify the source is closed once. * feat(handler): add request-aware byte range responses Add a request-aware artifact serving helper for bounded, open-ended, and suffix byte ranges, including If-Range handling, 206 responses, and 416 responses for valid unsatisfiable ranges. Ignore malformed and multi-range requests by serving the full artifact. Advertise byte-range support only for seekable readers, preserving HEAD, redirect, and non-seekable behavior. Clarify that net/http recovers ErrAbortHandler per request and keeps the server running. * feat(handler): enable byte ranges across artifact downloads Forward each artifact request to the shared range-aware response helper, including cached generic release assets and OCI blobs. This lets the handler honor ranges only when its reader supports efficient seeking, without changing direct-storage redirect behavior. Add warm-cache endpoint tests that assert partial response headers and bytes without an upstream refetch. Document supported range behavior, unsupported reader fallback, and the integrity limitation of partial reads.
43 lines
1,017 B
Go
43 lines
1,017 B
Go
package handler
|
|
|
|
import (
|
|
"net/http"
|
|
"strings"
|
|
)
|
|
|
|
type filenameDownload struct {
|
|
ecosystem string
|
|
upstreamURL string
|
|
suffix string
|
|
parseErr string
|
|
fetchErr string
|
|
parse func(string) (name, version string)
|
|
}
|
|
|
|
func (p *Proxy) handleFilenameDownload(w http.ResponseWriter, r *http.Request, d filenameDownload) {
|
|
filename := r.PathValue("filename")
|
|
if filename == "" || !strings.HasSuffix(filename, d.suffix) {
|
|
http.Error(w, "invalid filename", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
name, version := d.parse(filename)
|
|
if name == "" || version == "" {
|
|
http.Error(w, d.parseErr, http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
p.Logger.Info(d.ecosystem+" download request",
|
|
"name", name, "version", version, "filename", filename)
|
|
|
|
downloadURL := d.upstreamURL + r.URL.Path
|
|
result, err := p.GetOrFetchArtifactFromURL(
|
|
r.Context(), d.ecosystem, name, version, filename, downloadURL,
|
|
)
|
|
if err != nil {
|
|
p.serveArtifactError(w, err, d.fetchErr)
|
|
return
|
|
}
|
|
|
|
ServeArtifactRequest(w, r, result)
|
|
}
|