clipper/backend/server/handler.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
}