forked from hswaw/hscloud
radex
a28fa4d7f2
Change-Id: Id64cccadcd1e109035ed09f62086772fa615dd72 Reviewed-on: https://gerrit.hackerspace.pl/c/hscloud/+/1690 Reviewed-by: q3k <q3k@hackerspace.pl> Reviewed-by: radex <radex@hackerspace.pl>
125 lines
3.3 KiB
Go
125 lines
3.3 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"flag"
|
|
"fmt"
|
|
"math/rand"
|
|
"mime"
|
|
"net/http"
|
|
"regexp"
|
|
"strings"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/golang/glog"
|
|
|
|
"code.hackerspace.pl/hscloud/hswaw/site/calendar"
|
|
"code.hackerspace.pl/hscloud/hswaw/site/static"
|
|
)
|
|
|
|
var (
|
|
flagSitePublic string
|
|
)
|
|
|
|
type service struct {
|
|
// feeds is a map from atom feed name to atom feed. This is updated by a
|
|
// background worker.
|
|
feeds map[string]*atomFeed
|
|
// feedsMu locks the feeds field.
|
|
feedsMu sync.RWMutex
|
|
|
|
// events is a list of upcoming events, sorted so the first event is the
|
|
// one that will happen the soonests.
|
|
events []*calendar.UpcomingEvent
|
|
// eventsMu locks the events field.
|
|
eventsMu sync.RWMutex
|
|
}
|
|
|
|
func main() {
|
|
flag.StringVar(&flagSitePublic, "site_public", "0.0.0.0:8080", "Address at which to serve public HTTP requests")
|
|
flag.Parse()
|
|
|
|
rand.Seed(time.Now().UnixNano())
|
|
|
|
// TODO(q3k): use sigint-interruptible context
|
|
ctx := context.Background()
|
|
|
|
s := &service{}
|
|
go s.feedWorker(ctx)
|
|
go s.eventsWorker(ctx)
|
|
|
|
mux := http.NewServeMux()
|
|
s.registerHTTP(mux)
|
|
|
|
go func() {
|
|
glog.Infof("Listening for public HTTP at %v", flagSitePublic)
|
|
if err := http.ListenAndServe(flagSitePublic, mux); err != nil {
|
|
glog.Exit(err)
|
|
}
|
|
}()
|
|
|
|
<-ctx.Done()
|
|
}
|
|
|
|
var (
|
|
// staticRoutes define the resolution of static file paths into assets
|
|
// built into //hswaw/site/static, whose names correspond to their origin
|
|
// within the Bazel workspace.
|
|
// The regexp will be matched against the normalized within the URL. If it
|
|
// matches, its first group/submatch will be used to format the string
|
|
// corresponding to this regexp, and that string will be then used to
|
|
// retrieve a path embedded within //hswaw/site/static:static
|
|
// (go_embed_data).
|
|
//
|
|
// To see paths available within that go_embed_data, you can do:
|
|
// $ bazel build //hswaw/site/static:static
|
|
// $ grep -A100 'Data =' bazel-bin/hswaw/site/static/static.go
|
|
staticRoutes = map[*regexp.Regexp]string{
|
|
regexp.MustCompile(`^static/site/(.+)$`): "hswaw/site/static/%s",
|
|
regexp.MustCompile(`^static/leaflet/(.+)$`): "external/com_npmjs_leaflet/package/dist/%s",
|
|
regexp.MustCompile(`^static/gfonts/([a-z]+)/([0-9]+)\.ttf$`): "external/com_gstatic_fonts_%s_%s/file/font.ttf",
|
|
}
|
|
)
|
|
|
|
// handleHTTPStatic uses staticRoutes to serve static files embedded within
|
|
// //hswaw/site/static.
|
|
func (s *service) handleHTTPStatic(w http.ResponseWriter, r *http.Request) {
|
|
path := strings.TrimPrefix(r.URL.Path, "/")
|
|
for from, to := range staticRoutes {
|
|
match := from.FindStringSubmatch(path)
|
|
if match == nil {
|
|
continue
|
|
}
|
|
var args []interface{}
|
|
for _, m := range match[1:] {
|
|
args = append(args, m)
|
|
}
|
|
if len(args) != strings.Count(to, "%s") {
|
|
http.NotFound(w, r)
|
|
return
|
|
}
|
|
to := fmt.Sprintf(to, args...)
|
|
data, ok := static.Data[to]
|
|
if !ok {
|
|
continue
|
|
}
|
|
parts := strings.Split(path, ".")
|
|
ext := fmt.Sprintf(".%s", parts[len(parts)-1])
|
|
t := mime.TypeByExtension(ext)
|
|
w.Header().Set("Content-Type", t)
|
|
w.Write(data)
|
|
return
|
|
|
|
}
|
|
http.NotFound(w, r)
|
|
}
|
|
|
|
func (s *service) registerHTTP(mux *http.ServeMux) {
|
|
mux.HandleFunc("/static/", s.handleHTTPStatic)
|
|
mux.HandleFunc("/spaceapi", s.handleSpaceAPI)
|
|
mux.HandleFunc("/events.json", s.handleJSONEvents)
|
|
mux.HandleFunc("/event/", s.handleEvent)
|
|
mux.HandleFunc("/robots.txt", s.handleRobotsTxt)
|
|
mux.HandleFunc("/", s.handleIndex)
|
|
}
|