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.
Has this Issue been created already? I’m interested.
Coming from Golang, the global FileSystem
abstraction is a huge enabler for a lot of cool stuff.
I’m on board on refactoring the StaticFileHandler to isolate syscalls and other logic into protected methods. That will allow to subclass and customize the behaviour in some scenarios.
Yet I would consider those as :nodoc:
or not stable api. It won’t be worst as the current state were some frameworks monkey patch StaticFileHandler to extend the behavior to:
- handle partial responses
- remove some url components to mount the handler at other than root. (This should be handled in a more generic / composable
RouteHandler
at some point though)
- customize the content to list in a directory
- customize the directory listing template