vain/cmd/vaind/main.go

160 lines
3.7 KiB
Go

/*
vaind, a webserver for hosting go get vanity urls.
The go get command searches for the following header when searching for
packages:
<meta name="go-import" content="import-prefix vcs repo-root">
this is simply a service for aggregating a collection of prefix, vcs, and
repo-root tuples, and serving the appropriate header over http. For more
information please refer to the documentation for the go tool found at
https://golang.org/cmd/go/#hdr-Remote_import_paths
API
Assume an instance of vaind at example.org. In order to add a package
example.org/foo that points at bitbucket.org/example/foo (a mercurial
repository) POST the following json object:
{
"vcs": "mercurial",
"repo": "https://bitbucket.org/example/foo"
}
to https://example.org/foo.
Doing so, then visiting https://example.org/foo?go-get=1 will yield a header
that looks like:
<meta name="go-import" content="example.org/foo hg https://bitbucket.org/foo">
The json object sent to server can have two fields: "repo" and "vcs". "repo" is
required; leaving off the "vcs" member defaults to "git".
In order to delete a package:
DELETE /<package name>
*/
package main
import (
"fmt"
"log"
"net/http"
"os"
"os/signal"
"syscall"
"time"
"mcquay.me/vain"
"github.com/kelseyhightower/envconfig"
)
const usage = "vaind <dbname>"
type config struct {
Port int
Insecure bool
Cert string
Key string
Static string
EmailTimeout time.Duration `envconfig:"email_timeout"`
SMTPHost string `envconfig:"smtp_host"`
SMTPPort int `envconfig:"smtp_port"`
From string
}
func main() {
log.SetFlags(log.Lshortfile)
if len(os.Args) < 2 {
fmt.Fprintf(os.Stderr, "%s\n", usage)
os.Exit(1)
}
c := &config{
Port: 4040,
EmailTimeout: 5 * time.Minute,
SMTPPort: 25,
}
if err := envconfig.Process("vain", c); err != nil {
fmt.Fprintf(os.Stderr, "problem processing environment: %v", err)
os.Exit(1)
}
if len(os.Args) > 1 {
switch os.Args[1] {
case "env", "e":
fmt.Printf("VAIN_PORT: %v\n", c.Port)
fmt.Printf("VAIN_INSECURE: %v\n", c.Insecure)
fmt.Printf("VAIN_CERT: %v\n", c.Cert)
fmt.Printf("VAIN_KEY: %v\n", c.Key)
fmt.Printf("VAIN_STATIC: %v\n", c.Static)
fmt.Printf("VAIN_EMAIL_TIMEOUT: %v\n", c.EmailTimeout)
fmt.Printf("VAIN_SMTP_HOST: %v\n", c.SMTPHost)
fmt.Printf("VAIN_SMTP_PORT: %v\n", c.SMTPPort)
fmt.Printf("VAIN_FROM: %v\n", c.From)
os.Exit(0)
case "help", "h":
fmt.Printf("%s\n", usage)
os.Exit(0)
}
}
log.Printf("%+v", c)
db, err := vain.NewMemDB(os.Args[1])
if err != nil {
fmt.Fprintf(os.Stderr, "couldn't open db: %v\n", err)
os.Exit(1)
}
sigs := make(chan os.Signal)
signal.Notify(sigs, os.Interrupt, syscall.SIGTERM)
go func() {
s := <-sigs
log.Printf("signal: %+v", s)
if err := db.Sync(); err != nil {
log.Printf("problem syncing db to disk: %+v", err)
os.Exit(1)
}
os.Exit(0)
}()
m, err := vain.NewMail(c.From, c.SMTPHost, c.SMTPPort)
if err != nil {
fmt.Fprintf(os.Stderr, "problem initializing mailer: %v", err)
os.Exit(1)
}
hostname := "localhost"
if hn, err := os.Hostname(); err != nil {
log.Printf("problem getting hostname: %v", err)
} else {
hostname = hn
}
log.Printf("serving at: http://%s:%d/", hostname, c.Port)
sm := http.NewServeMux()
vain.NewServer(sm, db, m, c.Static, c.EmailTimeout, c.Insecure)
addr := fmt.Sprintf(":%d", c.Port)
if c.Cert == "" || c.Key == "" {
log.Printf("INSECURE MODE")
if err := http.ListenAndServe(addr, sm); err != nil {
log.Printf("problem with http server: %v", err)
os.Exit(1)
}
} else {
if err := http.ListenAndServeTLS(addr, c.Cert, c.Key, sm); err != nil {
log.Printf("problem with http server: %v", err)
os.Exit(1)
}
}
}