summaryrefslogtreecommitdiff
path: root/main.go
diff options
context:
space:
mode:
authorAlexander Kiryukhin <a.kiryukhin@mail.ru>2022-03-24 23:25:02 +0300
committerAlexander Kiryukhin <a.kiryukhin@mail.ru>2022-03-24 23:25:02 +0300
commitcc3ae00bbbe3bd0e04d1821e4bb54a7d8545d0a3 (patch)
treec17e0f623c038f35ff191572717213d6374da75c /main.go
initial
Diffstat (limited to 'main.go')
-rw-r--r--main.go112
1 files changed, 112 insertions, 0 deletions
diff --git a/main.go b/main.go
new file mode 100644
index 0000000..d8e7015
--- /dev/null
+++ b/main.go
@@ -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)
+ })
+}