1 个不稳定版本
0.2.0 | 2024年5月12日 |
---|
#628 在 HTTP服务器
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