FlyingFox
FlyingFox copied to clipboard
Directory Handler for static files
First of all, thanks for this really good library!
With this setup:
let server = HTTPServer(port: 8080)
let root = URL(fileURLWithPath: "/Users/myUser/myStaticDir")
let route = HTTPRoute(method: .GET, path: "/static/*")
let handler = DirectoryHTTPHandler(root: root, serverPath: "static")
await server.appendRoute(route, to: handler)
try await server.start()
When I perform:
curl -L -vv http://localhost:8080/static/index.html
I'm always getting a 404
.
That's because:
https://github.com/swhitty/FlyingFox/blob/8ef9eddda8f4ea370233454eded2ceded1fb76ee/FlyingFox/Sources/Handlers/DirectoryHTTPHandler.swift#L51
never matches, because request.path
will always be /static/index.html
, so I find this example to be wrong: https://github.com/swhitty/FlyingFox#directoryhttphandler
To make it work I had to write the handler like this:
let handler = DirectoryHTTPHandler(root: root, serverPath: "/static/")
But then I found out that if I want to also handle the default file to be index.html
when not explicitly specifying it:
curl -L -vv http://localhost:8080/static/
or
curl -L -vv http://localhost:8080/static
I have to also add:
let fileRoute = HTTPRoute(method: .GET, path: "/static")
let fileHandler = FileHTTPHandler(path: root.appendingPathComponent("index.html"), contentType: "text/html")
await server.appendRoute(fileRoute, to: fileHandler)
Then I thought this is a very common scenario one would expect to work with minimal work, so I written this extension:
extension HTTPServer {
func appendStaticRoute(_ route: String, root: URL, defaultFileName: String = "index.html", withContentType contentType: String = "text/html") {
appendRoute(HTTPRoute(method: .GET, path: "/\(route)/*"), to: DirectoryHTTPHandler(root: root, serverPath: "/\(route)/"))
appendRoute(HTTPRoute(method: .GET, path: "/\(route)/"), to: FileHTTPHandler(path: root.appendingPathComponent(defaultFileName), contentType: contentType))
appendRoute(HTTPRoute(method: .GET, path: "/\(route)"), to: .redirect(to: "/\(route)/"))
}
func appendStaticRoute(_ route: String, bundle: Bundle = .main, defaultFileName: String = "index.html", withContentType contentType: String = "text/html") throws {
guard let root = bundle.resourceURL else { throw HTTPUnhandledError() }
appendStaticRoute(route, root: root, defaultFileName: defaultFileName, withContentType: contentType)
}
}
Which allows you to achieve the same with only:
let server = HTTPServer(port: 8080)
let root = URL(fileURLWithPath: "/Users/myUser/myStaticDir")
await server.appendStaticRoute("static", root: root)
try await server.start()
And so here I am, posting this. If you think it's a valuable addition, feel free to add it in the library 🍻
Excellent! Just what I needed! Many thanks.
Thank you for reporting this discrepancy in the docs and annoyance.
I have merged a change that is more lenient when processing the serverPath
making the leading and trialing /
delimiters optional.
https://github.com/swhitty/FlyingFox/pull/55
I will have a think about severing a default file within the handler.