An experimental IndieWeb site built in Go.
at 33290a94de2d47494661cd925883dea75b75a387 90 lines 2.1 kB view raw
1package main 2 3//go:generate templ generate 4//go:generate deno run --allow-all npm:tailwindcss -i config/main.css -o static/styles.css -c config/tailwind.config.js --minify 5 6import ( 7 "os" 8 "time" 9 10 "log" 11 "net/http" 12 "strconv" 13 14 "github.com/puregarlic/space/handlers" 15 "github.com/puregarlic/space/storage" 16 17 "github.com/go-chi/chi/v5" 18 "github.com/go-chi/chi/v5/middleware" 19 "github.com/go-chi/cors" 20 "github.com/go-chi/httprate" 21 22 "go.hacdias.com/indielib/indieauth" 23 24 _ "github.com/joho/godotenv/autoload" 25) 26 27func main() { 28 port, profileURL := validateRuntimeConfiguration() 29 defer storage.CleanupAuthCache() 30 31 r := chi.NewRouter() 32 33 r.Use(middleware.RequestID) 34 r.Use(middleware.RealIP) 35 r.Use(middleware.Logger) 36 r.Use(middleware.Recoverer) 37 r.Use(httprate.LimitByIP(100, 1*time.Minute)) 38 39 // CORS be enabled for browser-based agents to fetch `rel` elements. 40 // We'll enable it just on the root route since it should be used as the profile URL 41 r.With(cors.AllowAll().Handler).Get("/", handlers.ServeHomePage) 42 43 // Content pages 44 r.Get("/posts/{slug}", handlers.ServePostPage) 45 46 // Static asset handlers 47 r.Get("/media/*", handlers.ServeMedia) 48 r.Get("/static/*", http.StripPrefix( 49 "/static", 50 http.FileServer(http.Dir("static")), 51 ).ServeHTTP) 52 53 // Service handlers 54 handlers.AttachIndieAuth(r, "/authorization", profileURL) 55 handlers.AttachMicropub(r, "/micropub", profileURL) 56 57 // Start it! 58 log.Printf("Listening on http://localhost:%d", port) 59 log.Printf("Listening on %s", profileURL) 60 if err := http.ListenAndServe(":"+strconv.Itoa(port), r); err != nil { 61 log.Fatal(err) 62 } 63} 64 65func validateRuntimeConfiguration() (portNumber int, profileURL string) { 66 var port int 67 if portStr, ok := os.LookupEnv("PORT"); !ok { 68 port = 80 69 } else { 70 portInt, err := strconv.Atoi(portStr) 71 if err != nil { 72 log.Fatal(err) 73 } 74 75 port = portInt 76 } 77 78 profileURL, ok := os.LookupEnv("PROFILE_URL") 79 if !ok { 80 profileURL = "http://localhost/" 81 } 82 83 // Validate the given Client ID before starting the HTTP server. 84 err := indieauth.IsValidProfileURL(profileURL) 85 if err != nil { 86 log.Fatal(err) 87 } 88 89 return port, profileURL 90}