go-macaron/macaron

macaron.Static(path, opts) ignores path

coolaj86 opened this issue · 6 comments

Sample Code

m.Use(macaron.Static("assets1", macaron.StaticOptions{
  Prefix: "/assets2",
  IndexFile: "index.html",
  FileSystem: myHTTPFileSystem,
}))

Expected

A request to /assets2/foo.html should try to open the FileSystem as ./assets1/foo.html

curl http://localhost:3000/assets2/

Actual

Instead, the FileSystem is opened for "/foo.html"

I think your implementation of filesystem should aware of the root directory is "assets1" otherwise it is going to just look for "foo.html".

image

(successful demo with default file system)

The problem is that macaron.Static is calling myFS.Open("/foo.html") instead of calling myFS.Open("/assets1/foo.html").

My filesystem never sees "/assets1" because macaron.Static doesn't send it.

Workaround

This was my workaround:

type myHTTPFS struct {
  prefix string
  httpfs http.FileSystem
}

func (hfs *myHTTPFS) Open(path string) (http.File, error) {
  f, err := hfs.httpfs.Open(hfs.prefix + path)
  return f, err
}

func NewFS(prefix string, fs http.FileSystem) http.FileSystem {
  return &myHTTPFS{
    prefix: prefix,
    httpfs: fs,
  }
}
  m.Use(macaron.Static("-", macaron.StaticOptions{
    Prefix:     "/install",
    IndexFile:  "index.html",
    FileSystem: NewFS("/install", static.HTTP),
  }))

  m.Use(macaron.Static("-", macaron.StaticOptions{
    Prefix:     "/",
    IndexFile:  "index.html",
    FileSystem: NewFS("/public", static.HTTP),
  }))

The default file system implementation knows what the directory is:

macaron/static.go

Lines 107 to 109 in 9f1e972

if opt.FileSystem == nil {
opt.FileSystem = newStaticFileSystem(dir)
}

I think you need a wrapper around the your current "myHTTPFileSystem" to deal with "assets1" or whatever value it would be.

What I would expect is that the prefix is passed in as a prefix each time.

So this

macaron/static.go

Lines 89 to 91 in 9f1e972

func (fs staticFileSystem) Open(name string) (http.File, error) {
return fs.dir.Open(name)
}

Would become this:

func (fs staticFileSystem) Open(name string) (http.File, error) {
	return fs.dir.Open(fs.prefix + name)
}

Or perhaps this:

f, err := opt.FileSystem.Open(file)

Would become this:

f, err := opt.FileSystem.Open(opt.Prefix + file)

However, I understand what you are saying.

I think what you're doing is fine, even the default file system is just a wrapper of http.Dir:

macaron/static.go

Lines 75 to 91 in 9f1e972

// staticFileSystem implements http.FileSystem interface.
type staticFileSystem struct {
dir *http.Dir
}
func newStaticFileSystem(directory string) staticFileSystem {
if !filepath.IsAbs(directory) {
directory = filepath.Join(Root, directory)
}
dir := http.Dir(directory)
statics.Set(&dir)
return staticFileSystem{&dir}
}
func (fs staticFileSystem) Open(name string) (http.File, error) {
return fs.dir.Open(name)
}