diff options
author | Alexander Kiryukhin <a.kiryukhin@mail.ru> | 2022-03-24 23:25:02 +0300 |
---|---|---|
committer | Alexander Kiryukhin <a.kiryukhin@mail.ru> | 2022-03-24 23:25:02 +0300 |
commit | cc3ae00bbbe3bd0e04d1821e4bb54a7d8545d0a3 (patch) | |
tree | c17e0f623c038f35ff191572717213d6374da75c /main.go |
initial
Diffstat (limited to 'main.go')
-rw-r--r-- | main.go | 112 |
1 files changed, 112 insertions, 0 deletions
@@ -0,0 +1,112 @@ +package main + +import ( + "context" + "encoding/json" + "html/template" + "log" + "net/http" + "os" + "os/signal" + "path/filepath" + "strings" + + "github.com/go-chi/chi/v5" + "github.com/go-chi/chi/v5/middleware" +) + +var ( + templates = template.Must(template.ParseGlob("./tpl/*.gohtml")) + packages = Packages{} +) + +func main() { + addr := os.Getenv("ADDR") + if addr == "" { + addr = ":8080" + } + ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, os.Kill) + defer cancel() + + cfg := &Config{} + + fp, err := os.Open("./config.json") + if err != nil { + log.Fatal(err) + } + if err := json.NewDecoder(fp).Decode(cfg); err != nil { + log.Fatal(err) + } + + r := chi.NewRouter() + + r.Use(middleware.RequestID) + r.Use(middleware.StripSlashes) + r.Use(middleware.RealIP) + r.Use(middleware.Logger) + r.Use(middleware.Recoverer) + + r.Get("/", func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + templates.ExecuteTemplate(w, "index.gohtml", indexRenderContext{ + Title: cfg.Title, + Packages: cfg.Packages, + Host: cfg.Host, + Doc: "//pkg.go.dev/", + }) + }) + + r.Get("/{pkg}", func(w http.ResponseWriter, r *http.Request) { + pkgID := chi.URLParam(r, "pkg") + pkg, ok := (*cfg.Packages)[pkgID] + if !ok { + w.WriteHeader(http.StatusNotFound) + return + } + w.WriteHeader(http.StatusOK) + templates.ExecuteTemplate(w, "package.gohtml", pageRenderContext{ + Title: cfg.Title, + Package: &pkg, + Host: cfg.Host, + Doc: "//pkg.go.dev/", + }) + }) + + workDir, _ := os.Getwd() + filesDir := http.Dir(filepath.Join(workDir, "static")) + FileServer(r, "/static", filesDir) + + srv := &http.Server{ + Handler: r, + Addr: addr, + } + go func() { + <-ctx.Done() + srv.Shutdown(context.Background()) + }() + log.Println("Start at", addr) + if err := srv.ListenAndServe(); err != http.ErrServerClosed { + log.Fatal(err) + } +} + +// FileServer conveniently sets up a http.FileServer handler to serve +// static files from a http.FileSystem. +func FileServer(r chi.Router, path string, root http.FileSystem) { + if strings.ContainsAny(path, "{}*") { + panic("FileServer does not permit any URL parameters.") + } + + if path != "/" && path[len(path)-1] != '/' { + r.Get(path, http.RedirectHandler(path+"/", 301).ServeHTTP) + path += "/" + } + path += "*" + + r.Get(path, func(w http.ResponseWriter, r *http.Request) { + rctx := chi.RouteContext(r.Context()) + pathPrefix := strings.TrimSuffix(rctx.RoutePattern(), "/*") + fs := http.StripPrefix(pathPrefix, http.FileServer(root)) + fs.ServeHTTP(w, r) + }) +} |