#pingora #web-server #http #host-name #virtual-hosts

virtual-hosts-module

用于Pingora的模块,处理每个虚拟主机的配置

1 个不稳定版本

0.2.0 2024年5月12日

#628HTTP服务器

Apache-2.0

40KB
522

Pingora的虚拟主机模块

此模块简化了处理虚拟主机的操作。它包装了任何实现 module_utils::RequestFilter 和其配置的处理程序,允许为每个虚拟主机及其子目录提供不同的配置。例如,如果包装的处理程序是静态文件模块,则配置文件可能如下所示

vhosts:
    localhost:8000:
        aliases:
            - 127.0.0.1:8000
            - "[::1]:8000"
        root: ./local-debug-root
    example.com:
        aliases:
            - www.example.com
        default: true
        root: ./production-root
        subdirs:
            /metrics
                root: ./metrics
            /test:
                strip_prefix: true
                root: ./local-debug-root
                redirect_prefix: /test

虚拟主机配置向包装处理程序的配置添加三个配置设置

  • aliases 列出应共享相同配置的附加主机名。
  • default 可以设置为 true 以指示此配置应适用于未明确列出所有主机名。
  • subdirs 将子目录映射到其相应的配置。配置是包装处理程序的配置,并添加了 strip_prefix 设置。如果 true,则此设置将在将请求传递给处理程序之前从URI中删除子目录路径。

如果没有默认主机条目,并且对未知主机名发出请求,此处理程序将不处理请求。否则,处理将委托给包装处理程序。

在选择子目录配置时,较长的匹配路径优先。匹配始终针对完整文件名进行,这意味着URI /test/abc 匹配子目录 /test,而URI /test_abc 不匹配。如果没有找到匹配路径,则使用主机配置。

注意:当使用 strip_prefix 选项时,后续处理程序将接收到不匹配实际请求URI的URI。这可能导致链接或重定向错误。当使用静态文件模块时,可以设置类似于上面的示例中的 redirect_prefix 设置来补偿。可能需要通过Pingora的 upstream_response_filter 修正上游响应。

代码示例

通常,虚拟主机配置将从配置文件中读取并用于实例化相应的处理程序。这就是如何操作的

use pingora_core::server::configuration::{Opt, ServerConf};
use module_utils::{FromYaml, merge_conf};
use static_files_module::{StaticFilesConf, StaticFilesHandler};
use structopt::StructOpt;
use virtual_hosts_module::{VirtualHostsConf, VirtualHostsHandler};

// Combine Pingora server configuration with virtual hosts wrapping static files configuration.
#[merge_conf]
struct Conf {
    server: ServerConf,
    virtual_hosts: VirtualHostsConf<StaticFilesConf>,
}

// Read command line options and configuration file.
let opt = Opt::from_args();
let conf = opt
    .conf
    .as_ref()
    .and_then(|path| Conf::load_from_yaml(path).ok())
    .unwrap_or_else(Conf::default);

// Create handler from configuration
let handler: VirtualHostsHandler<StaticFilesHandler> = conf.virtual_hosts.try_into().unwrap();

然后您可以在您的服务器实现中使用该处理程序

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

pub struct MyServer {
    handler: VirtualHostsHandler<StaticFilesHandler>,
}

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

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

    async fn upstream_peer(
        &self,
        _session: &mut Session,
        _ctx: &mut Self::CTX,
    ) -> Result<Box<HttpPeer>, Box<Error>> {
        // Virtual hosts handler didn't handle the request, meaning no matching virtual host in
        // configuration. Delegate to upstream peer.
        Ok(Box::new(HttpPeer::new(
            "example.com:443",
            true,
            "example.com".to_owned(),
        )))
    }
}

要查看完整且更全面的代码,请参阅仓库中的 virtual-hosts 示例

依赖项

~39-54MB
~1M SLoC