mirror of
https://codeberg.org/git-pages/git-pages.git
synced 2026-05-18 13:11:35 +00:00
Implement force redirects.
This commit is contained in:
36
src/pages.go
36
src/pages.go
@@ -141,22 +141,28 @@ func getPage(w http.ResponseWriter, r *http.Request) error {
|
||||
return err
|
||||
}
|
||||
entry = manifest.Contents[entryPath]
|
||||
if entry == nil || entry.GetType() == Type_Invalid {
|
||||
if !appliedRedirect {
|
||||
originalURL := (&url.URL{Host: r.Host}).ResolveReference(r.URL)
|
||||
redirectURL, redirectStatus := ApplyRedirects(manifest, originalURL)
|
||||
if Is3xxHTTPStatus(redirectStatus) {
|
||||
w.Header().Set("Location", redirectURL.String())
|
||||
w.WriteHeader(int(redirectStatus))
|
||||
fmt.Fprintf(w, "see %s\n", redirectURL.String())
|
||||
return nil
|
||||
} else if redirectURL != nil {
|
||||
entryPath = strings.TrimPrefix(redirectURL.Path, "/")
|
||||
status = int(redirectStatus)
|
||||
appliedRedirect = true
|
||||
continue
|
||||
}
|
||||
if !appliedRedirect {
|
||||
redirectKind := RedirectAny
|
||||
if entry != nil && entry.GetType() != Type_Invalid {
|
||||
redirectKind = RedirectForce
|
||||
}
|
||||
originalURL := (&url.URL{Host: r.Host}).ResolveReference(r.URL)
|
||||
redirectURL, redirectStatus := ApplyRedirects(manifest, originalURL, redirectKind)
|
||||
if Is3xxHTTPStatus(redirectStatus) {
|
||||
w.Header().Set("Location", redirectURL.String())
|
||||
w.WriteHeader(int(redirectStatus))
|
||||
fmt.Fprintf(w, "see %s\n", redirectURL.String())
|
||||
return nil
|
||||
} else if redirectURL != nil {
|
||||
entryPath = strings.TrimPrefix(redirectURL.Path, "/")
|
||||
status = int(redirectStatus)
|
||||
// Apply user redirects at most once; if something ends in a loop, it should be
|
||||
// the user agent, not the pages server.
|
||||
appliedRedirect = true
|
||||
continue
|
||||
}
|
||||
}
|
||||
if entry == nil || entry.GetType() == Type_Invalid {
|
||||
status = 404
|
||||
if entryPath != notFoundPage {
|
||||
entryPath = notFoundPage
|
||||
|
||||
@@ -80,9 +80,6 @@ func validateRule(rule redirects.Rule) error {
|
||||
if toURL.Host != "" && !Is3xxHTTPStatus(uint(rule.Status)) {
|
||||
return fmt.Errorf("'to' URL may only include a hostname for 3xx status rules")
|
||||
}
|
||||
if rule.Force {
|
||||
return fmt.Errorf("force redirects are not supported")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -130,10 +127,24 @@ func toOrFromComponent(to, from string) string {
|
||||
}
|
||||
}
|
||||
|
||||
func ApplyRedirects(manifest *Manifest, fromURL *url.URL) (toURL *url.URL, status uint) {
|
||||
type RedirectKind int
|
||||
|
||||
const (
|
||||
RedirectAny RedirectKind = iota
|
||||
RedirectForce
|
||||
)
|
||||
|
||||
func ApplyRedirects(
|
||||
manifest *Manifest, fromURL *url.URL, kind RedirectKind,
|
||||
) (
|
||||
toURL *url.URL, status uint,
|
||||
) {
|
||||
fromSegments := pathSegments(fromURL.Path)
|
||||
next:
|
||||
for _, rule := range manifest.Redirects {
|
||||
if kind == RedirectForce && !*rule.Force {
|
||||
continue
|
||||
}
|
||||
// check if the rule matches fromURL
|
||||
ruleFromURL, _ := url.Parse(*rule.From) // pre-validated in `validateRule`
|
||||
if ruleFromURL.Scheme != "" && fromURL.Scheme != ruleFromURL.Scheme {
|
||||
|
||||
Reference in New Issue
Block a user