mirror of
				https://github.com/caddyserver/caddy.git
				synced 2025-10-31 10:37:24 -04:00 
			
		
		
		
	
		
			
				
	
	
		
			169 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			169 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package config
 | |
| 
 | |
| import (
 | |
| 	"os"
 | |
| 	"os/exec"
 | |
| 	"runtime"
 | |
| 	"strconv"
 | |
| 	"strings"
 | |
| 
 | |
| 	"github.com/mholt/caddy/middleware"
 | |
| )
 | |
| 
 | |
| // 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, built-in directive names
 | |
| // to their parsing function. Built-in directives cannot be
 | |
| // ordered, so they should only be used for internal server
 | |
| // configuration; not directly handling requests.
 | |
| 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.nextArg() {
 | |
| 				return p.argErr()
 | |
| 			}
 | |
| 			p.cfg.Root = p.tkn()
 | |
| 			return nil
 | |
| 		},
 | |
| 		"import": func(p *parser) error {
 | |
| 			if !p.nextArg() {
 | |
| 				return p.argErr()
 | |
| 			}
 | |
| 
 | |
| 			filename := p.tkn()
 | |
| 			file, err := os.Open(filename)
 | |
| 			if err != nil {
 | |
| 				return p.err("Parse", err.Error())
 | |
| 			}
 | |
| 			defer file.Close()
 | |
| 			p2, err := newParser(file)
 | |
| 			if err != nil {
 | |
| 				return p.err("Parse", "Could not import "+filename+"; "+err.Error())
 | |
| 			}
 | |
| 
 | |
| 			p2.cfg = p.cfg
 | |
| 			err = p2.directives()
 | |
| 			if err != nil {
 | |
| 				return err
 | |
| 			}
 | |
| 			p.cfg = p2.cfg
 | |
| 
 | |
| 			return nil
 | |
| 		},
 | |
| 		"tls": func(p *parser) error {
 | |
| 			tls := TLSConfig{Enabled: true}
 | |
| 
 | |
| 			if !p.nextArg() {
 | |
| 				return p.argErr()
 | |
| 			}
 | |
| 			tls.Certificate = p.tkn()
 | |
| 
 | |
| 			if !p.nextArg() {
 | |
| 				return p.argErr()
 | |
| 			}
 | |
| 			tls.Key = p.tkn()
 | |
| 
 | |
| 			p.cfg.TLS = tls
 | |
| 			return nil
 | |
| 		},
 | |
| 		"cpu": func(p *parser) error {
 | |
| 			sysCores := runtime.NumCPU()
 | |
| 
 | |
| 			if !p.nextArg() {
 | |
| 				return p.argErr()
 | |
| 			}
 | |
| 			strNum := p.tkn()
 | |
| 
 | |
| 			setCPU := func(val int) {
 | |
| 				if val < 1 {
 | |
| 					val = 1
 | |
| 				}
 | |
| 				if val > sysCores {
 | |
| 					val = sysCores
 | |
| 				}
 | |
| 				if val > p.cfg.MaxCPU {
 | |
| 					p.cfg.MaxCPU = val
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 			if strings.HasSuffix(strNum, "%") {
 | |
| 				// Percent
 | |
| 				var percent float32
 | |
| 				pctStr := strNum[:len(strNum)-1]
 | |
| 				pctInt, err := strconv.Atoi(pctStr)
 | |
| 				if err != nil || pctInt < 1 || pctInt > 100 {
 | |
| 					return p.err("Parse", "Invalid number '"+strNum+"' (must be a positive percentage between 1 and 100)")
 | |
| 				}
 | |
| 				percent = float32(pctInt) / 100
 | |
| 				setCPU(int(float32(sysCores) * percent))
 | |
| 			} else {
 | |
| 				// Number
 | |
| 				num, err := strconv.Atoi(strNum)
 | |
| 				if err != nil || num < 0 {
 | |
| 					return p.err("Parse", "Invalid number '"+strNum+"' (requires positive integer or percent)")
 | |
| 				}
 | |
| 				setCPU(num)
 | |
| 			}
 | |
| 			return nil
 | |
| 		},
 | |
| 		"startup": func(p *parser) error {
 | |
| 			// TODO: This code is duplicated with the shutdown directive below
 | |
| 
 | |
| 			if !p.nextArg() {
 | |
| 				return p.argErr()
 | |
| 			}
 | |
| 
 | |
| 			command, args, err := middleware.SplitCommandAndArgs(p.tkn())
 | |
| 			if err != nil {
 | |
| 				return p.err("Parse", err.Error())
 | |
| 			}
 | |
| 
 | |
| 			startupfn := func() error {
 | |
| 				cmd := exec.Command(command, args...)
 | |
| 				cmd.Stdout = os.Stdout
 | |
| 				cmd.Stderr = os.Stderr
 | |
| 				err := cmd.Run()
 | |
| 				if err != nil {
 | |
| 					return err
 | |
| 				}
 | |
| 				return nil
 | |
| 			}
 | |
| 
 | |
| 			p.cfg.Startup = append(p.cfg.Startup, startupfn)
 | |
| 			return nil
 | |
| 		},
 | |
| 		"shutdown": func(p *parser) error {
 | |
| 			if !p.nextArg() {
 | |
| 				return p.argErr()
 | |
| 			}
 | |
| 
 | |
| 			command, args, err := middleware.SplitCommandAndArgs(p.tkn())
 | |
| 			if err != nil {
 | |
| 				return p.err("Parse", err.Error())
 | |
| 			}
 | |
| 
 | |
| 			shutdownfn := func() error {
 | |
| 				cmd := exec.Command(command, args...)
 | |
| 				cmd.Stdout = os.Stdout
 | |
| 				cmd.Stderr = os.Stderr
 | |
| 				err := cmd.Run()
 | |
| 				if err != nil {
 | |
| 					return err
 | |
| 				}
 | |
| 				return nil
 | |
| 			}
 | |
| 
 | |
| 			p.cfg.Shutdown = append(p.cfg.Shutdown, shutdownfn)
 | |
| 			return nil
 | |
| 		},
 | |
| 	}
 | |
| }
 |