如何为具有给定前缀的 URL 提供文件? 上下文问题考虑的方法

问题描述

上下文

我已经通过 Vapor (v4) 成功提供文件

func configure(_ app: Application) throws {
   // ...
   app.middleware.use(FileMiddleware(publicDirectory: app.directory.publicDirectory))
   // ...
}

问题

  • 这会尝试映射与 publicDirectory 中的文件匹配的任何/每个 URL。
  • 如何将 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。

解决方法

似乎 FileMiddleware 只能在全局范围内工作,而不能像中间件实例通常那样附加到路由组。

如果您在项目文件夹中有一个名为 Private 的文件夹(即保存您的 Public 文件夹的同一个文件夹),那么访问其中包含的文件很简单:

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 干净的一些安全问题(即不是一些“/../../”垃圾),我认为应该这样做。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...