FastCGI 是一种用于将 Web 服务器与应用程序连接的协议,特别适用于动态内容生成。本文档详细介绍了 Caddy 的 FastCGI 实现,它允许 Caddy 与 PHP-FPM 等 FastCGI 应用程序进行通信。有关通用反向代理的信息,请参阅反向代理。
Caddy 将 FastCGI 作为其反向代理处理程序的传输协议来实现。这种集成使 Caddy 能够高效地将请求转发到 FastCGI 应用程序并处理它们的响应。该实现包括针对 PHP 的特殊优化,因为 PHP 是 FastCGI 最常见的用例。
Sources: modules/caddyhttp/reverseproxy/fastcgi/fastcgi.go116-209
Caddy 中的 FastCGI 实现是作为反向代理处理程序的专用传输机制。此实现的核心是 fastcgi 包中的 Transport 结构体。
Sources: modules/caddyhttp/reverseproxy/fastcgi/fastcgi.go43-85
Transport 结构体实现了 http.RoundTripper 接口,这使得它可以用作反向代理处理程序的传输机制。当接收到请求时,RoundTrip 方法会构建相应的 CGI 环境变量,建立与 FastCGI 服务器的连接,并使用 client 类型管理通信。
FastCGI 传输可以直接在 Caddy 的 JSON 配置中进行配置。下面是可用的配置选项表
| 字段 | 类型 | 描述 |
|---|---|---|
root | 字符串 | FastCGI 应用程序的根目录(默认为虚拟主机的根目录) |
split_path | []string | 用于分割 URL 的路径段(第一部分成为脚本名,第二部分成为 PATH_INFO) |
resolve_root_symlink | bool | 是否解析根路径中的符号链接 |
env | map[string]string | 要传递给 FastCGI 应用程序的额外环境变量 |
dial_timeout | duration | 建立连接的超时时间(默认:3秒) |
read_timeout | duration | 从 FastCGI 服务器读取的超时时间 |
write_timeout | duration | 写入 FastCGI 服务器的超时时间 |
capture_stderr | bool | 是否捕获并记录 FastCGI 应用程序的 stderr 输出 |
Sources: modules/caddyhttp/reverseproxy/fastcgi/fastcgi.go43-85
对于 PHP 应用程序(FastCGI 最常见的用例),Caddy 为 Caddyfile 提供了 php_fastcgi 指令。此指令为 PHP 处理设置了完整的配置。
基本语法
php_fastcgi [<matcher>] <upstream>
其中
<matcher> 是一个可选的路径匹配器<upstream> 是 FastCGI 服务器的地址,例如 localhost:9000其他选项
php_fastcgi [<matcher>] <upstream> {
root <path>
split <extensions...>
env <key> <value>
index <filename>
try_files <files...>
resolve_root_symlink
dial_timeout <duration>
read_timeout <duration>
write_timeout <duration>
capture_stderr
}
Sources: modules/caddyhttp/reverseproxy/fastcgi/caddyfile.go37-122 modules/caddyhttp/reverseproxy/fastcgi/caddyfile.go207-302
php_fastcgi 指令经过特殊设计,旨在高效处理 PHP 应用程序。它设置了多个协同工作的路由,以提供正确的 PHP 处理
Sources: modules/caddyhttp/reverseproxy/fastcgi/caddyfile.go124-447
此设置提供了针对 PHP 应用程序的几个关键功能
在底层,php_fastcgi 指令创建了多个路由和处理程序
Sources: modules/caddyhttp/reverseproxy/fastcgi/caddyfile.go310-383 modules/caddyhttp/reverseproxy/fastcgi/caddyfile.go385-417
当请求由 FastCGI 传输处理时,会发生以下步骤
buildEnv 方法从 HTTP 请求构建 CGI 环境变量FastCGI 传输设置了标准的 CGI 环境变量,包括
DOCUMENT_ROOT:为 FastCGI 应用程序配置的根目录SCRIPT_FILENAME:正在执行脚本的绝对路径SCRIPT_NAME:脚本的 URL 路径PATH_INFO:脚本名后的额外路径信息(如果启用了路径分割)REQUEST_URI:客户端请求的原始 URIQUERY_STRING:URL 中的查询字符串HTTP_ 为前缀)env 中配置的额外环境变量Sources: modules/caddyhttp/reverseproxy/fastcgi/fastcgi.go212-372
FastCGI 传输的一个重要功能是路径分割,它将脚本名与额外路径信息分开。这对于需要通过 $_SERVER['PATH_INFO'] 访问路径信息的 PHP 应用程序特别有用。
例如,如果路径为 /script.php/extra/info,分割路径为 .php,传输将设置
SCRIPT_NAME 为 /script.phpPATH_INFO 为 /extra/infoSources: modules/caddyhttp/reverseproxy/fastcgi/fastcgi.go376-392
FastCGI 实现,特别是针对 PHP 的实现,如果配置不当,可能会带来安全风险。Caddy 的 FastCGI 实现中的一些关键安全功能包括
\x00)的请求将被拒绝,以防止 PHP 相关的潜在安全问题SCRIPT_FILENAME 之前会进行净化resolve_root_symlink 选项有助于防止 PHP opcache 的问题Sources: modules/caddyhttp/reverseproxy/fastcgi/fastcgi.go119-124
PHP 应用程序的基本 Caddyfile 配置
example.com {
root * /var/www/html
php_fastcgi localhost:9000
file_server
}
此配置
/var/www/htmllocalhost:9000 的 FastCGI 服务器具有自定义设置的更高级配置
example.com {
root * /var/www/html
php_fastcgi /app/* localhost:9000 {
root /var/www/html/app
env APP_ENV production
split .php
index index.php
try_files {path} {path}/index.php index.php
dial_timeout 5s
read_timeout 30s
write_timeout 30s
}
file_server
}
此配置
/app/ 路径下的 PHP 请求Sources: modules/caddyhttp/reverseproxy/fastcgi/caddyfile.go37-122 modules/caddyhttp/reverseproxy/fastcgi/caddyfile.go171-302