cdn/main.go

119 lines
2.6 KiB
Go
Raw Normal View History

package main
import (
"context"
"flag"
"fmt"
"log"
"net/http"
"os"
"path/filepath"
2023-11-19 18:00:00 +01:00
"strings"
"time"
"golang.org/x/sync/errgroup"
)
var (
ctx = context.Background()
previewPort = "8080"
)
// genListingPages generates listing pages recursively inside provided directory
2023-11-19 18:00:00 +01:00
func genListingPages(path, prefix string) error {
entries, err := os.ReadDir(path)
if err != nil {
return err
}
indexFile, err := os.Create(filepath.Join(path, "index.html"))
if err != nil {
return err
}
2023-11-19 18:00:00 +01:00
trimedPath := strings.TrimPrefix(path, prefix)
if err := listingPage(strings.TrimPrefix(trimedPath, "/"), entries).Render(ctx, indexFile); err != nil {
return err
}
// Goroutines are cheap, so just spawn them needlessly \^-^/
errGroup := new(errgroup.Group)
for _, entry := range entries {
entry := entry
if entry.IsDir() {
errGroup.Go(func() error {
2023-11-19 18:00:00 +01:00
return genListingPages(filepath.Join(path, entry.Name()), prefix)
})
}
}
return errGroup.Wait()
}
// preview Previews the website at specified root directory on localhost:<port>
func preview(root, port string) error {
2023-11-19 18:00:00 +01:00
http.Handle("/", http.FileServer(http.Dir(root)))
fmt.Println("Serving the preview webpage at http://localhost:" + port)
srv := &http.Server{
Addr: ":" + port,
ReadTimeout: 5 * time.Second,
WriteTimeout: 10 * time.Second,
}
return srv.ListenAndServe()
}
// generate generates index.html files for the root directory
func generate(root string) error {
// NOTE: it also generate one for the root directory. We'll override this file later
2023-11-19 18:00:00 +01:00
if err := genListingPages(root, root); err != nil {
return err
}
// Render the home page to override the written listing page at root
homePage, err := os.Create(filepath.Join(root, "index.html"))
if err != nil {
return err
}
return indexPage().Render(ctx, homePage)
}
func main() {
genFlag := flag.Bool("gen", false, "Generate index files")
previewFlag := flag.Bool("preview", false, "Preview the built website")
flag.Usage = func() {
fmt.Printf(`Usage: go run *.go [OPTIONS] DIR
Arguments:
DIR
Path to the directory containing the source files
Options:
`)
flag.PrintDefaults()
}
flag.Parse()
// The root directory argument is required
if len(flag.Args()) != 1 {
log.Fatal("[ERROR] exactly 1 argument DIR is required")
}
2023-11-19 18:00:00 +01:00
// Specify the starting directory, for consistency
rootDir, err := filepath.Abs(flag.Arg(0))
if err != nil {
log.Fatal(err)
}
if *genFlag {
if err := generate(rootDir); err != nil {
log.Fatalf("[ERROR] %v", err)
}
}
// Only preview after things are generated
if *previewFlag {
if err := preview(rootDir, previewPort); err != nil {
log.Fatalf("[ERROR] %v", err)
}
}
}