mirror of
https://github.com/caddyserver/caddy.git
synced 2024-12-23 22:27:38 -05:00
258 lines
5.3 KiB
Go
258 lines
5.3 KiB
Go
|
package config
|
||
|
|
||
|
// dirFunc is a type of parsing function which processes
|
||
|
// a particular directive and populates the config.
|
||
|
type dirFunc func(*parser) error
|
||
|
|
||
|
// validDirectives is a map of valid directive names to
|
||
|
// their parsing function.
|
||
|
var validDirectives map[string]dirFunc
|
||
|
|
||
|
func init() {
|
||
|
// This has to be in the init function
|
||
|
// to avoid an initialization loop error because
|
||
|
// the 'import' directive (key) in this map
|
||
|
// invokes a method that uses this map.
|
||
|
validDirectives = map[string]dirFunc{
|
||
|
"root": func(p *parser) error {
|
||
|
if !p.lexer.NextArg() {
|
||
|
return p.argErr()
|
||
|
}
|
||
|
p.cfg.Root = p.tkn()
|
||
|
return nil
|
||
|
},
|
||
|
"import": func(p *parser) error {
|
||
|
if !p.lexer.NextArg() {
|
||
|
return p.argErr()
|
||
|
}
|
||
|
|
||
|
p2 := parser{}
|
||
|
err := p2.lexer.Load(p.tkn())
|
||
|
if err != nil {
|
||
|
return p.err("Parse", err.Error())
|
||
|
}
|
||
|
defer p2.lexer.Close()
|
||
|
|
||
|
p2.cfg = p.cfg
|
||
|
err = p2.directives()
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
p.cfg = p2.cfg
|
||
|
|
||
|
return nil
|
||
|
},
|
||
|
"gzip": func(p *parser) error {
|
||
|
p.cfg.Gzip = true
|
||
|
return nil
|
||
|
},
|
||
|
"log": func(p *parser) error {
|
||
|
log := Log{Enabled: true}
|
||
|
|
||
|
// Get the type of log (requests, errors, etc.)
|
||
|
if !p.lexer.NextArg() {
|
||
|
return p.argErr()
|
||
|
}
|
||
|
logWhat := p.tkn()
|
||
|
|
||
|
// Set the log output file
|
||
|
if p.lexer.NextArg() {
|
||
|
log.OutputFile = p.tkn()
|
||
|
}
|
||
|
|
||
|
// Set the log output format
|
||
|
if p.lexer.NextArg() {
|
||
|
log.Format = p.tkn()
|
||
|
}
|
||
|
|
||
|
switch logWhat {
|
||
|
case "requests":
|
||
|
if log.OutputFile == "" || log.OutputFile == "_" {
|
||
|
log.OutputFile = DefaultRequestsLog
|
||
|
}
|
||
|
p.cfg.RequestLog = log
|
||
|
case "errors":
|
||
|
if log.OutputFile == "" || log.OutputFile == "_" {
|
||
|
log.OutputFile = DefaultErrorsLog
|
||
|
}
|
||
|
p.cfg.ErrorLog = log
|
||
|
default:
|
||
|
return p.err("Parse", "Unknown log '"+logWhat+"'")
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
},
|
||
|
"rewrite": func(p *parser) error {
|
||
|
var rw Rewrite
|
||
|
|
||
|
if !p.lexer.NextArg() {
|
||
|
return p.argErr()
|
||
|
}
|
||
|
rw.From = p.tkn()
|
||
|
|
||
|
if !p.lexer.NextArg() {
|
||
|
return p.argErr()
|
||
|
}
|
||
|
rw.To = p.tkn()
|
||
|
|
||
|
p.cfg.Rewrites = append(p.cfg.Rewrites, rw)
|
||
|
return nil
|
||
|
},
|
||
|
"redir": func(p *parser) error {
|
||
|
var redir Redirect
|
||
|
|
||
|
// From
|
||
|
if !p.lexer.NextArg() {
|
||
|
return p.argErr()
|
||
|
}
|
||
|
redir.From = p.tkn()
|
||
|
|
||
|
// To
|
||
|
if !p.lexer.NextArg() {
|
||
|
return p.argErr()
|
||
|
}
|
||
|
redir.To = p.tkn()
|
||
|
|
||
|
// Status Code
|
||
|
if !p.lexer.NextArg() {
|
||
|
return p.argErr()
|
||
|
}
|
||
|
if code, ok := httpRedirs[p.tkn()]; !ok {
|
||
|
return p.err("Parse", "Invalid redirect code '"+p.tkn()+"'")
|
||
|
} else {
|
||
|
redir.Code = code
|
||
|
}
|
||
|
|
||
|
p.cfg.Redirects = append(p.cfg.Redirects, redir)
|
||
|
return nil
|
||
|
},
|
||
|
"ext": func(p *parser) error {
|
||
|
if !p.lexer.NextArg() {
|
||
|
return p.argErr()
|
||
|
}
|
||
|
p.cfg.Extensions = append(p.cfg.Extensions, p.tkn())
|
||
|
for p.lexer.NextArg() {
|
||
|
p.cfg.Extensions = append(p.cfg.Extensions, p.tkn())
|
||
|
}
|
||
|
return nil
|
||
|
},
|
||
|
"error": func(p *parser) error {
|
||
|
if !p.lexer.NextArg() {
|
||
|
return p.argErr()
|
||
|
}
|
||
|
if code, ok := httpErrors[p.tkn()]; !ok {
|
||
|
return p.err("Syntax", "Invalid error code '"+p.tkn()+"'")
|
||
|
} else if val, exists := p.cfg.ErrorPages[code]; exists {
|
||
|
return p.err("Config", p.tkn()+" error page already configured to be '"+val+"'")
|
||
|
} else {
|
||
|
if !p.lexer.NextArg() {
|
||
|
return p.argErr()
|
||
|
}
|
||
|
p.cfg.ErrorPages[code] = p.tkn()
|
||
|
}
|
||
|
return nil
|
||
|
},
|
||
|
"header": func(p *parser) error {
|
||
|
var head Headers
|
||
|
var isNewPattern bool
|
||
|
|
||
|
if !p.lexer.NextArg() {
|
||
|
return p.argErr()
|
||
|
}
|
||
|
pattern := p.tkn()
|
||
|
|
||
|
// See if we already have a definition for this URL pattern...
|
||
|
for _, h := range p.cfg.Headers {
|
||
|
if h.Url == pattern {
|
||
|
head = h
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// ...otherwise, this is a new pattern
|
||
|
if head.Url == "" {
|
||
|
head.Url = pattern
|
||
|
isNewPattern = true
|
||
|
}
|
||
|
|
||
|
processHeaderBlock := func() error {
|
||
|
err := p.openCurlyBrace()
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
for p.lexer.Next() {
|
||
|
if p.tkn() == "}" {
|
||
|
break
|
||
|
}
|
||
|
h := Header{Name: p.tkn()}
|
||
|
if p.lexer.NextArg() {
|
||
|
h.Value = p.tkn()
|
||
|
}
|
||
|
head.Headers = append(head.Headers, h)
|
||
|
}
|
||
|
err = p.closeCurlyBrace()
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// A single header could be declared on the same line, or
|
||
|
// multiple headers can be grouped by URL pattern, so we have
|
||
|
// to look for both here.
|
||
|
if p.lexer.NextArg() {
|
||
|
if p.tkn() == "{" {
|
||
|
err := processHeaderBlock()
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
} else {
|
||
|
h := Header{Name: p.tkn()}
|
||
|
if p.lexer.NextArg() {
|
||
|
h.Value = p.tkn()
|
||
|
}
|
||
|
head.Headers = append(head.Headers, h)
|
||
|
}
|
||
|
} else {
|
||
|
// Okay, it might be an opening curly brace on the next line
|
||
|
if !p.lexer.Next() {
|
||
|
return p.eofErr()
|
||
|
}
|
||
|
err := processHeaderBlock()
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if isNewPattern {
|
||
|
p.cfg.Headers = append(p.cfg.Headers, head)
|
||
|
} else {
|
||
|
for i := 0; i < len(p.cfg.Headers); i++ {
|
||
|
if p.cfg.Headers[i].Url == pattern {
|
||
|
p.cfg.Headers[i] = head
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
},
|
||
|
"tls": func(p *parser) error {
|
||
|
tls := TLSConfig{Enabled: true}
|
||
|
|
||
|
if !p.lexer.NextArg() {
|
||
|
return p.argErr()
|
||
|
}
|
||
|
tls.Certificate = p.tkn()
|
||
|
|
||
|
if !p.lexer.NextArg() {
|
||
|
return p.argErr()
|
||
|
}
|
||
|
tls.Key = p.tkn()
|
||
|
|
||
|
p.cfg.TLS = tls
|
||
|
return nil
|
||
|
},
|
||
|
}
|
||
|
}
|