backup-notify/api/serve.go
2024-04-21 18:46:40 -07:00

93 lines
3.4 KiB
Go

package api
import (
"database/sql"
"fmt"
"log"
"net/http"
"time"
"git.simponic.xyz/simponic/backup-notify/api/backups"
"git.simponic.xyz/simponic/backup-notify/api/template"
"git.simponic.xyz/simponic/backup-notify/api/types"
"git.simponic.xyz/simponic/backup-notify/args"
"git.simponic.xyz/simponic/backup-notify/utils"
)
func LogRequestContinuation(context *types.RequestContext, req *http.Request, resp http.ResponseWriter) types.ContinuationChain {
return func(success types.Continuation, _failure types.Continuation) types.ContinuationChain {
context.Start = time.Now()
context.Id = utils.RandomId()
log.Println(req.Method, req.URL.Path, req.RemoteAddr, context.Id)
return success(context, req, resp)
}
}
func LogExecutionTimeContinuation(context *types.RequestContext, req *http.Request, resp http.ResponseWriter) types.ContinuationChain {
return func(success types.Continuation, _failure types.Continuation) types.ContinuationChain {
end := time.Now()
log.Println(context.Id, "took", end.Sub(context.Start))
return success(context, req, resp)
}
}
func HealthCheckContinuation(context *types.RequestContext, req *http.Request, resp http.ResponseWriter) types.ContinuationChain {
return func(success types.Continuation, _failure types.Continuation) types.ContinuationChain {
resp.WriteHeader(200)
resp.Write([]byte("healthy"))
return success(context, req, resp)
}
}
func FailurePassingContinuation(context *types.RequestContext, req *http.Request, resp http.ResponseWriter) types.ContinuationChain {
return func(_success types.Continuation, failure types.Continuation) types.ContinuationChain {
return failure(context, req, resp)
}
}
func IdContinuation(context *types.RequestContext, req *http.Request, resp http.ResponseWriter) types.ContinuationChain {
return func(success types.Continuation, _failure types.Continuation) types.ContinuationChain {
return success(context, req, resp)
}
}
func CacheControlMiddleware(next http.Handler, maxAge int) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
header := fmt.Sprintf("public, max-age=%d", maxAge)
w.Header().Set("Cache-Control", header)
next.ServeHTTP(w, r)
})
}
func MakeServer(argv *args.Arguments, dbConn *sql.DB) *http.Server {
mux := http.NewServeMux()
staticFileServer := http.FileServer(http.Dir(argv.StaticPath))
mux.Handle("GET /static/", http.StripPrefix("/static/", CacheControlMiddleware(staticFileServer, 3600)))
makeRequestContext := func() *types.RequestContext {
return &types.RequestContext{
DBConn: dbConn,
Args: argv,
TemplateData: &map[string]interface{}{},
}
}
mux.HandleFunc("GET /health", func(w http.ResponseWriter, r *http.Request) {
requestContext := makeRequestContext()
LogRequestContinuation(requestContext, r, w)(HealthCheckContinuation, FailurePassingContinuation)(LogExecutionTimeContinuation, LogExecutionTimeContinuation)(IdContinuation, IdContinuation)
})
mux.HandleFunc("GET /", func(w http.ResponseWriter, r *http.Request) {
requestContext := makeRequestContext()
LogRequestContinuation(requestContext, r, w)(backups.ListBackupsContinuation, backups.ListBackupsContinuation)(template.TemplateContinuation("backup_list.html", true), FailurePassingContinuation)(LogExecutionTimeContinuation, LogExecutionTimeContinuation)(IdContinuation, IdContinuation)
})
return &http.Server{
Addr: ":" + fmt.Sprint(argv.Port),
Handler: mux,
}
}