I have been serving files via Vapor (v4) successfully with:
func configure(_ app: Application) throws {
// ...
app.middleware.use(FileMiddleware(publicDirectory: app.directory.publicDirectory))
// ...
}
FileMiddleware
to only requests whose URL have a specific prefix? (say /files/
)As in, if I have /Public/foobar.txt
, one would request it via GET /files/foobar.txt
while GET /foobar.txt
would NOT match anything.
Middleware
is applied server-wide (affects every "route") and not a subset ... so this wouldn't work./Public/foobar.txt
to /Public/files/foobar.txt
is NOT a solution as I'm trying to limit URLs that can potentially get mapped to the file system...GET /files/foobar.txt
to GET /foobar.txt
is also not acceptable. Again, I need to limit the potential URLs which are mapped to the file system.It seems that FileMiddleware
will only work globally and not if attached to groups of routes as is usually the case with instances of middleware.
If you have a folder called Private in the project folder (i.e. the same folder holding your Public folder), then accessing files contained in it is straightforward:
public func configure(_ app: Application) throws {
app.get("files", "**") { req -> Response in
let filepath = req.parameters.getCatchall()
let workPath = DirectoryConfiguration.detect().workingDirectory
var fileURL = URL(fileURLWithPath: workPath)
.appendingPathComponent("Private", isDirectory: true)
.appendingPathComponent(filepath.joined(separator: "/"), isDirectory: false)
return req.fileio.streamFile(at: fileURL.path)
}
}
Assuming you are running this minimal project on localhost:8080
, it will serve files via the URL:
http://localhost:8080/files/path/to/myFile.txt
EDIT
OP indicates flat files only. In the light of comment, made it work with arbitrary paths under Private/
. I'll leave you to add action if file/path does not exist.