2个不稳定版本

0.2.0 2024年5月12日
0.1.0 2024年5月8日

#494HTTP服务器


虚拟主机模块 中使用

Apache-2.0

120KB
2.5K SLoC

Pingora的静态文件模块

该Crate允许通过Pingora代理扩展功能,以便从目录中提供静态文件。

支持的功能

  • GETHEAD 请求
  • 可配置的目录索引文件(默认为 index.html
  • 可配置的页面,在404未找到错误时显示,而不是标准的错误页面
  • 通过 If-Modified-SinceIf-Unmodified-SinceIf-MatchIf-None-Match 匹配HTTP头部进行条件请求
  • 通过 RangeIf-Range HTTP头部进行字节范围请求
  • 压缩支持:提供文件的预压缩版本(支持gzip、zlib deflate、compress、Brotli、Zstandard算法)
  • 压缩支持:通过Pingora进行动态压缩(目前支持gzip、Brotli和Zstandard算法)

已知限制

  • 不支持多个字节范围的请求,将会返回整个文件。实现此功能的复杂度不值得在如此罕见的使用场景中使用。
  • 在Pingora框架中目前无法支持零拷贝数据传输(即sendfile)。

代码示例

通常您会在 request_filter 阶段创建一个 StaticFilesHandler 实例并调用它。如果无条件调用,它将处理所有请求,因此后续阶段将完全无法到达。

use async_trait::async_trait;
use pingora_core::Result;
use pingora_core::upstreams::peer::HttpPeer;
use pingora_proxy::{ProxyHttp, Session};
use module_utils::RequestFilter;
use static_files_module::StaticFilesHandler;

pub struct MyServer {
    static_files_handler: StaticFilesHandler,
}

#[async_trait]
impl ProxyHttp for MyServer {
    type CTX = <StaticFilesHandler as RequestFilter>::CTX;
    fn new_ctx(&self) -> Self::CTX {
        StaticFilesHandler::new_ctx()
    }

    async fn request_filter(
        &self,
        session: &mut Session,
        ctx: &mut Self::CTX
    ) -> Result<bool> {
        self.static_files_handler.handle(session, ctx).await
    }

    async fn upstream_peer(
        &self,
        _session: &mut Session,
        _ctx: &mut Self::CTX,
    ) -> Result<Box<HttpPeer>> {
        panic!("Unexpected, upstream_peer stage reached");
    }
}

您可以通过直接指定其配置来创建一个 StaticFilesHandler 实例。

use static_files_module::{StaticFilesConf, StaticFilesHandler};

let conf = StaticFilesConf {
    root: Some("/var/www/html".into()),
    ..Default::default()
};
let static_files_handler: StaticFilesHandler = conf.try_into().unwrap();

还可以从命令行选项和配置文件创建配置,扩展默认的Pingora数据结构。宏module_utils::merge_optmodule_utils::merge_conf分别帮助合并命令行选项和配置结构,而module_utils::FromYaml特质帮助读取配置文件。

use log::error;
use pingora_core::server::configuration::{Opt as ServerOpt, ServerConf};
use pingora_core::server::Server;
use module_utils::{FromYaml, merge_opt, merge_conf};
use serde::Deserialize;
use static_files_module::{StaticFilesConf, StaticFilesHandler, StaticFilesOpt};
use std::fs::File;
use std::io::BufReader;
use structopt::StructOpt;

// The command line flags from both structures are merged, so that the user doesn't need to
// care which structure they belong to.
#[merge_opt]
struct MyServerOpt {
    server: ServerOpt,
    static_files: StaticFilesOpt,
}

// The configuration settings from both structures are merged, so that the user doesn't need to
// care which structure they belong to.
#[merge_conf]
struct MyServerConf {
    server: ServerConf,
    static_files: StaticFilesConf,
}

let opt = MyServerOpt::from_args();
let conf = opt
    .server
    .conf
    .as_ref()
    .and_then(|path| MyServerConf::load_from_yaml(path).ok())
    .unwrap_or_else(MyServerConf::default);

let mut server = Server::new_with_opt_and_conf(opt.server, conf.server);
server.bootstrap();

let mut static_files_conf = conf.static_files;
static_files_conf.merge_with_opt(opt.static_files);
let static_files_handler: StaticFilesHandler = static_files_conf.try_into().unwrap();

要查看完整的更全面的代码,请参阅存储库中的single-static-root示例

压缩支持

您可以通过precompressed配置设置激活对所选压缩算法的支持

use static_files_module::{CompressionAlgorithm, StaticFilesConf};

let conf = StaticFilesConf {
    root: Some("/var/www/html".into()),
    precompressed: vec![CompressionAlgorithm::Gzip, CompressionAlgorithm::Brotli],
    ..Default::default()
};

这将使StaticFilesHandler寻找请求文件的gzip(.gz)和Brotli(.br)版本,并在客户端支持的情况下提供这些预压缩文件。例如,请求file.txt并发送HTTP头Accept-Encoding: br, gzip的客户端将收到file.txt.br文件,如果找不到,则收到file.txt.gz文件。StaticFilesHandler寻找预压缩文件的顺序由客户端的压缩算法首选项决定。

还可以通过Pingora的下游压缩动态地实时压缩文件。为此,在调用StaticFilesHandler之前激活会话的压缩

async fn request_filter(
    &self,
    session: &mut Session,
    ctx: &mut Self::CTX
) -> Result<bool> {
    session.downstream_compression.adjust_level(3);
    self.static_files_handler.handle(session, ctx).await
}

依赖关系

~38-53MB
~1M SLoC