mirror of
https://github.com/nkanaev/yarr.git
synced 2025-05-24 00:33:14 +00:00
refactoring
This commit is contained in:
parent
9b04353c4a
commit
d07a5fd173
@ -20,6 +20,23 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var routes []Route = []Route{
|
||||||
|
p("/", IndexHandler),
|
||||||
|
p("/static/*path", StaticHandler),
|
||||||
|
p("/api/status", StatusHandler),
|
||||||
|
p("/api/folders", FolderListHandler),
|
||||||
|
p("/api/folders/:id", FolderHandler),
|
||||||
|
p("/api/feeds", FeedListHandler),
|
||||||
|
p("/api/feeds/:id", FeedHandler),
|
||||||
|
p("/api/feeds/find", FeedHandler),
|
||||||
|
p("/api/items", ItemListHandler),
|
||||||
|
p("/api/items/:id", ItemHandler),
|
||||||
|
p("/api/settings", SettingsHandler),
|
||||||
|
p("/opml/import", OPMLImportHandler),
|
||||||
|
p("/opml/export", OPMLExportHandler),
|
||||||
|
p("/page", PageCrawlHandler),
|
||||||
|
}
|
||||||
|
|
||||||
func IndexHandler(rw http.ResponseWriter, req *http.Request) {
|
func IndexHandler(rw http.ResponseWriter, req *http.Request) {
|
||||||
t := template.Must(template.New("index.html").Delims("{%", "%}").Funcs(template.FuncMap{
|
t := template.Must(template.New("index.html").Delims("{%", "%}").Funcs(template.FuncMap{
|
||||||
"inline": func(svg string) template.HTML {
|
"inline": func(svg string) template.HTML {
|
||||||
|
17
server/response.go
Normal file
17
server/response.go
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
"log"
|
||||||
|
)
|
||||||
|
|
||||||
|
func writeJSON(rw http.ResponseWriter, data interface{}) {
|
||||||
|
rw.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
|
reply, err := json.Marshal(data)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
rw.Write(reply)
|
||||||
|
rw.Write([]byte("\n"))
|
||||||
|
}
|
42
server/router.go
Normal file
42
server/router.go
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"regexp"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Route struct {
|
||||||
|
url string
|
||||||
|
urlRegex *regexp.Regexp
|
||||||
|
handler func(http.ResponseWriter, *http.Request)
|
||||||
|
}
|
||||||
|
|
||||||
|
func p(path string, handler func(http.ResponseWriter, *http.Request)) Route {
|
||||||
|
var urlRegexp string
|
||||||
|
urlRegexp = regexp.MustCompile(`[\*\:]\w+`).ReplaceAllStringFunc(path, func(m string) string {
|
||||||
|
if m[0:1] == `*` {
|
||||||
|
return "(?P<" + m[1:] + ">.+)"
|
||||||
|
}
|
||||||
|
return "(?P<" + m[1:] + ">[^/]+)"
|
||||||
|
})
|
||||||
|
urlRegexp = "^" + urlRegexp + "$"
|
||||||
|
return Route{
|
||||||
|
url: path,
|
||||||
|
urlRegex: regexp.MustCompile(urlRegexp),
|
||||||
|
handler: handler,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getRoute(req *http.Request) (*Route, map[string]string) {
|
||||||
|
vars := make(map[string]string)
|
||||||
|
for _, route := range routes {
|
||||||
|
if route.urlRegex.MatchString(req.URL.Path) {
|
||||||
|
matches := route.urlRegex.FindStringSubmatchIndex(req.URL.Path)
|
||||||
|
for i, key := range route.urlRegex.SubexpNames()[1:] {
|
||||||
|
vars[key] = req.URL.Path[matches[i*2+2]:matches[i*2+3]]
|
||||||
|
}
|
||||||
|
return &route, vars
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
}
|
@ -2,19 +2,11 @@ package server
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
|
||||||
"github.com/nkanaev/yarr/storage"
|
"github.com/nkanaev/yarr/storage"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"regexp"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Route struct {
|
|
||||||
url string
|
|
||||||
urlRegex *regexp.Regexp
|
|
||||||
handler func(http.ResponseWriter, *http.Request)
|
|
||||||
}
|
|
||||||
|
|
||||||
type Handler struct {
|
type Handler struct {
|
||||||
db *storage.Storage
|
db *storage.Storage
|
||||||
log *log.Logger
|
log *log.Logger
|
||||||
@ -25,14 +17,12 @@ type Handler struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func New(db *storage.Storage, logger *log.Logger) *Handler {
|
func New(db *storage.Storage, logger *log.Logger) *Handler {
|
||||||
db.DeleteOldItems()
|
return &Handler{
|
||||||
h := Handler{
|
|
||||||
db: db,
|
db: db,
|
||||||
log: logger,
|
log: logger,
|
||||||
feedQueue: make(chan storage.Feed),
|
feedQueue: make(chan storage.Feed),
|
||||||
counter: make(chan int),
|
counter: make(chan int),
|
||||||
}
|
}
|
||||||
return &h
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handler) Start(addr string) {
|
func (h *Handler) Start(addr string) {
|
||||||
@ -41,7 +31,19 @@ func (h *Handler) Start(addr string) {
|
|||||||
s.ListenAndServe()
|
s.ListenAndServe()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||||
|
route, vars := getRoute(req)
|
||||||
|
if route == nil {
|
||||||
|
rw.WriteHeader(http.StatusNotFound)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx := context.WithValue(req.Context(), ctxHandler, &h)
|
||||||
|
ctx = context.WithValue(ctx, ctxVars, vars)
|
||||||
|
route.handler(rw, req.WithContext(ctx))
|
||||||
|
}
|
||||||
|
|
||||||
func (h *Handler) startJobs() {
|
func (h *Handler) startJobs() {
|
||||||
|
h.db.DeleteOldItems()
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
feed := <-h.feedQueue
|
feed := <-h.feedQueue
|
||||||
@ -70,39 +72,6 @@ func (h *Handler) fetchAllFeeds() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func p(path string, handler func(http.ResponseWriter, *http.Request)) Route {
|
|
||||||
var urlRegexp string
|
|
||||||
urlRegexp = regexp.MustCompile(`[\*\:]\w+`).ReplaceAllStringFunc(path, func(m string) string {
|
|
||||||
if m[0:1] == `*` {
|
|
||||||
return "(?P<" + m[1:] + ">.+)"
|
|
||||||
}
|
|
||||||
return "(?P<" + m[1:] + ">[^/]+)"
|
|
||||||
})
|
|
||||||
urlRegexp = "^" + urlRegexp + "$"
|
|
||||||
return Route{
|
|
||||||
url: path,
|
|
||||||
urlRegex: regexp.MustCompile(urlRegexp),
|
|
||||||
handler: handler,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var routes []Route = []Route{
|
|
||||||
p("/", IndexHandler),
|
|
||||||
p("/static/*path", StaticHandler),
|
|
||||||
p("/api/status", StatusHandler),
|
|
||||||
p("/api/folders", FolderListHandler),
|
|
||||||
p("/api/folders/:id", FolderHandler),
|
|
||||||
p("/api/feeds", FeedListHandler),
|
|
||||||
p("/api/feeds/:id", FeedHandler),
|
|
||||||
p("/api/feeds/find", FeedHandler),
|
|
||||||
p("/api/items", ItemListHandler),
|
|
||||||
p("/api/items/:id", ItemHandler),
|
|
||||||
p("/api/settings", SettingsHandler),
|
|
||||||
p("/opml/import", OPMLImportHandler),
|
|
||||||
p("/opml/export", OPMLExportHandler),
|
|
||||||
p("/page", PageCrawlHandler),
|
|
||||||
}
|
|
||||||
|
|
||||||
func Vars(req *http.Request) map[string]string {
|
func Vars(req *http.Request) map[string]string {
|
||||||
if rv := req.Context().Value(ctxVars); rv != nil {
|
if rv := req.Context().Value(ctxVars); rv != nil {
|
||||||
return rv.(map[string]string)
|
return rv.(map[string]string)
|
||||||
@ -111,8 +80,8 @@ func Vars(req *http.Request) map[string]string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func db(req *http.Request) *storage.Storage {
|
func db(req *http.Request) *storage.Storage {
|
||||||
if rv := req.Context().Value(ctxDB); rv != nil {
|
if h := handler(req); h != nil {
|
||||||
return rv.(*storage.Storage)
|
return h.db
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -122,37 +91,6 @@ func handler(req *http.Request) *Handler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ctxDB = 1
|
|
||||||
ctxVars = 2
|
ctxVars = 2
|
||||||
ctxHandler = 3
|
ctxHandler = 3
|
||||||
)
|
)
|
||||||
|
|
||||||
func (h Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
|
||||||
for _, route := range routes {
|
|
||||||
if route.urlRegex.MatchString(req.URL.Path) {
|
|
||||||
ctx := context.WithValue(req.Context(), ctxDB, h.db)
|
|
||||||
ctx = context.WithValue(ctx, ctxHandler, &h)
|
|
||||||
if route.urlRegex.NumSubexp() > 0 {
|
|
||||||
vars := make(map[string]string)
|
|
||||||
matches := route.urlRegex.FindStringSubmatchIndex(req.URL.Path)
|
|
||||||
for i, key := range route.urlRegex.SubexpNames()[1:] {
|
|
||||||
vars[key] = req.URL.Path[matches[i*2+2]:matches[i*2+3]]
|
|
||||||
}
|
|
||||||
ctx = context.WithValue(ctx, ctxVars, vars)
|
|
||||||
}
|
|
||||||
route.handler(rw, req.WithContext(ctx))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rw.WriteHeader(http.StatusNotFound)
|
|
||||||
}
|
|
||||||
|
|
||||||
func writeJSON(rw http.ResponseWriter, data interface{}) {
|
|
||||||
rw.Header().Set("Content-Type", "application/json; charset=utf-8")
|
|
||||||
reply, err := json.Marshal(data)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
rw.Write(reply)
|
|
||||||
rw.Write([]byte("\n"))
|
|
||||||
}
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user