Configure routes based on post paths from DB

This commit is contained in:
Jan-Lukas Else 2020-07-29 17:17:48 +02:00
parent 04ec81a43b
commit 9ee3c0c730
3 changed files with 79 additions and 17 deletions

70
http.go
View File

@ -9,27 +9,23 @@ import (
"os" "os"
"os/signal" "os/signal"
"strconv" "strconv"
"sync"
"syscall" "syscall"
"time" "time"
) )
func startServer() { func startServer() error {
r := chi.NewRouter() d := newDynamicHandler()
h, err := buildHandler()
if appConfig.server.logging { if err != nil {
r.Use(middleware.RealIP) return err
r.Use(middleware.Logger)
} }
r.Use(middleware.Recoverer) d.swapHandler(h)
r.Use(middleware.StripSlashes)
r.Get("/", hello)
r.Get("/*", servePost)
address := ":" + strconv.Itoa(appConfig.server.port) address := ":" + strconv.Itoa(appConfig.server.port)
srv := &http.Server{ srv := &http.Server{
Addr: address, Addr: address,
Handler: r, Handler: d,
} }
go func() { go func() {
@ -45,10 +41,58 @@ func startServer() {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel() defer cancel()
if err := srv.Shutdown(ctx); err != nil { if err := srv.Shutdown(ctx); err != nil {
log.Fatal(err) return err
} }
return nil
}
func buildHandler() (http.Handler, error) {
r := chi.NewRouter()
if appConfig.server.logging {
r.Use(middleware.RealIP)
r.Use(middleware.Logger)
}
r.Use(middleware.Recoverer)
r.Use(middleware.StripSlashes)
r.Get("/", hello)
allPostPaths, err := allPostPaths()
if err != nil {
return nil, err
} else {
for _, path := range allPostPaths {
if path != "" {
r.Get("/"+path, servePost)
}
}
}
return r, nil
} }
func hello(w http.ResponseWriter, _ *http.Request) { func hello(w http.ResponseWriter, _ *http.Request) {
_, _ = w.Write([]byte("Hello World!")) _, _ = w.Write([]byte("Hello World!"))
} }
type dynamicHandler struct {
realHandler http.Handler
changeMutex *sync.Mutex
}
func newDynamicHandler() *dynamicHandler {
return &dynamicHandler{
changeMutex: &sync.Mutex{},
}
}
func (d *dynamicHandler) swapHandler(h http.Handler) {
d.changeMutex.Lock()
d.realHandler = h
d.changeMutex.Unlock()
}
func (d *dynamicHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
d.realHandler.ServeHTTP(w, r)
}

View File

@ -23,5 +23,8 @@ func main() {
}() }()
log.Println("Loaded database") log.Println("Loaded database")
log.Println("Start server") log.Println("Start server")
startServer() err = startServer()
if err != nil {
log.Fatal(err)
}
} }

View File

@ -1,6 +1,7 @@
package main package main
import ( import (
"context"
"database/sql" "database/sql"
"errors" "errors"
"net/http" "net/http"
@ -17,7 +18,7 @@ type post struct {
} }
func servePost(w http.ResponseWriter, r *http.Request) { func servePost(w http.ResponseWriter, r *http.Request) {
post, err := getPost(strings.TrimSuffix(strings.TrimPrefix(r.RequestURI, "/"), "/")) post, err := getPost(strings.TrimSuffix(strings.TrimPrefix(r.RequestURI, "/"), "/"), r.Context())
if err == postNotFound { if err == postNotFound {
http.NotFound(w, r) http.NotFound(w, r)
return return
@ -34,9 +35,9 @@ func servePost(w http.ResponseWriter, r *http.Request) {
_, _ = w.Write(htmlContent) _, _ = w.Write(htmlContent)
} }
func getPost(path string) (*post, error) { func getPost(path string, context context.Context) (*post, error) {
queriedPost := &post{} queriedPost := &post{}
row := appDb.QueryRow("select path, COALESCE(content, ''), COALESCE(published, ''), COALESCE(updated, '') from posts where path=?", path) row := appDb.QueryRowContext(context, "select path, COALESCE(content, ''), COALESCE(published, ''), COALESCE(updated, '') from posts where path=?", path)
err := row.Scan(&queriedPost.path, &queriedPost.content, &queriedPost.published, &queriedPost.updated) err := row.Scan(&queriedPost.path, &queriedPost.content, &queriedPost.published, &queriedPost.updated)
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
return nil, postNotFound return nil, postNotFound
@ -45,3 +46,17 @@ func getPost(path string) (*post, error) {
} }
return queriedPost, nil return queriedPost, nil
} }
func allPostPaths() ([]string, error) {
var postPaths []string
rows, err := appDb.Query("select path from posts")
if err != nil {
return nil, err
}
for rows.Next() {
var path string
_ = rows.Scan(&path)
postPaths = append(postPaths, path)
}
return postPaths, nil
}