feat(config): 添加 alias 配置支持
- StaticConfig 添加 Alias 字段,与 Root 互斥 - server.go 创建 handler 时设置 alias - validate.go 添加 root/alias 互斥验证和路径安全检查 - converter.go nginx alias 指令正确转换为 Alias 字段 - defaults.go --generate-config 输出包含 alias 文档和示例 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
5bb44fdbcb
commit
07acfad146
@ -261,8 +261,15 @@ type StaticConfig struct {
|
||||
|
||||
// Root 静态文件根目录
|
||||
// 所有静态文件请求都将以此目录为基础解析
|
||||
// 请求路径追加到 root 后面
|
||||
// 示例: root=/var/www, path=/static/ → /static/img.png → /var/www/static/img.png
|
||||
Root string `yaml:"root"`
|
||||
|
||||
// Alias 替换路径(与 root 互斥)
|
||||
// 将 location 路径替换为 alias 路径(nginx alias 语义)
|
||||
// 示例: alias=/var/www/files/, path=/images/ → /images/logo.png → /var/www/files/logo.png
|
||||
Alias string `yaml:"alias"`
|
||||
|
||||
// Index 索引文件列表
|
||||
// 访问目录时依次查找这些文件作为默认页面
|
||||
// 默认为 ["index.html", "index.htm"]
|
||||
|
||||
@ -343,6 +343,11 @@ func GenerateConfigYAML(cfg *Config) ([]byte, error) {
|
||||
for _, st := range cfg.Servers[0].Static {
|
||||
buf.WriteString(" - path: \"/\" # 匹配路径前缀\n")
|
||||
fmt.Fprintf(&buf, " root: \"%s\" # 静态文件根目录\n", st.Root)
|
||||
buf.WriteString(" # alias: \"\" # 替换路径(与 root 互斥,nginx alias 语义)\n")
|
||||
buf.WriteString(" # root: 请求路径追加到 root 后面\n")
|
||||
buf.WriteString(" # alias: 请求路径替换 location 为 alias\n")
|
||||
buf.WriteString(" # 示例: path=/images/, alias=/var/www/files/\n")
|
||||
buf.WriteString(" # /images/logo.png → /var/www/files/logo.png\n")
|
||||
buf.WriteString(" index: # 索引文件\n")
|
||||
for _, idx := range st.Index {
|
||||
fmt.Fprintf(&buf, " - \"%s\"\n", idx)
|
||||
@ -353,9 +358,9 @@ func GenerateConfigYAML(cfg *Config) ([]byte, error) {
|
||||
buf.WriteString(" # location_type: \"\" # 位置匹配类型(有效值: exact, prefix, regex, regex_caseless, prefix_priority, named)\n")
|
||||
buf.WriteString(" # internal: false # 仅允许内部重定向访问\n")
|
||||
}
|
||||
buf.WriteString(" # 示例:额外的静态目录\n")
|
||||
buf.WriteString(" # - path: \"/assets/\"\n")
|
||||
buf.WriteString(" # root: \"/var/www/assets\"\n")
|
||||
buf.WriteString(" # 示例:使用 alias 替换路径\n")
|
||||
buf.WriteString(" # - path: \"/images/\"\n")
|
||||
buf.WriteString(" # alias: \"/var/www/files/\" # /images/logo.png → /var/www/files/logo.png\n")
|
||||
buf.WriteString(" # index: [\"index.html\"]\n")
|
||||
buf.WriteString("\n")
|
||||
|
||||
|
||||
@ -221,11 +221,21 @@ func validateStatics(statics []StaticConfig) error {
|
||||
}
|
||||
paths[path] = i
|
||||
|
||||
// root 和 alias 互斥检查
|
||||
if s.Root != "" && s.Alias != "" {
|
||||
return fmt.Errorf("static[%d]: root 和 alias 不能同时设置", i)
|
||||
}
|
||||
|
||||
// 验证根目录路径安全
|
||||
if s.Root != "" && strings.Contains(s.Root, "..") {
|
||||
return fmt.Errorf("static[%d]: 根目录路径不能包含 '..'", i)
|
||||
}
|
||||
|
||||
// 验证 alias 路径安全
|
||||
if s.Alias != "" && strings.Contains(s.Alias, "..") {
|
||||
return fmt.Errorf("static[%d]: alias 路径不能包含 '..'", i)
|
||||
}
|
||||
|
||||
// 验证 try_files 模式
|
||||
for j, pattern := range s.TryFiles {
|
||||
if err := validateTryFilesPattern(pattern); err != nil {
|
||||
|
||||
@ -832,13 +832,7 @@ func convertStaticDirectives(directives []Directive, static *config.StaticConfig
|
||||
}
|
||||
case "alias":
|
||||
if len(d.Args) > 0 {
|
||||
static.Root = d.Args[0]
|
||||
result.Warnings = append(result.Warnings, Warning{
|
||||
Directive: "alias",
|
||||
Line: d.Line,
|
||||
File: d.File,
|
||||
Message: "alias is converted to root; semantic differences may exist for locations with non-trailing paths",
|
||||
})
|
||||
static.Alias = d.Args[0]
|
||||
}
|
||||
case "index":
|
||||
static.Index = append(static.Index, d.Args...)
|
||||
|
||||
@ -645,12 +645,12 @@ http {
|
||||
}
|
||||
|
||||
st := s.Static[0]
|
||||
if st.Root != "/data/photos/" {
|
||||
t.Errorf("Root = %s, want /data/photos/", st.Root)
|
||||
if st.Alias != "/data/photos/" {
|
||||
t.Errorf("Alias = %s, want /data/photos/", st.Alias)
|
||||
}
|
||||
|
||||
if !hasWarningContaining(result.Warnings, "alias") {
|
||||
t.Error("expected warning about alias conversion to root")
|
||||
// alias 和 root 互斥,root 应为空
|
||||
if st.Root != "" {
|
||||
t.Errorf("Root = %s, want empty (alias is set)", st.Root)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1077,6 +1077,10 @@ func (s *Server) registerStaticHandlersWithLocationEngine(cfg *config.ServerConf
|
||||
static.Index,
|
||||
true, // useSendfile
|
||||
)
|
||||
// 设置 alias(与 root 互斥)
|
||||
if static.Alias != "" {
|
||||
staticHandler.SetAlias(static.Alias)
|
||||
}
|
||||
if s.fileCache != nil {
|
||||
staticHandler.SetFileCache(s.fileCache)
|
||||
// 设置默认缓存 TTL (5s)
|
||||
@ -1442,6 +1446,10 @@ func (s *Server) registerStaticHandlers(router *handler.Router, cfg *config.Serv
|
||||
static.Index,
|
||||
true, // useSendfile
|
||||
)
|
||||
// 设置 alias(与 root 互斥)
|
||||
if static.Alias != "" {
|
||||
staticHandler.SetAlias(static.Alias)
|
||||
}
|
||||
if s.fileCache != nil {
|
||||
staticHandler.SetFileCache(s.fileCache)
|
||||
// 设置默认缓存 TTL (5s)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user