blob: a7f3e54a9920fbf23f23eb7cb14955d1c548bd56 [file] [log] [blame]
Serge Bazanskia7674672021-05-30 21:09:34 +00001package main
2
3import (
4 "flag"
5 "fmt"
6 "mime"
7 "net/http"
Serge Bazanski1f062302021-06-01 22:24:34 +00008 "regexp"
Serge Bazanskia7674672021-05-30 21:09:34 +00009 "strings"
Serge Bazanski3c9092a2021-05-30 23:15:20 +000010 "sync"
Serge Bazanskia7674672021-05-30 21:09:34 +000011
12 "code.hackerspace.pl/hscloud/go/mirko"
13 "github.com/golang/glog"
14
15 "code.hackerspace.pl/hscloud/hswaw/site/static"
16)
17
18var (
19 flagSitePublic string
20)
21
22type service struct {
Serge Bazanski3c9092a2021-05-30 23:15:20 +000023 // feeds is a map from atom feed name to atom feed. This is updated by a
24 // background worker.
25 feeds map[string]*atomFeed
26 // feedsMu locks the feeds field.
27 feedsMu sync.RWMutex
Serge Bazanskia7674672021-05-30 21:09:34 +000028}
29
30func main() {
31 flag.StringVar(&flagSitePublic, "site_public", "0.0.0.0:8080", "Address at which to serve public HTTP requests")
32 flag.Parse()
33
34 mi := mirko.New()
35 if err := mi.Listen(); err != nil {
36 glog.Exitf("Listen failed: %v", err)
37 }
38
39 s := &service{}
Serge Bazanski3c9092a2021-05-30 23:15:20 +000040 go s.feedWorker(mi.Context())
Serge Bazanskia7674672021-05-30 21:09:34 +000041
42 mux := http.NewServeMux()
43 s.registerHTTP(mux)
44
45 go func() {
46 glog.Infof("Listening for public HTTP at %v", flagSitePublic)
47 if err := http.ListenAndServe(flagSitePublic, mux); err != nil {
48 glog.Exit(err)
49 }
50 }()
51
52 if err := mi.Serve(); err != nil {
53 glog.Exitf("Serve failed: %v", err)
54 }
55
56 <-mi.Done()
57}
58
Serge Bazanski1f062302021-06-01 22:24:34 +000059var (
60 // staticRoutes define the resolution of static file paths into assets
61 // built into //hswaw/site/static, whose names correspond to their origin
62 // within the Bazel workspace.
63 // The regexp will be matched against the normalized within the URL. If it
64 // matches, its first group/submatch will be used to format the string
65 // corresponding to this regexp, and that string will be then used to
66 // retrieve a path embedded within //hswaw/site/static:static
67 // (go_embed_data).
68 //
69 // To see paths available within that go_embed_data, you can do:
70 // $ bazel build //hswaw/site/static:static
71 // $ grep -A100 'Data =' bazel-bin/hswaw/site/static/static.go
72 staticRoutes = map[*regexp.Regexp]string{
73 regexp.MustCompile(`^static/site/(.+)$`): "hswaw/site/static/%s",
74 regexp.MustCompile(`^static/leaflet/(.+)$`): "external/com_npmjs_leaflet/package/dist/%s",
75 }
76)
77
78// handleHTTPStatic uses staticRoutes to serve static files embedded within
79// //hswaw/site/static.
Serge Bazanskia7674672021-05-30 21:09:34 +000080func (s *service) handleHTTPStatic(w http.ResponseWriter, r *http.Request) {
81 path := strings.TrimPrefix(r.URL.Path, "/")
Serge Bazanski1f062302021-06-01 22:24:34 +000082 for from, to := range staticRoutes {
83 match := from.FindStringSubmatch(path)
84 if match == nil {
85 continue
86 }
87 to := fmt.Sprintf(to, match[1])
88 data, ok := static.Data[to]
89 if !ok {
90 continue
91 }
Serge Bazanskia7674672021-05-30 21:09:34 +000092 parts := strings.Split(path, ".")
93 ext := fmt.Sprintf(".%s", parts[len(parts)-1])
94 t := mime.TypeByExtension(ext)
95 w.Header().Set("Content-Type", t)
96 w.Write(data)
Serge Bazanski1f062302021-06-01 22:24:34 +000097 return
98
Serge Bazanskia7674672021-05-30 21:09:34 +000099 }
Serge Bazanski1f062302021-06-01 22:24:34 +0000100 http.NotFound(w, r)
Serge Bazanskia7674672021-05-30 21:09:34 +0000101}
102
103func (s *service) registerHTTP(mux *http.ServeMux) {
104 mux.HandleFunc("/static/", s.handleHTTPStatic)
Serge Bazanski4d7b2f02021-05-31 22:33:51 +0000105 mux.HandleFunc("/", s.handleIndex)
Serge Bazanskia7674672021-05-30 21:09:34 +0000106}