fix: exact redirects with a trailing slash or an upper-case query fire at runtime (CR-03)
The resolver fetched exact rules with lower(source) IN keys, while the keys drop one trailing slash and keep the query as written, so a source stored as /old/ or /list?Page=2 was never read. A new migration adds the stored generated column source_key (the SQL form of exactKey) with an index for exact rules, and the fetch compares it.
This commit is contained in:
@@ -117,7 +117,9 @@ func toggleSlash(p string) string {
|
||||
}
|
||||
|
||||
// exactKey is the lookup key of an exact source: lowercased, without a
|
||||
// trailing slash on its path, with its query as written.
|
||||
// trailing slash on its path, with its query as written. The column
|
||||
// golem15_seo_redirects.source_key computes the same key in SQL (migration
|
||||
// 202610280001); change both together.
|
||||
func exactKey(source string) string {
|
||||
p, q, hasQuery := strings.Cut(source, "?")
|
||||
key := strings.ToLower(trimSlash(p))
|
||||
@@ -225,8 +227,9 @@ func LoadRedirects(db *gorm.DB) ([]models.Redirect, error) {
|
||||
}
|
||||
|
||||
// LoadRedirectSet reads the rule set for the resolver: every pattern and
|
||||
// regex rule now, exact rules per path as the set needs them (indexed on
|
||||
// lower(source)).
|
||||
// regex rule now, exact rules per path as the set needs them, by the
|
||||
// generated source_key column, which holds exactKey(source) (so the fetch
|
||||
// sees the same rules as an in-memory set).
|
||||
func LoadRedirectSet(db *gorm.DB) (*RedirectSet, error) {
|
||||
var rows []models.Redirect
|
||||
if err := db.Where("match <> ?", models.RedirectExact).Order("id ASC").Find(&rows).Error; err != nil {
|
||||
@@ -235,7 +238,7 @@ func LoadRedirectSet(db *gorm.DB) (*RedirectSet, error) {
|
||||
s := NewRedirectSet(rows)
|
||||
s.fetch = func(keys []string) ([]models.Redirect, error) {
|
||||
var out []models.Redirect
|
||||
err := db.Where("match = ? AND lower(source) IN ?", models.RedirectExact, keys).Order("id ASC").Find(&out).Error
|
||||
err := db.Where("match = ? AND source_key IN ?", models.RedirectExact, keys).Order("id ASC").Find(&out).Error
|
||||
return out, err
|
||||
}
|
||||
return s, nil
|
||||
|
||||
Reference in New Issue
Block a user