The Crystal Programming Language Forum

Introduce HTTP::Dir and HTTP::FileSystem

HTTP::StaticFileHandler should use an abstraction instead of a string to serve files from.

In go we have http.Dir that is a wrapper around a string but it adds the Open(name string) (File, error) method, i think something similar would be great to have in crystal, here’s my attempt at translating the same abstraction we have in go.

# https://godoc.org/net/http#FileSystem
abstract class HTTP::FileSystem
  abstract def open(path : String) : IO
  end
end

# https://godoc.org/net/http#Dir
class HTTP::Dir < HTTP::FileSystem
  def open(path : String) : IO
    # ...
  end
end

Then HTTP::StaticFileHandler could work like this

class HTTP::StaticFileHandler
    def initialize(@fs : HTTP::FileSystem, fallthrough = true, directory_listing = true)
    @fallthrough = !!fallthrough
    @directory_listing = !!directory_listing
  end

  # use @fs.open to open files
end

This could be implemented in a backwards compatible way by overloading new(String) to create an HTTP::Dir and use it.

I don’t think it makes much sense to introduce two new types just for StaticFileHandler. To customize the way this handler accesses a file system, it would be much cleaner to just extract all filesystem-specific calls to private methods which can be overridden in a subclass.

As mentioned earlier, in the long term it might be great to have some kind of filesystem abstraction, but it should be universal, not just for StaticFileHandler.

I agree, having a global FIleSystem abstraction would be nicer in the long term, I’m going to refactor the filesystem calls in HTTP::StaticFileHandler into private methods and PR it, if thats alright with you?

EDIT: After implementing it its pretty hackish, i think implementing the filesystem abstraction should be opened as an issue on the crystal repo, I’ll open it if you agree.