diff --git a/gateway/handler_unixfs__redirects.go b/gateway/handler_unixfs__redirects.go index afd0c7c3c..9a3e9daec 100644 --- a/gateway/handler_unixfs__redirects.go +++ b/gateway/handler_unixfs__redirects.go @@ -39,78 +39,85 @@ import ( func (i *handler) serveRedirectsIfPresent(w http.ResponseWriter, r *http.Request, resolvedPath ipath.Resolved, contentPath ipath.Path, logger *zap.SugaredLogger) (newResolvedPath ipath.Resolved, newContentPath ipath.Path, continueProcessing bool, hadMatchingRule bool) { redirectsFile := i.getRedirectsFile(r, contentPath, logger) if redirectsFile != nil { - redirectRules, err := i.getRedirectRules(r, redirectsFile) - if err != nil { - webError(w, err, http.StatusInternalServerError) - return nil, nil, false, true - } + // No matching rule, paths remain the same, continue regular processing + return resolvedPath, contentPath, true, false + } - redirected, newPath, err := i.handleRedirectsFileRules(w, r, contentPath, redirectRules) - if err != nil { - err = fmt.Errorf("trouble processing _redirects file at %q: %w", redirectsFile.String(), err) - webError(w, err, http.StatusInternalServerError) - return nil, nil, false, true - } + redirectRules, err := i.getRedirectRules(r, redirectsFile) + if err != nil { + webError(w, err, http.StatusInternalServerError) + return nil, nil, false, true + } - if redirected { - return nil, nil, false, true - } + redirected, newPath, err := i.handleRedirectsFileRules(w, r, contentPath, redirectRules) + if err != nil { + err = fmt.Errorf("trouble processing _redirects file at %q: %w", redirectsFile.String(), err) + webError(w, err, http.StatusInternalServerError) + return nil, nil, false, true + } - // 200 is treated as a rewrite, so update the path and continue - if newPath != "" { - // Reassign contentPath and resolvedPath since the URL was rewritten - contentPath = ipath.New(newPath) - resolvedPath, err = i.api.ResolvePath(r.Context(), contentPath) - if err != nil { - webError(w, err, http.StatusInternalServerError) - return nil, nil, false, true - } + if redirected { + return nil, nil, false, true + } - return resolvedPath, contentPath, true, true - } + // 200 is treated as a rewrite, so update the path and continue + if newPath == "" { + // No matching rule, paths remain the same, continue regular processing + return resolvedPath, contentPath, true, false + } + + // Reassign contentPath and resolvedPath since the URL was rewritten + contentPath = ipath.New(newPath) + resolvedPath, err = i.api.ResolvePath(r.Context(), contentPath) + if err != nil { + webError(w, err, http.StatusInternalServerError) + return nil, nil, false, true } - // No matching rule, paths remain the same, continue regular processing - return resolvedPath, contentPath, true, false + + return resolvedPath, contentPath, true, true } func (i *handler) handleRedirectsFileRules(w http.ResponseWriter, r *http.Request, contentPath ipath.Path, redirectRules []redirects.Rule) (redirected bool, newContentPath string, err error) { // Attempt to match a rule to the URL path, and perform the corresponding redirect or rewrite pathParts := strings.Split(contentPath.String(), "/") - if len(pathParts) > 3 { - // All paths should start with /ipfs/cid/, so get the path after that - urlPath := "/" + strings.Join(pathParts[3:], "/") - rootPath := strings.Join(pathParts[:3], "/") - // Trim off the trailing / - urlPath = strings.TrimSuffix(urlPath, "/") - - for _, rule := range redirectRules { - // Error right away if the rule is invalid - if !rule.MatchAndExpandPlaceholders(urlPath) { - continue - } + if len(pathParts) <= 3 { + // Path isn't /ipfs/cid/ as expected + return false, "", nil + } - // We have a match! + // All paths should start with /ipfs/cid/, so get the path after that + urlPath := "/" + strings.Join(pathParts[3:], "/") + rootPath := strings.Join(pathParts[:3], "/") + // Trim off the trailing / + urlPath = strings.TrimSuffix(urlPath, "/") - // Rewrite - if rule.Status == 200 { - // Prepend the rootPath - toPath := rootPath + rule.To - return false, toPath, nil - } + for _, rule := range redirectRules { + // Error right away if the rule is invalid + if !rule.MatchAndExpandPlaceholders(urlPath) { + continue + } - // Or 4xx - if rule.Status == 404 || rule.Status == 410 || rule.Status == 451 { - toPath := rootPath + rule.To - content4xxPath := ipath.New(toPath) - err := i.serve4xx(w, r, content4xxPath, rule.Status) - return true, toPath, err - } + // We have a match! - // Or redirect - if rule.Status >= 301 && rule.Status <= 308 { - http.Redirect(w, r, rule.To, rule.Status) - return true, "", nil - } + // Rewrite + if rule.Status == 200 { + // Prepend the rootPath + toPath := rootPath + rule.To + return false, toPath, nil + } + + // Or 4xx + if rule.Status == 404 || rule.Status == 410 || rule.Status == 451 { + toPath := rootPath + rule.To + content4xxPath := ipath.New(toPath) + err := i.serve4xx(w, r, content4xxPath, rule.Status) + return true, toPath, err + } + + // Or redirect + if rule.Status >= 301 && rule.Status <= 308 { + http.Redirect(w, r, rule.To, rule.Status) + return true, "", nil } }