102 lines
2.5 KiB
Go
102 lines
2.5 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"github.com/go-chi/chi"
|
|
"github.com/go-chi/valve"
|
|
"github.com/rs/zerolog/log"
|
|
"media-roller/src/media"
|
|
"net/http"
|
|
"os"
|
|
"os/signal"
|
|
"path"
|
|
"path/filepath"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
func main() {
|
|
// Setup routes
|
|
router := chi.NewRouter()
|
|
router.Route("/", func(r chi.Router) {
|
|
router.Get("/", media.Index)
|
|
router.Get("/fetch", media.FetchMedia)
|
|
router.Get("/api/download", media.FetchMediaApi)
|
|
router.Get("/download", media.ServeMedia)
|
|
})
|
|
fileServer(router, "/static", "static/")
|
|
|
|
// Print out all routes
|
|
walkFunc := func(method string, route string, handler http.Handler, middlewares ...func(http.Handler) http.Handler) error {
|
|
log.Info().Msgf("%s %s", method, route)
|
|
return nil
|
|
}
|
|
// Panic if there is an error
|
|
if err := chi.Walk(router, walkFunc); err != nil {
|
|
log.Panic().Msgf("%s\n", err.Error())
|
|
}
|
|
|
|
valv := valve.New()
|
|
baseCtx := valv.Context()
|
|
srv := http.Server{Addr: ":3000", Handler: chi.ServerBaseContext(baseCtx, router)}
|
|
|
|
// Create a shutdown hook for graceful shutdowns
|
|
c := make(chan os.Signal, 1)
|
|
signal.Notify(c, os.Interrupt)
|
|
go func() {
|
|
for range c {
|
|
// sig is a ^C, handle it
|
|
log.Info().Msgf("Shutting down...")
|
|
|
|
// first valv
|
|
_ = valv.Shutdown(20 * time.Second)
|
|
|
|
// create context with timeout
|
|
ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
|
|
defer cancel()
|
|
|
|
// start http shutdown
|
|
_ = srv.Shutdown(ctx)
|
|
|
|
// verify, in worst case call cancel via defer
|
|
select {
|
|
case <-time.After(21 * time.Second):
|
|
log.Error().Msgf("Not all connections done")
|
|
case <-ctx.Done():
|
|
}
|
|
}
|
|
}()
|
|
|
|
err := srv.ListenAndServe()
|
|
if err != nil {
|
|
log.Info().Msg(err.Error())
|
|
}
|
|
log.Info().Msgf("Shutdown complete")
|
|
}
|
|
|
|
func fileServer(r chi.Router, public string, static string) {
|
|
if strings.ContainsAny(public, "{}*") {
|
|
panic("FileServer does not permit URL parameters.")
|
|
}
|
|
|
|
root, _ := filepath.Abs(static)
|
|
if _, err := os.Stat(root); os.IsNotExist(err) {
|
|
panic("Static Documents Directory Not Found")
|
|
}
|
|
|
|
fs := http.StripPrefix(public, http.FileServer(http.Dir(root)))
|
|
|
|
if public != "/" && public[len(public)-1] != '/' {
|
|
r.Get(public, http.RedirectHandler(public+"/", 301).ServeHTTP)
|
|
public += "/"
|
|
}
|
|
|
|
r.Get(public+"*", func(w http.ResponseWriter, r *http.Request) {
|
|
file := strings.Replace(r.RequestURI, public, "/", 1)
|
|
if _, err := os.Stat(root + file); os.IsNotExist(err) {
|
|
http.ServeFile(w, r, path.Join(root, "index.html"))
|
|
return
|
|
}
|
|
fs.ServeHTTP(w, r)
|
|
})
|
|
}
|