94 lines
2.6 KiB
Go
94 lines
2.6 KiB
Go
package server
|
|
|
|
import (
|
|
"net/http"
|
|
"path/filepath"
|
|
|
|
"git.netflux.io/rob/clipper/config"
|
|
"git.netflux.io/rob/clipper/filestore"
|
|
"github.com/gorilla/mux"
|
|
"github.com/improbable-eng/grpc-web/go/grpcweb"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
type httpHandler struct {
|
|
grpcHandler *grpcweb.WrappedGrpcServer
|
|
router http.Handler
|
|
mediaSetService MediaSetService
|
|
logger *zap.SugaredLogger
|
|
}
|
|
|
|
func newHTTPHandler(grpcHandler *grpcweb.WrappedGrpcServer, mediaSetService MediaSetService, c config.Config, logger *zap.SugaredLogger) *httpHandler {
|
|
fileStoreHandler := http.NotFoundHandler()
|
|
if c.FileStoreHTTPRoot != "" {
|
|
logger.With("root", c.FileStoreHTTPRoot, "baseURL", c.FileStoreHTTPBaseURL.String()).Info("Configured to serve file store over HTTP")
|
|
fileStoreHandler = http.FileServer(&indexedFileSystem{http.Dir(c.FileStoreHTTPRoot)})
|
|
}
|
|
|
|
assetsHandler := http.NotFoundHandler()
|
|
if c.AssetsHTTPRoot != "" {
|
|
logger.With("root", c.AssetsHTTPRoot).Info("Configured to serve assets over HTTP")
|
|
assetsHandler = http.FileServer(&indexedFileSystem{http.Dir(c.AssetsHTTPRoot)})
|
|
}
|
|
|
|
// If FileSystemStore AND assets serving are both enabled,
|
|
// FileStoreHTTPBaseURL *must* be set to a value other than "/" to avoid
|
|
// clobbering the assets routes.
|
|
router := mux.NewRouter()
|
|
if c.FileStore == config.FileSystemStore {
|
|
router.
|
|
Methods("GET").
|
|
PathPrefix(c.FileStoreHTTPBaseURL.Path).
|
|
Handler(filestore.NewFileSystemStoreHTTPMiddleware(c.FileStoreHTTPBaseURL, fileStoreHandler))
|
|
}
|
|
router.
|
|
Methods("GET").
|
|
Handler(assetsHandler)
|
|
|
|
return &httpHandler{
|
|
grpcHandler: grpcHandler,
|
|
router: router,
|
|
mediaSetService: mediaSetService,
|
|
logger: logger,
|
|
}
|
|
}
|
|
|
|
func (h *httpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
if !h.grpcHandler.IsGrpcWebRequest(r) && !h.grpcHandler.IsAcceptableGrpcCorsRequest(r) {
|
|
h.router.ServeHTTP(w, r)
|
|
return
|
|
}
|
|
h.grpcHandler.ServeHTTP(w, r)
|
|
}
|
|
|
|
// indexedFileSystem is an HTTP file system which handles index.html files if
|
|
// they exist, but does not serve directory listings.
|
|
//
|
|
// Ref: https://www.alexedwards.net/blog/disable-http-fileserver-directory-listings
|
|
type indexedFileSystem struct {
|
|
httpFS http.FileSystem
|
|
}
|
|
|
|
func (ifs *indexedFileSystem) Open(path string) (http.File, error) {
|
|
f, err := ifs.httpFS.Open(path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
s, err := f.Stat()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if !s.IsDir() {
|
|
return f, nil
|
|
}
|
|
|
|
index := filepath.Join(path, "index.html")
|
|
if _, err := ifs.httpFS.Open(index); err != nil {
|
|
_ = f.Close() // ignore error
|
|
return nil, err
|
|
}
|
|
|
|
return f, nil
|
|
}
|