vanity/cmd/vanity-server/server.go

76 lines
1.9 KiB
Go

package main
import (
"context"
"errors"
"flag"
"fmt"
"net/http"
"os"
"path/filepath"
"go.jolheiser.com/vanity/server/database"
"go.jolheiser.com/vanity/server/router"
"github.com/peterbourgon/ff/v3"
"github.com/peterbourgon/ff/v3/ffcli"
"github.com/peterbourgon/ff/v3/fftoml"
"github.com/rs/zerolog/log"
)
func New() *ffcli.Command {
fs := flag.NewFlagSet("vanity", flag.ExitOnError)
portFlag := fs.Int("port", 3333, "Port to run the vanity server on")
domainFlag := fs.String("domain", "", "The Go module domain (e.g. go.jolheiser.com)")
tokenFlag := fs.String("token", "", "vanity auth token to use")
dbFlag := fs.String("database", dbPath(), "The path to the database")
cmd := &ffcli.Command{
Name: "vanity",
ShortUsage: "vanity",
ShortHelp: "Vanity Server",
LongHelp: "Vanity Server to serve the Go module vanity domain",
FlagSet: fs,
Options: []ff.Option{
ff.WithEnvVarPrefix("VANITY"),
ff.WithAllowMissingConfigFile(true),
ff.WithConfigFileFlag("config"),
ff.WithConfigFileParser(fftoml.New().Parse),
},
Exec: server(portFlag, domainFlag, tokenFlag, dbFlag),
}
return cmd
}
func server(port *int, domain, token, dbPath *string) func(context.Context, []string) error {
return func(ctx context.Context, args []string) error {
if *token == "" || *domain == "" {
return errors.New("vanity server requires --token and --domain")
}
db, err := database.Load(*dbPath)
if err != nil {
log.Fatal().Msgf("could not load database at %s: %v", *dbPath, err)
}
log.Info().Msgf("Running vanity server at http://localhost:%d", *port)
if err := http.ListenAndServe(fmt.Sprintf(":%d", *port), router.New(*token, *domain, db)); err != nil {
return err
}
return nil
}
}
func dbPath() string {
fn := "vanity.db"
home, err := os.UserHomeDir()
if err != nil {
bin, err := os.Executable()
if err != nil {
return fn
}
return filepath.Join(filepath.Dir(bin), fn)
}
return filepath.Join(home, fn)
}