make route handling better

This commit is contained in:
hcl 2021-01-25 23:28:52 +08:00 committed by nkanaev
parent 4f79c919f0
commit 52073e7e81
4 changed files with 40 additions and 54 deletions

View File

@ -44,8 +44,6 @@ func main() {
server.BasePath = strings.TrimSuffix(server.BasePath, "/") server.BasePath = strings.TrimSuffix(server.BasePath, "/")
} }
server.BasePathReady <- true
logger := log.New(os.Stdout, "", log.Ldate|log.Ltime|log.Lshortfile) logger := log.New(os.Stdout, "", log.Ldate|log.Ltime|log.Lshortfile)
configPath, err := os.UserConfigDir() configPath, err := os.UserConfigDir()

View File

@ -6,6 +6,7 @@ import (
"encoding/base64" "encoding/base64"
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/nkanaev/yarr/storage"
"html" "html"
"html/template" "html/template"
"io" "io"
@ -18,41 +19,27 @@ import (
"reflect" "reflect"
"strconv" "strconv"
"strings" "strings"
"github.com/nkanaev/yarr/storage"
) )
var routes []Route var routes []Route = []Route{
p("/", IndexHandler).ManualAuth(),
p("/static/*path", StaticHandler).ManualAuth(),
var BasePathReady = make(chan bool) p("/api/status", StatusHandler),
p("/api/folders", FolderListHandler),
func init() { p("/api/folders/:id", FolderHandler),
go func() { p("/api/feeds", FeedListHandler),
<-BasePathReady p("/api/feeds/find", FeedHandler),
routes = []Route{ p("/api/feeds/refresh", FeedRefreshHandler),
p(BasePath+"/", IndexHandler).ManualAuth(), p("/api/feeds/errors", FeedErrorsHandler),
p(BasePath+"/static/*path", StaticHandler).ManualAuth(), p("/api/feeds/:id/icon", FeedIconHandler),
p("/api/feeds/:id", FeedHandler),
p(BasePath+"/api/status", StatusHandler), p("/api/items", ItemListHandler),
p(BasePath+"/api/folders", FolderListHandler), p("/api/items/:id", ItemHandler),
p(BasePath+"/api/folders/:id", FolderHandler), p("/api/settings", SettingsHandler),
p(BasePath+"/api/feeds", FeedListHandler), p("/opml/import", OPMLImportHandler),
p(BasePath+"/api/feeds/find", FeedHandler), p("/opml/export", OPMLExportHandler),
p(BasePath+"/api/feeds/refresh", FeedRefreshHandler), p("/page", PageCrawlHandler),
p(BasePath+"/api/feeds/errors", FeedErrorsHandler),
p(BasePath+"/api/feeds/:id/icon", FeedIconHandler),
p(BasePath+"/api/feeds/:id", FeedHandler),
p(BasePath+"/api/items", ItemListHandler),
p(BasePath+"/api/items/:id", ItemHandler),
p(BasePath+"/api/settings", SettingsHandler),
p(BasePath+"/opml/import", OPMLImportHandler),
p(BasePath+"/opml/export", OPMLExportHandler),
p(BasePath+"/page", PageCrawlHandler),
}
if BasePath != "" {
routes = append(routes, p(BasePath, RedirectBasePathHandler).ManualAuth())
}
}()
} }
type asset struct { type asset struct {
@ -153,11 +140,6 @@ func IndexHandler(rw http.ResponseWriter, req *http.Request) {
func StaticHandler(rw http.ResponseWriter, req *http.Request) { func StaticHandler(rw http.ResponseWriter, req *http.Request) {
path := Vars(req)["path"] path := Vars(req)["path"]
if BasePath != "" {
path = strings.TrimPrefix(path, BasePath)
}
ctype := mime.TypeByExtension(filepath.Ext(path)) ctype := mime.TypeByExtension(filepath.Ext(path))
if assets != nil { if assets != nil {
@ -546,7 +528,3 @@ func PageCrawlHandler(rw http.ResponseWriter, req *http.Request) {
} }
} }
} }
func RedirectBasePathHandler(rw http.ResponseWriter, req *http.Request) {
http.Redirect(rw, req, req.URL.Path+"/", http.StatusFound)
}

View File

@ -35,13 +35,13 @@ func p(path string, handler func(http.ResponseWriter, *http.Request)) Route {
} }
} }
func getRoute(req *http.Request) (*Route, map[string]string) { func getRoute(reqPath string) (*Route, map[string]string) {
vars := make(map[string]string) vars := make(map[string]string)
for _, route := range routes { for _, route := range routes {
if route.urlRegex.MatchString(req.URL.Path) { if route.urlRegex.MatchString(reqPath) {
matches := route.urlRegex.FindStringSubmatchIndex(req.URL.Path) matches := route.urlRegex.FindStringSubmatchIndex(reqPath)
for i, key := range route.urlRegex.SubexpNames()[1:] { for i, key := range route.urlRegex.SubexpNames()[1:] {
vars[key] = req.URL.Path[matches[i*2+2]:matches[i*2+3]] vars[key] = reqPath[matches[i*2+2]:matches[i*2+3]]
} }
return &route, vars return &route, vars
} }

View File

@ -2,12 +2,14 @@ package server
import ( import (
"context" "context"
"github.com/nkanaev/yarr/storage"
"log" "log"
"net/http" "net/http"
"runtime" "runtime"
"strings"
"sync/atomic" "sync/atomic"
"time" "time"
"github.com/nkanaev/yarr/storage"
) )
type Handler struct { type Handler struct {
@ -18,11 +20,11 @@ type Handler struct {
queueSize *int32 queueSize *int32
refreshRate chan int64 refreshRate chan int64
// auth // auth
Username string Username string
Password string Password string
// https // https
CertFile string CertFile string
KeyFile string KeyFile string
} }
func New(db *storage.Storage, logger *log.Logger, addr string) *Handler { func New(db *storage.Storage, logger *log.Logger, addr string) *Handler {
@ -39,7 +41,7 @@ func New(db *storage.Storage, logger *log.Logger, addr string) *Handler {
func (h *Handler) GetAddr() string { func (h *Handler) GetAddr() string {
proto := "http" proto := "http"
if (h.CertFile != "" && h.KeyFile != "") { if h.CertFile != "" && h.KeyFile != "" {
proto = "https" proto = "https"
} }
return proto + "://" + h.Addr return proto + "://" + h.Addr
@ -65,7 +67,15 @@ func unsafeMethod(method string) bool {
} }
func (h Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) { func (h Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
route, vars := getRoute(req) reqPath := req.URL.Path
if BasePath != "" {
reqPath = strings.TrimPrefix(req.URL.Path, BasePath)
if reqPath == "" {
http.Redirect(rw, req, BasePath+"/", http.StatusFound)
return
}
}
route, vars := getRoute(reqPath)
if route == nil { if route == nil {
rw.WriteHeader(http.StatusNotFound) rw.WriteHeader(http.StatusNotFound)
return return