Documentation
¶
Overview ¶
Package redirects sends visitors from old URLs to new ones, for example after moving a site to WebThings. Editors manage the redirects in the admin: an old path, a new address (a path on this site or a full URL) and the kind of redirect (301, 302, 307 or 308). Each redirect counts its hits. Add the module with:
app.Use(redirects.Module())
Its admin section is at <AdminPath>/redirects; redirects.Module(redirects.Named("old", "Old addresses")) chooses another key and title.
The module wraps the public site. GET and HEAD requests whose path matches a redirect are redirected before the site handles them; the query string is kept when the new address has none. Paths are compared after normalising: host, query and fragment are dropped, a leading slash is added, trailing slashes and dot segments are removed, and case is kept. The home page "/" and the paths WebThings serves itself (webthings.App.CorePaths: the admin, visitor actions (/_/), media, assets, theme files, sitemap.xml, robots.txt, /healthz, /readyz and /metrics) are never redirected.
Requests that end in "not found" are counted as missed paths; the admin lists the most frequent ones so editors can add redirects for them. A "not found" that asks not to be indexed (X-Robots-Tag: noindex or none), such as a mistyped registration code, is not a missed page and is not counted.
The admin can import redirects as CSV, one per line: old path, new address and, optionally, the status (301 when empty). A first line starting with "from" is skipped, and semicolons may separate the fields instead of commas. An import saves all lines or, when one is wrong, none.
Deleting a redirect moves it to the admin's trash: it stops redirecting and its path is free for a new redirect. Restoring it fails while another redirect uses the path.
The module also redirects for the page editor (webthings.Parts.Redirects, see Service.Redirect): when a page that published content links to is unpublished, or a revision that changes its address is published, the editor offers to redirect the addresses it leaves, and the report of broken links offers to redirect an address that links lead to.
The module has no public templates or template functions.
Index ¶
- Variables
- func Module(opts ...Option) webthings.Module
- func Normalize(address string) (string, error)
- type EditView
- type ImportError
- type ImportView
- type IndexRow
- type IndexView
- type LineError
- type Miss
- type MissedRow
- type MissedView
- type Option
- type Redirect
- type Service
- func (s *Service) ClearMissed(ctx context.Context) error
- func (s *Service) Delete(ctx context.Context, id string) error
- func (s *Service) Flush(ctx context.Context) error
- func (s *Service) Get(ctx context.Context, id string) (Redirect, error)
- func (s *Service) Import(ctx context.Context, source io.Reader) (int, error)
- func (s *Service) List(ctx context.Context) ([]Redirect, error)
- func (s *Service) Missed(ctx context.Context, limit int) ([]Miss, error)
- func (s *Service) Purge(ctx context.Context, id string) error
- func (s *Service) Redirect(ctx context.Context, address, target string) error
- func (s *Service) Redirected(ctx context.Context, address string) (string, bool)
- func (s *Service) Resolve(ctx context.Context, requestPath string) (Redirect, bool)
- func (s *Service) Save(ctx context.Context, redirect Redirect) (Redirect, error)
- func (s *Service) Trace(ctx context.Context, requestPath string) []Redirect
- func (s *Service) Trashed(ctx context.Context, limit, offset int) ([]Redirect, int, error)
- func (s *Service) Undelete(ctx context.Context, id string) error
- type TestResult
Constants ¶
This section is empty.
Variables ¶
var Statuses = []int{301, 302, 307, 308}
Statuses are the HTTP statuses a redirect can answer with.
Functions ¶
Types ¶
type EditView ¶
type EditView struct {
Title string
BackURL string
// BackLabel names the list BackURL leads to, as a translation key.
BackLabel string
// Warnings point out chains of redirects.
Warnings []string
// Saved is set for an existing redirect, which has hits.
Saved bool
Hits int64
LastHit string
Form form.RenderModel
Errors form.FieldErrors
Delete *form.RenderModel
}
EditView is the data of templates/admin/edit.gohtml: the form of one redirect.
type ImportError ¶
type ImportError struct {
Lines []LineError
}
ImportError lists the lines an import refused; nothing was saved.
func (*ImportError) Error ¶
func (e *ImportError) Error() string
Error lists the refused lines with their reasons.
type ImportView ¶
type ImportView struct {
Title string
BackURL string
// Problems lists the refused lines; nothing was imported.
Problems []string
Form form.RenderModel
Errors form.FieldErrors
}
ImportView is the data of templates/admin/import.gohtml: the form that imports redirects from CSV.
type IndexRow ¶
type IndexRow struct {
URL string
From string
To string
Status int
Hits int64
LastHit string
// Chained is set when To leads to another redirect.
Chained bool
}
IndexRow is one redirect in the list, with how often it was used.
type IndexView ¶
type IndexView struct {
Title string
NewURL string
ImportURL string
MissedURL string
// TrashURL shows the deleted redirects in the admin's trash.
TrashURL string
// TestURL is where the test box sends ?test=<path>.
TestURL string
// TestForm is the test box, a form that gets TestURL.
TestForm form.RenderModel
Test *TestResult
Rows []IndexRow
// Pager pages through long lists.
Pager admin.Pager
}
IndexView is the data of templates/admin/index.gohtml: the redirects, with a box to test where a path leads.
type Miss ¶
type Miss struct {
Path string `db:"path"`
Hits int64 `db:"hits"`
LastHit time.Time `db:"last_hit_at"`
}
Miss is a path that was not found, with how often and when it was last requested.
type MissedRow ¶
type MissedRow struct {
Path string
Hits int64
LastHit string
// AddURL opens a new redirect for the path; empty without the right.
AddURL string
}
MissedRow is one path that was not found, with how often it was asked for.
type MissedView ¶
type MissedView struct {
Title string
BackURL string
Rows []MissedRow
Clear *form.RenderModel
}
MissedView is the data of templates/admin/missed.gohtml: the paths visitors asked for that the site does not have.
type Redirect ¶
type Redirect struct {
ID string `db:"id"`
// From is the normalised old path, for example "/old-page".
From string `db:"from_path"`
// To is a path on the site, such as "/en/news", or an absolute URL.
To string `db:"to_url"`
Status int `db:"status"`
Hits int64 `db:"hits"`
LastHit *time.Time `db:"last_hit_at"`
// CreatedAt is when the redirect was added, CreatedBy by whom (empty for
// the system).
CreatedAt time.Time `db:"created_at"`
CreatedBy db.Ref `db:"created_by"`
// UpdatedAt and UpdatedBy are the last change by an editor; hits do not
// count as changes.
UpdatedAt time.Time `db:"updated_at"`
UpdatedBy db.Ref `db:"updated_by"`
// DeletedAt is set while the redirect is in the trash, with DeletedBy.
DeletedAt *time.Time `db:"deleted_at"`
DeletedBy db.Ref `db:"deleted_by"`
}
Redirect sends requests for From to To.
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
Service is one Redirects instance, for the website's own code.
func (*Service) ClearMissed ¶
ClearMissed empties the list of missed paths.
func (*Service) Delete ¶
Delete moves a redirect to the trash: it stops redirecting and its path is free for a new redirect. An unknown one, or one already in the trash, is db.ErrNotFound.
func (*Service) Get ¶
Get returns one redirect, or db.ErrNotFound when it does not exist or is in the trash.
func (*Service) Import ¶
Import reads CSV lines "old path,new address[,status]" and saves them, replacing redirects with the same old path. It saves all lines or, when a line is wrong, none; then the error is an *ImportError. A source over 1 MiB or 5000 lines is refused whole. It returns the number of redirects saved.
func (*Service) Missed ¶
Missed returns the most requested paths that were not found and have no redirect yet.
func (*Service) Purge ¶
Purge removes a redirect in the trash for good; one that is not in the trash is db.ErrNotFound.
func (*Service) Redirect ¶
Redirect sends the visitors of address to target, a path on this site or a full URL, with a permanent redirect (301) from now on: it replaces the redirect of address when there is one, and moves a redirect of target to the trash, as it would hide the page that is there now. It is the module's links.Redirector (webthings.Parts.Redirects): the admin redirects with it the addresses that links lead to when a page leaves them. A reserved address, or one target leads back to, is refused, as by Save.
func (*Service) Redirected ¶
Redirected returns where the redirect of address, a path on this site, sends visitors; ok is false when no redirect has it. It is part of the module's links.Redirector, with Redirect.
func (*Service) Resolve ¶
Resolve returns the redirect for a request path, if there is one. No redirect is saved from a reserved path (see Save), and requests to the paths the app serves itself never reach the site's middleware.
func (*Service) Save ¶
Save validates and stores a redirect: a new one when ID is empty, otherwise it changes From, To and Status of an existing one. A redirect that would lead back to its own path, directly or through other redirects, is refused.
func (*Service) Trace ¶
Trace follows a path through the redirects, at most a few steps, and returns each redirect on the way.
func (*Service) Trashed ¶
Trashed returns redirects in the trash, most recently deleted first: at most limit of them from offset (all for a limit of 0), and how many the trash holds in all.
type TestResult ¶
TestResult is what the test box found for a path.