- Normalize: https, www or bare host, double slashes and index files, trailing slash add/remove, optional ASCII lowercasing (defaults change nothing but scheme, slashes and index files) - strict URLs through signpost MatchPath: a path that names a record without being its address 301s to the record's address - resolve runs normalisation, redirects, strict URLs, then SEO; the location is the final address, so a visitor makes one hop - P1 warns when a record's canonical URL redirects
69 lines
2.2 KiB
Go
69 lines
2.2 KiB
Go
package classes
|
|
|
|
import (
|
|
"context"
|
|
"net/url"
|
|
"strings"
|
|
|
|
"git.golem15.com/golem15/summercms/modules/pact"
|
|
)
|
|
|
|
// StrictMatch is the record behind a path and whether the path is its
|
|
// address (D-20c). Key is "" when no published record answers the path.
|
|
type StrictMatch struct {
|
|
Key string
|
|
Match *pact.ContentMatchResult
|
|
Record *pact.ContentRecord
|
|
// Canonical is the record's own path in the matched locale, in the
|
|
// site's address form; "" when the descriptor answers none.
|
|
Canonical string
|
|
// Mismatch is true when the path names the record but is not its
|
|
// address: a wrong category or parent, a locale prefix with another
|
|
// locale's slug, a moved record. It then 301s to Canonical.
|
|
Mismatch bool
|
|
}
|
|
|
|
// Strict finds the published record behind path through the signpost
|
|
// patterns (MatchPath) and checks every segment against the record's own
|
|
// address (D-20c): a path that names a record without being its address
|
|
// is a mismatch, so a wrong URL never answers ok. The comparison uses the
|
|
// site's address form (opts), so a strict 301 and normalisation never
|
|
// send a visitor back and forth.
|
|
func (r *Resolver) Strict(ctx context.Context, path string, opts NormalizeOptions) (StrictMatch, error) {
|
|
var out StrictMatch
|
|
reg := r.Service.Registry()
|
|
if reg == nil {
|
|
return out, nil
|
|
}
|
|
unprefixed := r.Service.UnprefixedLocale()
|
|
// Content patterns carry no trailing slash; the site's trailing-slash
|
|
// rule is applied to the record's address below.
|
|
key, match, err := reg.MatchPath(ctx, trimSlash(path), unprefixed)
|
|
if err != nil || match == nil {
|
|
return out, err
|
|
}
|
|
rec, err := reg.Describe(ctx, key, match.ID, unprefixed)
|
|
if err != nil || rec == nil || !rec.Published {
|
|
return out, err
|
|
}
|
|
out.Key, out.Match, out.Record = key, match, rec
|
|
described := ""
|
|
for _, l := range rec.Locales {
|
|
if l.Locale == match.Locale {
|
|
described = strings.TrimSpace(l.URL)
|
|
}
|
|
}
|
|
if described == "" {
|
|
out.Mismatch = !match.Exact
|
|
return out, nil
|
|
}
|
|
du, err := url.Parse(described)
|
|
if err != nil {
|
|
return out, nil
|
|
}
|
|
canonical, _ := Normalize(&url.URL{Path: du.Path}, opts)
|
|
out.Canonical = canonical.Path
|
|
out.Mismatch = !match.Exact || canonical.Path != path
|
|
return out, nil
|
|
}
|