Skip to content

静态文件中间件

静态文件中间件用于高效地处理和提供 HTML、CSS、JS、图片等静态资源请求,是 Web 应用开发中不可或缺的基础能力。

基本使用

快速启动

静态文件的优先级低于动态资源(Endpoint)

cangjie
import spire_web_http.*
import spire_web_hosting.*
import spire_web_staticfiles.*

main(args: Array<String>) {
    let builder = WebHost.createBuilder()
    let host = builder.build()
    // 启用静态文件和默认文件中间件
    host.useFileServer()
    host.run()
    return 0
}

目录结构

  • 我们可以通过配置webRootPath来配置静态文件的根路径。由于配置支持环境变量、命令行参数、json。因此你可以使用上面的任意一种进行配置。
  • contentRootPath表示内容路径,即当前项目路径,日志日志会打印此路径
  • webRootPath为当前项目(contentRootPath)下的wwwroot文件夹。
bash

demo/ # contentRootPath
├─ src/
  ├─ main.cj
  └─ ...
├─ wwwroot/ # webRootPath
  ├─ html/
  ├─ css/
  ├─ index.html
  └─ ...
└─ ...

静态文件中间件

默认文件中间件,负责将/xxx.xxx请求路径路径,匹配静态文件列表

cangjie
main(args: Array<String>) {
    let builder = WebHost.createBuilder()
    let host = builder.build()
    host.useStaticFiles()
    host.run()
    return 0
}

默认文件中间件

默认文件中间件,负责将/请求路径,匹配默认文件列表(默认文件列表可配置)

cangjie
main(args: Array<String>) {
    let builder = WebHost.createBuilder()
    let host = builder.build()
    host.useDefaultFiles()
    host.run()
    return 0
}

配置项

自定义响应头

cangjie
main(args: Array<String>) {
    let builder = WebHost.createBuilder()
    let host = builder.build()
    host.useFileServer{ options =>
        options.staticFileOptions.onPrepareResponse = {context =>
            context.context.response.addHeader(HeaderNames.CacheControl, "public, max-age=604800")
        }
    }
    host.run()
    return 0
}

设置ContentType

如果文件类型映射是ContentTypeProvider声明以外的,将返回404。但是我们提供了多种配置方式来进行扩展。我们也可以实现IContentTypeProvider接口来进行更加灵活的控制。

处理未知的类型

统一处理所有为准的内容类型。

cangjie
main(args: Array<String>) {
    let builder = WebHost.createBuilder()
    let host = builder.build()
    host.useFileServer { options => 
        // 允许处理未知的响应类型
        options.staticFileOptions.serveUnknownFileTypes = true
        options.staticFileOptions.defaultContentType = "unkonwn"
    }
    host.run()
    return 0
}

扩展已知类型

框架内置了ContentTypeProvider,我们可以添加默认之外的已知类型。

cangjie
main(args: Array<String>) {
    let builder = WebHost.createBuilder()
    let host = builder.build()
    host.useFileServer { options => 
        let contentTypeProvider = ContentTypeProvider()
        contentTypeProvider.mappings.add(".cj", "cangjie")
        options.staticFileOptions.contentTypeProvider = contentTypeProvider
    }
    host.run()
    return 0
}

自定义文件提供程序

通过自定义文件提供程序,我们可以实现从不同的存储介质获取资源。比如我们可以通过网络从远程拉取。

cangjie
import std.fs.*

main(args: Array<String>) {
    let builder = WebHost.createBuilder()
    let host = builder.build()
    host.useFileServer {
        options => options.staticFileOptions.fileProvider = MyPhysicalFileProvider(builder.environment.webRootPath)
    }
    host.run()
    return 0
}

public class MyPhysicalFileProvider <: IFileProvider {
    private let _path: String

    public init(path: String) {
        _path = path
    }

    public func getFileInfo(file: String): IFileInfo {
        let path = "${_path}${file}"
        if (exists(path)) {
            return PhysicalFileInfo(FileInfo(path))
        } else {
            return NotFoundFileInfo(path.toString())
        }
    }
}

组合文件提供程序

支持将多个文件提供程序组合成一个,将按照注册顺序查找

cangjie
main(args: Array<String>) {
    let builder = WebHost.createBuilder()
    let host = builder.build()

    host.useFileServer { options => 
        let fileProvider = CompositeFileProvider([
            PhysicalFileProvider("${builder.environment.webRootPath}/a"), 
            PhysicalFileProvider("${builder.environment.webRootPath}/b")])
        options.staticFileOptions.fileProvider = fileProvider
    }
    host.run()
    return 0
}