2022-04-25 12:23:57 -05:00

91 lines
2.4 KiB
Go

package server
import (
"context"
"net"
"net/http"
//"strings"
"time"
//assetfs "github.com/elazarl/go-bindata-assetfs"
// "github.com/hashicorp/vagrant/internal/server/gen/vagrant_server"
"github.com/improbable-eng/grpc-web/go/grpcweb"
"github.com/oklog/run"
)
// httpInit initializes the HTTP server and adds it to the run group.
func httpInit(group *run.Group, opts *options) error {
log := opts.Logger.Named("http")
if opts.HTTPListener == nil {
log.Info("HTTP listener not specified, HTTP API is disabled")
return nil
}
// Wrap the grpc server so that it is grpc-web compatible
grpcWrapped := grpcweb.WrapServer(opts.grpcServer,
grpcweb.WithCorsForRegisteredEndpointsOnly(false),
grpcweb.WithOriginFunc(func(string) bool { return true }),
grpcweb.WithAllowNonRootResource(true),
)
// TODO: ember stuff
// uifs := http.FileServer(&assetfs.AssetFS{
// Asset: vagrant_server.Asset,
// AssetDir: vagrant_server.AssetDir,
// AssetInfo: vagrant_server.AssetInfo,
// Prefix: "ui/dist",
// Fallback: "index.html",
// })
// If the path has a grpc prefix we assume it's a GRPC gateway request,
// otherwise fall back to serving the UI from the filesystem
rootHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// if strings.HasPrefix(r.URL.Path, "/grpc") {
grpcWrapped.ServeHTTP(w, r)
// } else if opts.BrowserUIEnabled {
// uifs.ServeHTTP(w, r)
// }
})
// Create our http server
httpSrv := &http.Server{
ReadHeaderTimeout: 5 * time.Second,
IdleTimeout: 120 * time.Second,
Handler: httpLogHandler(rootHandler, log),
BaseContext: func(net.Listener) context.Context {
return opts.Context
},
}
// Add our gRPC server to the run group
group.Add(func() error {
// Serve traffic
ln := opts.HTTPListener
log.Info("starting HTTP server", "addr", ln.Addr().String())
return httpSrv.Serve(ln)
}, func(err error) {
ctx, cancelFunc := context.WithCancel(context.Background())
defer cancelFunc()
// Graceful in a goroutine so we can timeout
gracefulCh := make(chan struct{})
go func() {
defer close(gracefulCh)
log.Info("shutting down HTTP server")
httpSrv.Shutdown(ctx)
}()
select {
case <-gracefulCh:
// After a timeout we just forcibly exit. Our HTTP endpoints should
// be fairly quick and their operations are atomic so we just kill
// the connections after a few seconds.
case <-time.After(2 * time.Second):
cancelFunc()
}
})
return nil
}