Я успешно обслуживаю файлы через Vapor (v4):
func configure(_ app: Application) throws {
// ...
app.middleware.use(FileMiddleware(publicDirectory: app.directory.publicDirectory))
// ...
}
FileMiddleware
только запросами, URL-адреса которых имеют определенный префикс? (скажем /files/
)Например, если бы у меня был /Public/foobar.txt
, его можно было бы запросить через GET /files/foobar.txt
, в то время как GET /foobar.txt
НЕ соответствовало бы чему-либо.
Middleware
применяется ко всему серверу (влияет на каждый «маршрут»), а не к подмножеству... так что это не сработает./Public/foobar.txt
в /Public/files/foobar.txt
НЕ является решением, поскольку я пытаюсь ограничить URL-адреса, которые потенциально могут быть сопоставлены с файловой системой...GET /files/foobar.txt
на GET /foobar.txt
также недопустимо. Опять же, мне нужно ограничить потенциальные URL-адреса, которые отображаются в файловой системе.@0xTim, я только что попробовал то же самое предложение, но не представляется возможным сгруппировать FileMiddleware так же, как другое промежуточное ПО.
FileMiddleware
вещь только для отладки. Вы не должны использовать его для производства. Для производства вы должны настроить nginx для обслуживания ваших статических файлов.
Похоже, что FileMiddleware
будет работать только глобально, а не при подключении к группам маршрутов, как это обычно бывает с экземплярами промежуточного программного обеспечения.
Если у вас есть папка с именем Private в папке проекта (т. е. та же папка, в которой находится ваша общая папка), то доступ к содержащимся в ней файлам прост:
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)
}
}
Предполагая, что вы запускаете этот минимальный проект на localhost:8080
, он будет обслуживать файлы по URL-адресу:
http://localhost:8080/files/path/to/myFile.txt
РЕДАКТИРОВАТЬ
OP указывает только на плоские файлы. В свете комментария заставил его работать с произвольными путями под Private/
. Я оставлю вас, чтобы добавить действие, если файл/путь не существует.
Интересный! Разве для этого не потребуется плоская структура каталогов?
Не уверен в его достоверности, но после многих часов поиска документации я пришел к следующему:
app.get("files", "**") { req - > Response in
// get rest of URL directly from `req.url.path`
// ensure clean/secure URL and map it to file path using `DirectoryConfiguration`
req.fileio.streamFile(at: "/path/to/files")
}
Помимо некоторых проблем с безопасностью, связанных с обеспечением чистоты URL-адреса (т. Е. Не какого-то мусора «/../../»), я думаю, это должно сработать.
Вы можете применить промежуточное ПО к подмножеству маршрутов с помощью группы маршрутов. Таким образом, вы можете сделать
let filesRoutes = app.grouped("files")
, а затем filesRoutes.grouped(FileMiddleware(...))` - если это сработает, хотя я понятия не имею, стоит попробовать!