Detailed changes
@@ -55,6 +55,13 @@ type DBConfig struct {
SSLMode bool `env:"SSL_MODE" envDefault:"false"`
}
+// HTTPConfig is the HTTP server config.
+type HTTPConfig struct {
+ Enabled bool `env:"ENABLED" envDefault:"true"`
+ Port int `env:"PORT" envDefault:"8080"`
+ Domain string `env:"DOMAIN" envDefault:"localhost"` // used for go get
+}
+
// URL returns a database URL for the configuration.
func (d *DBConfig) URL() *url.URL {
switch d.Driver {
@@ -88,9 +95,10 @@ func (d *DBConfig) URL() *url.URL {
type Config struct {
Host string `env:"HOST" envDefault:"localhost"`
- SSH SSHConfig `env:"SSH" envPrefix:"SSH_"`
- Git GitConfig `env:"GIT" envPrefix:"GIT_"`
- Db DBConfig `env:"DB" envPrefix:"DB_"`
+ SSH SSHConfig `env:"SSH" envPrefix:"SSH_"`
+ Git GitConfig `env:"GIT" envPrefix:"GIT_"`
+ HTTP HTTPConfig `env:"HTTP" envPrefix:"HTTP_"`
+ Db DBConfig `env:"DB" envPrefix:"DB_"`
ServerName string `env:"SERVER_NAME" envDefault:"Soft Serve"`
AnonAccess proto.AccessLevel `env:"ANON_ACCESS" envDefault:"read-only"`
@@ -174,12 +182,12 @@ func DefaultConfig() *Config {
cfg.InitialAdminKeys[i] = pk
}
// init data path and db
- if err := os.MkdirAll(cfg.RepoPath(), 0755); err != nil {
+ if err := os.MkdirAll(cfg.RepoPath(), 0o755); err != nil {
log.Fatalln(err)
}
switch cfg.Db.Driver {
case "sqlite":
- if err := os.MkdirAll(filepath.Dir(cfg.DBPath()), 0755); err != nil {
+ if err := os.MkdirAll(filepath.Dir(cfg.DBPath()), 0o755); err != nil {
log.Fatalln(err)
}
db, err := sqlite.New(cfg.DBPath())
@@ -0,0 +1,50 @@
+package server
+
+import (
+ "html/template"
+ "log"
+ "net"
+ "net/http"
+ "strconv"
+ "strings"
+ "time"
+
+ "github.com/charmbracelet/soft-serve/server/config"
+)
+
+func newHTTPServer(cfg *config.Config) *http.Server {
+ r := http.NewServeMux()
+ r.HandleFunc("/", repoIndexHandler(cfg))
+ return &http.Server{
+ Addr: net.JoinHostPort(cfg.Host, strconv.Itoa(cfg.HTTP.Port)),
+ Handler: r,
+ ReadHeaderTimeout: time.Second * 10,
+ ReadTimeout: time.Second * 10,
+ WriteTimeout: time.Second * 10,
+ MaxHeaderBytes: http.DefaultMaxHeaderBytes,
+ }
+}
+
+var repoIndexHTMLTpl = template.Must(template.New("index").Parse(`<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta name="go-import" content="{{ .Config.HTTP.Domain }}/{{ .Repo }} git ssh://{{ .Config.Host }}:{{ .Config.SSH.Port }}/{{ .Repo }}">
+</head>
+</html>`))
+
+func repoIndexHandler(cfg *config.Config) func(w http.ResponseWriter, r *http.Request) {
+ return func(w http.ResponseWriter, r *http.Request) {
+ repo := strings.Split(strings.TrimPrefix(r.URL.Path, "/"), "/")[0]
+ log.Println("serving index for", repo)
+ if err := repoIndexHTMLTpl.Execute(w, struct {
+ Repo string
+ Config config.Config
+ }{
+ Repo: repo,
+ Config: *cfg,
+ }); err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+ }
+}
@@ -4,6 +4,7 @@ import (
"context"
"fmt"
"log"
+ "net/http"
"time"
cm "github.com/charmbracelet/soft-serve/server/cmd"
@@ -21,9 +22,10 @@ import (
// Server is the Soft Serve server.
type Server struct {
- SSHServer *ssh.Server
- GitServer *daemon.Daemon
- Config *config.Config
+ SSHServer *ssh.Server
+ GitServer *daemon.Daemon
+ HTTPServer *http.Server
+ Config *config.Config
}
// NewServer returns a new *ssh.Server configured to serve Soft Serve. The SSH
@@ -63,7 +65,6 @@ func NewServer(cfg *config.Config) *Server {
} else {
opts = append(opts, wish.WithHostKeyPath(cfg.PrivateKeyPath()))
}
- opts = append(opts)
sh, err := wish.NewServer(opts...)
if err != nil {
log.Fatalln(err)
@@ -82,6 +83,9 @@ func NewServer(cfg *config.Config) *Server {
}
s.GitServer = d
}
+ if cfg.HTTP.Enabled {
+ s.HTTPServer = newHTTPServer(cfg)
+ }
return s
}
@@ -97,6 +101,15 @@ func (s *Server) Start() error {
return nil
})
}
+ if s.Config.HTTP.Enabled {
+ errg.Go(func() error {
+ log.Printf("Starting HTTP server on %s:%d", s.Config.Host, s.Config.HTTP.Port)
+ if err := s.HTTPServer.ListenAndServe(); err != http.ErrServerClosed {
+ return err
+ }
+ return nil
+ })
+ }
errg.Go(func() error {
log.Printf("Starting SSH server on %s:%d", s.Config.Host, s.Config.SSH.Port)
if err := s.SSHServer.ListenAndServe(); err != ssh.ErrServerClosed {
@@ -115,6 +128,11 @@ func (s *Server) Shutdown(ctx context.Context) error {
return s.GitServer.Shutdown(ctx)
})
}
+ if s.Config.HTTP.Enabled {
+ errg.Go(func() error {
+ return s.HTTPServer.Shutdown(ctx)
+ })
+ }
errg.Go(func() error {
return s.SSHServer.Shutdown(ctx)
})
@@ -132,5 +150,10 @@ func (s *Server) Close() error {
return s.GitServer.Close()
})
}
+ if s.Config.HTTP.Enabled {
+ errg.Go(func() error {
+ return s.HTTPServer.Close()
+ })
+ }
return errg.Wait()
}