2020-07-29 15:39:46 +00:00
package main
import (
"context"
"database/sql"
"errors"
"net/http"
)
2020-07-30 19:18:13 +00:00
var errRedirectNotFound = errors . New ( "redirect not found" )
2020-07-29 15:39:46 +00:00
func serveRedirect ( w http . ResponseWriter , r * http . Request ) {
2020-07-31 19:02:47 +00:00
redirect , more , err := getRedirect ( r . Context ( ) , slashTrimmedPath ( r ) )
2020-07-30 19:18:13 +00:00
if err == errRedirectNotFound {
2020-07-31 19:02:47 +00:00
serve404 ( w , r )
2020-07-29 15:39:46 +00:00
return
} else if err != nil {
http . Error ( w , err . Error ( ) , http . StatusInternalServerError )
return
}
2020-07-31 19:02:47 +00:00
// Flatten redirects
if more {
for more == true {
redirect , more , _ = getRedirect ( r . Context ( ) , trimSlash ( redirect ) )
}
}
// Send redirect
w . Header ( ) . Set ( "Location" , redirect )
render ( w , templateRedirect , struct {
2020-07-31 13:48:01 +00:00
Permalink string
} {
Permalink : redirect ,
} )
2020-07-31 19:02:47 +00:00
w . WriteHeader ( http . StatusFound )
2020-07-29 15:39:46 +00:00
}
2020-07-31 19:02:47 +00:00
func getRedirect ( context context . Context , fromPath string ) ( string , bool , error ) {
2020-07-29 15:39:46 +00:00
var toPath string
2020-07-31 19:02:47 +00:00
var moreRedirects int
row := appDb . QueryRowContext ( context , "select toPath, (select count(*) from redirects where fromPath=(select toPath from redirects where fromPath=?)) as more from redirects where fromPath=?" , fromPath , fromPath )
err := row . Scan ( & toPath , & moreRedirects )
2020-07-29 15:39:46 +00:00
if err == sql . ErrNoRows {
2020-07-31 19:02:47 +00:00
return "" , false , errRedirectNotFound
2020-07-29 15:39:46 +00:00
} else if err != nil {
2020-07-31 19:02:47 +00:00
return "" , false , err
2020-07-29 15:39:46 +00:00
}
2020-07-31 19:02:47 +00:00
return toPath , moreRedirects > 0 , nil
2020-07-29 15:39:46 +00:00
}
func allRedirectPaths ( ) ( [ ] string , error ) {
var redirectPaths [ ] string
rows , err := appDb . Query ( "select fromPath from redirects" )
if err != nil {
return nil , err
}
for rows . Next ( ) {
var path string
_ = rows . Scan ( & path )
redirectPaths = append ( redirectPaths , path )
}
return redirectPaths , nil
}