112 lines
3.5 KiB
Go
112 lines
3.5 KiB
Go
|
package api
|
||
|
|
||
|
import (
|
||
|
"crypto/rand"
|
||
|
"database/sql"
|
||
|
"fmt"
|
||
|
"log"
|
||
|
"net/http"
|
||
|
"time"
|
||
|
|
||
|
"git.hatecomputers.club/hatecomputers/hatecomputers.club/args"
|
||
|
)
|
||
|
|
||
|
type RequestContext struct {
|
||
|
DBConn *sql.DB
|
||
|
Args *args.Arguments
|
||
|
|
||
|
Id string
|
||
|
Start time.Time
|
||
|
}
|
||
|
|
||
|
type Continuation func(*RequestContext, *http.Request, http.ResponseWriter) ContinuationChain
|
||
|
type ContinuationChain func(Continuation, Continuation) ContinuationChain
|
||
|
|
||
|
func randomId() string {
|
||
|
uuid := make([]byte, 16)
|
||
|
_, err := rand.Read(uuid)
|
||
|
if err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
|
||
|
uuid[8] = uuid[8]&^0xc0 | 0x80
|
||
|
uuid[6] = uuid[6]&^0xf0 | 0x40
|
||
|
|
||
|
return fmt.Sprintf("%x-%x-%x-%x-%x", uuid[0:4], uuid[4:6], uuid[6:8], uuid[8:10], uuid[10:])
|
||
|
}
|
||
|
|
||
|
func LogRequestContinuation(context *RequestContext, req *http.Request, resp http.ResponseWriter) ContinuationChain {
|
||
|
return func(success Continuation, _failure Continuation) ContinuationChain {
|
||
|
context.Start = time.Now()
|
||
|
context.Id = randomId()
|
||
|
|
||
|
log.Println(req.Method, req.URL.Path, req.RemoteAddr, context.Id)
|
||
|
return success(context, req, resp)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func LogExecutionTimeContinuation(context *RequestContext, req *http.Request, resp http.ResponseWriter) ContinuationChain {
|
||
|
return func(success Continuation, _failure Continuation) ContinuationChain {
|
||
|
end := time.Now()
|
||
|
|
||
|
log.Println(context.Id, "took", end.Sub(context.Start))
|
||
|
|
||
|
return success(context, req, resp)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func HealthCheckContinuation(context *RequestContext, req *http.Request, resp http.ResponseWriter) ContinuationChain {
|
||
|
return func(success Continuation, _failure Continuation) ContinuationChain {
|
||
|
resp.WriteHeader(200)
|
||
|
resp.Write([]byte("healthy"))
|
||
|
return success(context, req, resp)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func FailurePassingContinuation(context *RequestContext, req *http.Request, resp http.ResponseWriter) ContinuationChain {
|
||
|
return func(_success Continuation, failure Continuation) ContinuationChain {
|
||
|
return failure(context, req, resp)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func IdContinuation(context *RequestContext, req *http.Request, resp http.ResponseWriter) ContinuationChain {
|
||
|
return func(success Continuation, _failure Continuation) ContinuationChain {
|
||
|
return success(context, req, resp)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func MakeServer(argv *args.Arguments, dbConn *sql.DB) *http.Server {
|
||
|
mux := http.NewServeMux()
|
||
|
|
||
|
fileServer := http.FileServer(http.Dir(argv.StaticPath))
|
||
|
mux.Handle("/static/", http.StripPrefix("/static/", fileServer))
|
||
|
|
||
|
makeRequestContext := func() *RequestContext {
|
||
|
return &RequestContext{
|
||
|
DBConn: dbConn,
|
||
|
Args: argv,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||
|
requestContext := makeRequestContext()
|
||
|
LogRequestContinuation(requestContext, r, w)(TemplateContinuation("home.html", nil, true), FailurePassingContinuation)(LogExecutionTimeContinuation, LogExecutionTimeContinuation)(IdContinuation, IdContinuation)
|
||
|
})
|
||
|
|
||
|
mux.HandleFunc("GET /api/health", func(w http.ResponseWriter, r *http.Request) {
|
||
|
requestContext := makeRequestContext()
|
||
|
LogRequestContinuation(requestContext, r, w)(HealthCheckContinuation, FailurePassingContinuation)(LogExecutionTimeContinuation, LogExecutionTimeContinuation)(IdContinuation, IdContinuation)
|
||
|
})
|
||
|
|
||
|
mux.HandleFunc("GET /{name}", func(w http.ResponseWriter, r *http.Request) {
|
||
|
requestContext := makeRequestContext()
|
||
|
name := r.PathValue("name")
|
||
|
LogRequestContinuation(requestContext, r, w)(TemplateContinuation(name+".html", nil, true), FailurePassingContinuation)(LogExecutionTimeContinuation, LogExecutionTimeContinuation)(IdContinuation, IdContinuation)
|
||
|
})
|
||
|
|
||
|
return &http.Server{
|
||
|
Addr: ":" + fmt.Sprint(argv.Port),
|
||
|
Handler: mux,
|
||
|
}
|
||
|
}
|