caddyserver nginx adaper 简单说明

caddyserver 包含了一个强大的adapter 架构设计,我们可以方便的进行 caddyserver 扩展
nginx 扩展的处理核心也是基于adapter 模块扩展的,通过解析nginx.conf 文件,然后转换为json 格式内容

参考处理

 
func init() {
  // 注册Adapter
  caddyconfig.RegisterAdapter("nginx", Adapter{})
}
 
const ErrUnrecognized = "unrecognized or unsupported nginx directive"
const ErrNamedLocation = "named locations marked by @ are unnsupported"
const ErrExpiresAtTime = "usage of `expires @time` is not supported"
 
// Adapter adapts NGINX config to Caddy JSON.
type Adapter struct{}
// 解析nginx 配置并 转换为json 格式
// Adapt converts the NGINX config in body to Caddy JSON.
func (Adapter) Adapt(body []byte, options map[string]interface{}) ([]byte, []caddyconfig.Warning, error) {
  filename := "nginx.conf"
  if v, ok := options["filename"].(string); ok {
    filename = v
    filename, _ = filepath.Abs(filename)
  }
  // 解析nginx 的关键token
  tokens := tokenize(body, filename)
 // 解析nginx 指令
  dirs, err := parse(tokens)
  if err != nil {
    return nil, nil, fmt.Errorf("parsing: %v", err)
  }
 
  ss := setupState{
    servers: make(map[string]*caddyhttp.Server),
  }
 
  warnings, err := ss.mainContext(dirs)
  if err != nil {
    return nil, nil, err
  }
 
  httpApp := caddyhttp.App{
    Servers: ss.servers,
  }
 
  ss.mainConfig.AppsRaw = map[string]json.RawMessage{
    "http": caddyconfig.JSON(httpApp, &warnings),
  }
 
  result, err := json.Marshal(ss.mainConfig)
 
  return result, warnings, err
}

nginx 解析处理

parse.go 以及lexer.go 中处理上还是值得学习的,部分应该也参考了部分社区的golang nginx 解析工具
转换caddy 配置处理,实际解析都会处理为标准的caddy.Config

 
func (ss *setupState) mainContext(dirs []Directive) ([]caddyconfig.Warning, error) {
  var warnings []caddyconfig.Warning
  for _, dir := range dirs {
    var warns []caddyconfig.Warning
    var err error
    switch dir.Name() {
    case "http":
      warns, err = ss.httpContext(dir.Block)
    default:
      warns = []caddyconfig.Warning{
        {
          File:      dir.File,
          Line:      dir.Line,
          Directive: dir.Name(),
          Message:   ErrUnrecognized,
        },
      }
    }
    warnings = append(warnings, warns...)
    if err != nil {
      return warnings, err
    }
  }
  return warnings, nil
}
 
func (ss *setupState) httpContext(dirs []Directive) ([]caddyconfig.Warning, error) {
  var warnings []caddyconfig.Warning
  for _, dir := range dirs {
    var warns []caddyconfig.Warning
    var err error
    switch dir.Name() {
    case "index":
      for k, d := range dirs {
        if d.Name() == "server" {
          dirs[k].Block = append(d.Block, dir)
        }
      }
    case "server":
      warns, err = ss.serverContext(dir.Block)
    case "upstream":
      up, w, err := ss.upstreamContext(dir.Block)
      warns = append(warns, w...)
      if err != nil {
        return warns, err
      }
      if ss.upstreams == nil {
        ss.upstreams = make(map[string]Upstream)
      }
      ss.upstreams[dir.Param(1)] = up
    default:
      warns = []caddyconfig.Warning{
        {
          File:      dir.File,
          Line:      dir.Line,
          Directive: dir.Name(),
          Message:   ErrUnrecognized,
        },
      }
    }
    warnings = append(warnings, warns...)
    if err != nil {
      return warnings, err
    }
  }
  return warnings, nil
}

server 处理的 (server.go 中)会转换为标准caddy 配置的监听,路由等处理,详细的可以参考

说明

caddyserver nginx adaper 核心还是将nignx 配置转换为json 格式,之后caddy 会按照标准 adaper 模式进行加载,注意实际使用的时候需要自己构建
可以使用xcaddy 构建工具

参考资料

nginxadapter.go
https://github.com/caddyserver/nginx-adapter
https://caddyserver.com/docs/json/apps/http/
https://caddyserver.com/docs/config-adapters
https://caddyserver.com/docs/extending-caddy/config-adapters
https://caddyserver.com/docs/architecture
https://github.com/recoye/config
https://github.com/yangchenxing/go-nginx-conf-parser
https://www.nginx.com/resources/wiki/start/topics/examples/full/
https://github.com/caddyserver/xcaddy

posted on 2023-01-23 11:18  荣锋亮  阅读(181)  评论(0编辑  收藏  举报

导航