0
Fork 0
mirror of https://github.com/caddyserver/caddy.git synced 2024-12-23 22:27:38 -05:00
caddy/config/directives.go

258 lines
5.3 KiB
Go
Raw Normal View History

2015-01-13 14:43:45 -05:00
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
},
}
}