go-recipe-book/pkg/web/server.go
Alessio 10cc9342b1
Some checks failed
Build / release (push) Blocked by required conditions
Build / build (push) Has been cancelled
Add beginning of web package
2024-11-18 16:25:39 -08:00

96 lines
2.3 KiB
Go

package web
import (
"crypto/tls"
"log"
"net/http"
"os"
"os/exec"
"runtime"
"strings"
"time"
pkg_db "recipe_book/pkg/db"
)
type Application struct {
accessLog *log.Logger
traceLog *log.Logger
InfoLog *log.Logger
ErrorLog *log.Logger
Middlewares []Middleware
DB pkg_db.DB
}
func NewApp(db pkg_db.DB) Application {
ret := Application{
accessLog: log.New(os.Stdout, "ACCESS\t", log.Ldate|log.Ltime),
traceLog: log.New(os.Stdout, "TRACE\t", log.Ldate|log.Ltime),
InfoLog: log.New(os.Stdout, "INFO\t", log.Ldate|log.Ltime),
ErrorLog: log.New(os.Stderr, "ERROR\t", log.Ldate|log.Ltime|log.Lshortfile),
DB: db,
}
ret.Middlewares = []Middleware{
secureHeaders,
ret.logRequest,
ret.recoverPanic,
}
return ret
}
// Manual router implementation.
// I don't like the weird matching behavior of http.ServeMux, and it's not hard to write by hand.
func (app *Application) ServeHTTP(w http.ResponseWriter, r *http.Request) {
app.traceLog.Printf("base handler: %s", r.URL.Path)
parts := strings.Split(r.URL.Path, "/")[1:]
switch parts[0] {
case "static":
http.StripPrefix("/static", http.HandlerFunc(app.ServeStatic)).ServeHTTP(w, r)
case "ingredients":
http.StripPrefix("/ingredients", http.HandlerFunc(app.Ingredients)).ServeHTTP(w, r)
case "recipes":
http.StripPrefix("/recipes", http.HandlerFunc(app.Recipes)).ServeHTTP(w, r)
default:
app.error_404(w, r)
return
}
}
func (app *Application) Run(address string, should_auto_open bool) {
srv := &http.Server{
Addr: address,
ErrorLog: app.ErrorLog,
Handler: app.WithMiddlewares(),
TLSConfig: &tls.Config{
CurvePreferences: []tls.CurveID{tls.X25519, tls.CurveP256},
},
IdleTimeout: time.Minute,
ReadTimeout: 5 * time.Second,
WriteTimeout: 10 * time.Second,
}
app.InfoLog.Printf("Starting server on %s", address)
if should_auto_open {
go func(url string) {
var cmd *exec.Cmd
switch runtime.GOOS {
case "darwin": // macOS
cmd = exec.Command("open", url)
case "windows":
cmd = exec.Command("cmd", "/c", "start", url)
default: // Linux and others
cmd = exec.Command("xdg-open", url)
}
if err := cmd.Run(); err != nil {
log.Printf("Failed to open homepage: %s", err.Error())
}
}("http://" + address)
}
err := srv.ListenAndServe()
app.ErrorLog.Fatal(err)
}