violet/target/redirect.go

76 lines
1.6 KiB
Go
Raw Normal View History

2023-04-19 01:30:23 +01:00
package target
import (
"fmt"
2023-07-22 01:11:47 +01:00
"github.com/1f349/violet/utils"
2023-04-19 01:30:23 +01:00
"net/http"
"net/url"
"path"
"strings"
2023-04-19 01:30:23 +01:00
)
// Redirect is a target used by the router to manage redirecting the request
// using the specified configuration.
2023-04-19 01:30:23 +01:00
type Redirect struct {
Src string `json:"src"` // request source
Dst string `json:"dst"` // redirect destination
Flags Flags `json:"flags"` // extra flags
Code int `json:"code"` // status code used to redirect
2023-04-19 01:30:23 +01:00
}
2023-07-13 00:15:00 +01:00
type RedirectWithActive struct {
Redirect
Active bool `json:"active"`
}
2023-08-28 23:09:29 +01:00
func (r Redirect) HasFlag(flag Flags) bool {
return r.Flags&flag != 0
}
// ServeHTTP responds with the redirect to the response writer provided.
func (r Redirect) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
// default to redirecting with StatusFound if code is not set
code := r.Code
if r.Code == 0 {
code = http.StatusFound
}
// split the host and path
host, p := utils.SplitHostPath(r.Dst)
// if not Abs then join with the ending of the current path
if !r.Flags.HasFlag(FlagAbs) {
p = path.Join(p, req.URL.Path)
// replace the trailing slash that path.Join() strips off
if strings.HasSuffix(req.URL.Path, "/") {
p += "/"
}
}
// fix empty path
if p == "" {
p = "/"
}
// create a new URL
u := &url.URL{
Scheme: req.URL.Scheme,
Host: host,
Path: p,
}
// close the incoming body after use
if req.Body != nil {
defer req.Body.Close()
}
// use fast redirect for speed
utils.FastRedirect(rw, req, u.String(), code)
}
// String outputs a debug string for the redirect.
func (r Redirect) String() string {
return fmt.Sprintf("%#v", r)
2023-04-19 01:30:23 +01:00
}