Skip to content

Commit

Permalink
Fix missing hosts handling for defined files block #59
Browse files Browse the repository at this point in the history
  • Loading branch information
Marcel Ludwig committed Nov 9, 2020
1 parent 84948e8 commit 05d7c2e
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 36 deletions.
10 changes: 2 additions & 8 deletions config/runtime/mux.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,9 @@ package runtime
import (
"net/http"
"path"
"path/filepath"

"github.com/avenga/couper/config"
"github.com/avenga/couper/errors"
"github.com/avenga/couper/handler"
"github.com/avenga/couper/utils"
)

Expand All @@ -16,8 +14,8 @@ type MuxOptions struct {
APIPath string
EndpointRoutes map[string]http.Handler
FileBasePath string
FileHandler http.Handler
FileErrTpl *errors.Template
FileRoutes map[string]http.Handler
SPARoutes map[string]http.Handler
}

Expand All @@ -26,6 +24,7 @@ func NewMuxOptions(conf *config.Server) (*MuxOptions, error) {
APIErrTpl: errors.DefaultJSON,
FileErrTpl: errors.DefaultHTML,
EndpointRoutes: make(map[string]http.Handler),
FileRoutes: make(map[string]http.Handler),
SPARoutes: make(map[string]http.Handler),
}

Expand All @@ -50,12 +49,7 @@ func NewMuxOptions(conf *config.Server) (*MuxOptions, error) {
options.FileErrTpl = tpl
}

absPath, err := filepath.Abs(conf.Files.DocumentRoot)
if err != nil {
return nil, err
}
options.FileBasePath = utils.JoinPath("/", conf.BasePath, conf.Files.BasePath)
options.FileHandler = handler.NewFile(options.FileBasePath, absPath, options.FileErrTpl)
}

return options, nil
Expand Down
24 changes: 16 additions & 8 deletions config/runtime/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,11 @@ func NewServerConfiguration(conf *config.Gateway, httpConf *HTTPConfig, log *log
if err != nil {
log.Fatal(err)
}

spaHandler = configureProtectedHandler(accessControls, errors.DefaultHTML, // TODO: server err tpl
config.NewAccessControl(srvConf.AccessControl, srvConf.DisableAccessControl),
config.NewAccessControl(srvConf.Spa.AccessControl, srvConf.Spa.DisableAccessControl), spaHandler)

for _, spaPath := range srvConf.Spa.Paths {
for _, p := range getPathsFromHosts(defaultPort, srvConf.Hosts,
utils.JoinPath("/", srvConf.BasePath, srvConf.Spa.BasePath, spaPath)) {
Expand All @@ -87,16 +92,19 @@ func NewServerConfiguration(conf *config.Gateway, httpConf *HTTPConfig, log *log
}
}

if muxOptions.FileHandler != nil {
muxOptions.FileHandler = configureProtectedHandler(accessControls, muxOptions.FileErrTpl,
config.NewAccessControl(srvConf.AccessControl, srvConf.DisableAccessControl),
config.NewAccessControl(srvConf.Files.AccessControl, srvConf.Files.DisableAccessControl), muxOptions.FileHandler)
}
if srvConf.Files != nil {
fileHandler, err := handler.NewFile(muxOptions.FileBasePath, srvConf.Files.DocumentRoot, muxOptions.FileErrTpl)
if err != nil {
log.Fatal(err)
}

if spaHandler != nil {
spaHandler = configureProtectedHandler(accessControls, errors.DefaultHTML, // TODO: server err tpl
protectedFileHandler := configureProtectedHandler(accessControls, muxOptions.FileErrTpl,
config.NewAccessControl(srvConf.AccessControl, srvConf.DisableAccessControl),
config.NewAccessControl(srvConf.Spa.AccessControl, srvConf.Spa.DisableAccessControl), spaHandler)
config.NewAccessControl(srvConf.Files.AccessControl, srvConf.Files.DisableAccessControl), fileHandler)

for _, p := range getPathsFromHosts(defaultPort, srvConf.Hosts, muxOptions.FileBasePath) {
muxOptions.FileRoutes[p] = protectedFileHandler
}
}

if srvConf.API == nil {
Expand Down
11 changes: 8 additions & 3 deletions handler/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"net/http"
"os"
"path"
"path/filepath"
"strings"

"github.com/avenga/couper/errors"
Expand All @@ -28,14 +29,18 @@ type File struct {
rootDir http.Dir
}

func NewFile(basePath, docRoot string, errTpl *errors.Template) *File {
func NewFile(basePath, docRoot string, errTpl *errors.Template) (*File, error) {
dir, err := filepath.Abs(docRoot)
if err != nil {
return nil, err
}
f := &File{
basePath: basePath,
errorTpl: errTpl,
rootDir: http.Dir(docRoot),
rootDir: http.Dir(dir),
}

return f
return f, nil
}

func (f *File) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
Expand Down
5 changes: 4 additions & 1 deletion handler/file_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,10 @@ func TestFile_ServeHTTP(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
f := NewFile(tt.fields.basePath, path.Join(wd, tt.fields.docRootDir), errors.DefaultHTML)
f, err := NewFile(tt.fields.basePath, path.Join(wd, tt.fields.docRootDir), errors.DefaultHTML)
if err != nil {
t.Fatal(err)
}

rec := httptest.NewRecorder()
f.ServeHTTP(rec, tt.req)
Expand Down
40 changes: 24 additions & 16 deletions server/mux.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ import (
// Mux is a http request router and dispatches requests
// to their corresponding http handlers.
type Mux struct {
apiPath string
apiErrHandler *errors.Template
apiPath string
endpointRoot *pathpattern.Node
fileBasePath string
fileHandler http.Handler
fileErrHandler *errors.Template
fileRoot *pathpattern.Node
router *openapi3filter.Router
spaRoot *pathpattern.Node
}
Expand All @@ -50,12 +50,12 @@ func NewMux(options *runtime.MuxOptions) *Mux {
}

mux := &Mux{
apiPath: opts.APIPath,
apiErrHandler: opts.APIErrTpl,
apiPath: opts.APIPath,
endpointRoot: &pathpattern.Node{},
fileBasePath: opts.FileBasePath,
fileHandler: opts.FileHandler,
fileErrHandler: opts.FileErrTpl,
endpointRoot: &pathpattern.Node{},
fileRoot: &pathpattern.Node{},
spaRoot: &pathpattern.Node{},
}

Expand All @@ -64,6 +64,10 @@ func NewMux(options *runtime.MuxOptions) *Mux {
mux.mustAddRoute(mux.endpointRoot, allowedMethods, path, h)
}

for path, h := range opts.FileRoutes {
mux.mustAddRoute(mux.fileRoot, []string{http.MethodGet}, utils.JoinPath(path, "/**"), h)
}

for path, h := range opts.SPARoutes {
mux.mustAddRoute(mux.spaRoot, []string{http.MethodGet}, path, h)
}
Expand Down Expand Up @@ -128,13 +132,14 @@ func (m *Mux) FindHandler(req *http.Request) http.Handler {
return m.apiErrHandler.ServeError(errors.APIRouteNotFound)
}

if m.hasFileResponse(req) {
return m.fileHandler
fileHandler, exist := m.hasFileResponse(req)
if exist {
return fileHandler
}

node, paramValues = m.match(m.spaRoot, req)
if node == nil {
if m.fileHandler != nil && strings.HasPrefix(req.URL.Path, m.fileBasePath) {
if fileHandler != nil && strings.HasPrefix(req.URL.Path, m.fileBasePath) {
return m.fileErrHandler.ServeError(errors.FilesRouteNotFound)
}
// TODO: server err handler
Expand Down Expand Up @@ -183,18 +188,21 @@ func (m *Mux) match(root *pathpattern.Node, req *http.Request) (*pathpattern.Nod
return node, paramValues
}

func (m *Mux) hasFileResponse(req *http.Request) bool {
if m.fileHandler == nil {
return false
func (m *Mux) hasFileResponse(req *http.Request) (http.Handler, bool) {
node, _ := m.match(m.fileRoot, req)
if node == nil {
return nil, false
}

fileHandler := m.fileHandler
if p, isProtected := m.fileHandler.(ac.ProtectedHandler); isProtected {
route := node.Value.(*openapi3filter.Route)
fileHandler := route.Handler
if p, isProtected := fileHandler.(ac.ProtectedHandler); isProtected {
fileHandler = p.Child()
}
if fh, ok := fileHandler.(handler.HasResponse); ok && fh.HasResponse(req) {
return true

if fh, ok := fileHandler.(handler.HasResponse); ok {
return fileHandler, fh.HasResponse(req)
}

return false
return fileHandler, false
}

0 comments on commit 05d7c2e

Please sign in to comment.