如何为具有给定前缀的 URL 提供文件?

Posted

技术标签:

【中文标题】如何为具有给定前缀的 URL 提供文件?【英文标题】:How to serve file for URL with a given prefix? 【发布时间】:2020-12-22 19:57:06 【问题描述】:

上下文

我已经通过 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。

【问题讨论】:

您可以将中间件应用于具有路由组的路由子集。所以你可以先做let filesRoutes = app.grouped("files") 然后是filesRoutes.grouped(FileMiddleware(...))` - 如果我不知道这行得通,值得一试! @0xTim,我一直在尝试相同的建议,但似乎无法像其他中间件一样对 FileMiddleware 进行分组。 FileMiddleware 仅用于调试。您不应该将其用于生产。对于生产,您应该配置 nginx 来提供静态文件。 【参考方案1】:

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/ 下的任意路径。如果文件/路径不存在,我会让您添加操作。

【讨论】:

有趣!这不需要平面目录结构吗?【参考方案2】:

不确定其有效性,但在搜索文档数小时后,我想出了以下内容:

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

【讨论】:

以上是关于如何为具有给定前缀的 URL 提供文件?的主要内容,如果未能解决你的问题,请参考以下文章

如何为 Forge API 提供签名的 url 以创建 revit 文件

如何忽略具有给定前缀的文件?

如何为 .NET 库配置具有依赖注入的日志记录提供程序

如何为 graphql 查询配置 JSON?

如何为所有页面提供静态文件,而不仅仅是几个

如何为 Facebook SDK 配置 plist