mirror of
https://codeberg.org/git-pages/git-pages.git
synced 2026-05-14 11:11:35 +00:00
Observe all storage errors reported by GetManifest.
Otherwise users may get jumpscares of "site not found" due to temporary conditions (network errors to S3 backend included).
This commit is contained in:
@@ -10,7 +10,7 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
var errNotFound = errors.New("not found")
|
||||
var ObjectNotFoundError = errors.New("not found")
|
||||
|
||||
func splitBlobName(name string) []string {
|
||||
algo, hash, found := strings.Cut(name, "-")
|
||||
|
||||
@@ -100,7 +100,7 @@ func (fs *FSBackend) GetBlob(
|
||||
blobPath := filepath.Join(splitBlobName(name)...)
|
||||
stat, err := fs.blobRoot.Stat(blobPath)
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
err = fmt.Errorf("%w: %s", errNotFound, err.(*os.PathError).Path)
|
||||
err = fmt.Errorf("%w: %s", ObjectNotFoundError, err.(*os.PathError).Path)
|
||||
return
|
||||
} else if err != nil {
|
||||
err = fmt.Errorf("stat: %w", err)
|
||||
@@ -171,7 +171,7 @@ func (b *FSBackend) ListManifests(ctx context.Context) (manifests []string, err
|
||||
func (fs *FSBackend) GetManifest(ctx context.Context, name string, opts GetManifestOptions) (*Manifest, error) {
|
||||
data, err := fs.siteRoot.ReadFile(name)
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
return nil, fmt.Errorf("%w: %s", errNotFound, err.(*os.PathError).Path)
|
||||
return nil, fmt.Errorf("%w: %s", ObjectNotFoundError, err.(*os.PathError).Path)
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -299,7 +299,7 @@ func (s3 *S3Backend) GetBlob(
|
||||
cached, err = s3.blobCache.Get(ctx, name, otter.LoaderFunc[string, *CachedBlob](loader))
|
||||
if err != nil {
|
||||
if errResp := minio.ToErrorResponse(err); errResp.Code == "NoSuchKey" {
|
||||
err = fmt.Errorf("%w: %s", errNotFound, errResp.Key)
|
||||
err = fmt.Errorf("%w: %s", ObjectNotFoundError, errResp.Key)
|
||||
}
|
||||
} else {
|
||||
reader = bytes.NewReader(cached.blob)
|
||||
@@ -433,7 +433,7 @@ func (l s3ManifestLoader) load(ctx context.Context, name string, oldManifest *Ca
|
||||
|
||||
if err != nil {
|
||||
if errResp := minio.ToErrorResponse(err); errResp.Code == "NoSuchKey" {
|
||||
err = fmt.Errorf("%w: %s", errNotFound, errResp.Key)
|
||||
err = fmt.Errorf("%w: %s", ObjectNotFoundError, errResp.Key)
|
||||
return &CachedManifest{nil, 1, etag, err}, nil
|
||||
} else if errResp.StatusCode == http.StatusNotModified && oldManifest != nil {
|
||||
return oldManifest, nil
|
||||
|
||||
27
src/pages.go
27
src/pages.go
@@ -88,24 +88,31 @@ func getPage(w http.ResponseWriter, r *http.Request) error {
|
||||
return err
|
||||
}
|
||||
|
||||
indexManifestCh := make(chan *Manifest, 1)
|
||||
type indexManifestResult struct {
|
||||
manifest *Manifest
|
||||
err error
|
||||
}
|
||||
indexManifestCh := make(chan indexManifestResult, 1)
|
||||
go func() {
|
||||
manifest, _ := backend.GetManifest(r.Context(), makeWebRoot(host, ".index"),
|
||||
manifest, err := backend.GetManifest(r.Context(), makeWebRoot(host, ".index"),
|
||||
GetManifestOptions{BypassCache: bypassCache})
|
||||
indexManifestCh <- manifest
|
||||
indexManifestCh <- (indexManifestResult{manifest, err})
|
||||
}()
|
||||
|
||||
err = nil
|
||||
sitePath = strings.TrimPrefix(r.URL.Path, "/")
|
||||
if projectName, projectPath, found := strings.Cut(sitePath, "/"); found {
|
||||
projectManifest, err := backend.GetManifest(r.Context(), makeWebRoot(host, projectName),
|
||||
var projectManifest *Manifest
|
||||
projectManifest, err = backend.GetManifest(r.Context(), makeWebRoot(host, projectName),
|
||||
GetManifestOptions{BypassCache: bypassCache})
|
||||
if err == nil {
|
||||
sitePath, manifest = projectPath, projectManifest
|
||||
}
|
||||
}
|
||||
if manifest == nil {
|
||||
manifest = <-indexManifestCh
|
||||
if manifest == nil {
|
||||
if manifest == nil && (err == nil || errors.Is(err, ObjectNotFoundError)) {
|
||||
result := <-indexManifestCh
|
||||
manifest, err = result.manifest, result.err
|
||||
if manifest == nil && errors.Is(err, ObjectNotFoundError) {
|
||||
if found, fallbackErr := HandleWildcardFallback(w, r); found {
|
||||
return fallbackErr
|
||||
} else {
|
||||
@@ -115,6 +122,12 @@ func getPage(w http.ResponseWriter, r *http.Request) error {
|
||||
}
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
ObserveError(err) // all storage errors must be reported
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
fmt.Fprintf(w, "internal server error (%s)\n", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if r.Header.Get("Origin") != "" {
|
||||
// allow JavaScript code to access responses (including errors) even across origins
|
||||
|
||||
Reference in New Issue
Block a user