Commit 5ae1790e authored by Matthew Holt's avatar Matthew Holt

Moved controller into its own file; other minor cleanups

parent 16997d85
package config
// controller is a dispenser of tokens and also
// facilitates setup with the server by providing
// access to its configuration. It implements
// the middleware.Controller interface.
type controller struct {
dispenser
}
// newController returns a new controller.
func newController(p *parser) *controller {
return &controller{
dispenser: dispenser{
cursor: -1,
parser: p,
},
}
}
// Startup registers a function to execute when the server starts.
func (c *controller) Startup(fn func() error) {
c.parser.cfg.Startup = append(c.parser.cfg.Startup, fn)
}
// Root returns the server root file path.
func (c *controller) Root() string {
if c.parser.cfg.Root == "" {
return "."
} else {
return c.parser.cfg.Root
}
}
// Host returns the hostname the server is bound to.
func (c *controller) Host() string {
return c.parser.cfg.Host
}
// Port returns the port that the server is listening on.
func (c *controller) Port() string {
return c.parser.cfg.Port
}
...@@ -11,8 +11,8 @@ import ( ...@@ -11,8 +11,8 @@ import (
// a particular directive and populates the config. // a particular directive and populates the config.
type dirFunc func(*parser) error type dirFunc func(*parser) error
// validDirectives is a map of valid directive names to // validDirectives is a map of valid, built-in directive names
// their parsing function. // to their parsing function.
var validDirectives map[string]dirFunc var validDirectives map[string]dirFunc
func init() { func init() {
......
...@@ -5,54 +5,10 @@ import ( ...@@ -5,54 +5,10 @@ import (
"fmt" "fmt"
) )
// newController returns a new controller.
func newController(p *parser) *controller {
return &controller{
dispenser: dispenser{
cursor: -1,
parser: p,
},
}
}
// controller is a dispenser of tokens and also
// facilitates setup with the server by providing
// access to its configuration. It implements
// the middleware.Controller interface.
type controller struct {
dispenser
}
// Startup registers a function to execute when the server starts.
func (c *controller) Startup(fn func() error) {
c.parser.cfg.Startup = append(c.parser.cfg.Startup, fn)
}
// Root returns the server root file path.
func (c *controller) Root() string {
if c.parser.cfg.Root == "" {
return "."
} else {
return c.parser.cfg.Root
}
}
// Host returns the hostname the server is bound to.
func (c *controller) Host() string {
return c.parser.cfg.Host
}
// Port returns the port that the server is listening on.
func (c *controller) Port() string {
return c.parser.cfg.Port
}
// dispenser is a type that gets exposed to middleware // dispenser is a type that gets exposed to middleware
// generators so that they can parse tokens to configure // generators so that they can parse tokens to configure
// their instance. // their instance. It basically dispenses tokens but can
// TODO: Rename this; it does more than dispense tokens. // do so in a structured manner.
// It also provides access to the server to touch its
// configuration.
type dispenser struct { type dispenser struct {
parser *parser parser *parser
cursor int cursor int
...@@ -115,7 +71,9 @@ func (d *dispenser) NextLine() bool { ...@@ -115,7 +71,9 @@ func (d *dispenser) NextLine() bool {
// if the current token is an open curly brace on the // if the current token is an open curly brace on the
// same line. If so, that token is consumed and this // same line. If so, that token is consumed and this
// function will return true until the closing curly // function will return true until the closing curly
// brace is consumed by this method. // brace is consumed by this method. Usually, you would
// use this as the condition of a for loop to parse
// tokens while being inside the block.
func (d *dispenser) NextBlock() bool { func (d *dispenser) NextBlock() bool {
if d.nesting > 0 { if d.nesting > 0 {
d.Next() d.Next()
......
...@@ -62,7 +62,7 @@ func (p *parser) addressBlock() error { ...@@ -62,7 +62,7 @@ func (p *parser) addressBlock() error {
// openCurlyBrace expects the current token to be an // openCurlyBrace expects the current token to be an
// opening curly brace. This acts like an assertion // opening curly brace. This acts like an assertion
// because it returns an error if the token is not // because it returns an error if the token is not
// a opening curly brace. // a opening curly brace. It does not advance the token.
func (p *parser) openCurlyBrace() error { func (p *parser) openCurlyBrace() error {
if p.tkn() != "{" { if p.tkn() != "{" {
return p.syntaxErr("{") return p.syntaxErr("{")
...@@ -73,7 +73,7 @@ func (p *parser) openCurlyBrace() error { ...@@ -73,7 +73,7 @@ func (p *parser) openCurlyBrace() error {
// closeCurlyBrace expects the current token to be // closeCurlyBrace expects the current token to be
// a closing curly brace. This acts like an assertion // a closing curly brace. This acts like an assertion
// because it returns an error if the token is not // because it returns an error if the token is not
// a closing curly brace. // a closing curly brace. It does not advance the token.
func (p *parser) closeCurlyBrace() error { func (p *parser) closeCurlyBrace() error {
if p.tkn() != "}" { if p.tkn() != "}" {
return p.syntaxErr("}") return p.syntaxErr("}")
...@@ -84,32 +84,80 @@ func (p *parser) closeCurlyBrace() error { ...@@ -84,32 +84,80 @@ func (p *parser) closeCurlyBrace() error {
// directives parses through all the directives // directives parses through all the directives
// and it expects the current token to be the first // and it expects the current token to be the first
// directive. It goes until EOF or closing curly // directive. It goes until EOF or closing curly
// brace. // brace which ends the address block.
func (p *parser) directives() error { func (p *parser) directives() error {
for p.next() { for p.next() {
if p.tkn() == "}" { if p.tkn() == "}" {
// end of address scope // end of address scope
break break
} }
if fn, ok := validDirectives[p.tkn()]; ok { if p.tkn()[0] == '/' {
err := fn(p) // Path scope (a.k.a. location context)
if err != nil { // TODO: The parser can handle the syntax (obviously), but the
return err // implementation is incomplete. This is intentional,
// until we can better decide what kind of feature set we
// want to support. Until this is ready, we leave this
// syntax undocumented.
// location := p.tkn()
if !p.next() {
return p.eofErr()
} }
} else if middlewareRegistered(p.tkn()) {
err := p.collectTokens() err := p.openCurlyBrace()
if err != nil { if err != nil {
return err return err
} }
} else {
return p.err("Syntax", "Unexpected token '"+p.tkn()+"', expecting a valid directive") for p.next() {
err := p.closeCurlyBrace()
if err == nil { // end of location context
break
}
// TODO: How should we give the context to the directives?
// Or how do we tell the server that these directives should only
// be executed for requests routed to the current path?
err = p.directive()
if err != nil {
return err
}
}
} else if err := p.directive(); err != nil {
return err
}
}
return nil
}
// directive asserts that the current token is either a built-in
// directive or a registered middleware directive; otherwise an error
// will be returned.
func (p *parser) directive() error {
if fn, ok := validDirectives[p.tkn()]; ok {
// Built-in (standard) directive
err := fn(p)
if err != nil {
return err
}
} else if middlewareRegistered(p.tkn()) {
// Middleware directive
err := p.collectTokens()
if err != nil {
return err
} }
} else {
return p.err("Syntax", "Unexpected token '"+p.tkn()+"', expecting a valid directive")
} }
return nil return nil
} }
// collectTokens consumes tokens until the directive's scope // collectTokens consumes tokens until the directive's scope
// closes (either end of line or end of curly brace block). // closes (either end of line or end of curly brace block).
// It creates a controller which is stored in the parser for
// later use by the middleware.
func (p *parser) collectTokens() error { func (p *parser) collectTokens() error {
directive := p.tkn() directive := p.tkn()
line := p.line() line := p.line()
......
...@@ -15,10 +15,6 @@ func New(c middleware.Controller) (middleware.Middleware, error) { ...@@ -15,10 +15,6 @@ func New(c middleware.Controller) (middleware.Middleware, error) {
} }
return func(next http.HandlerFunc) http.HandlerFunc { return func(next http.HandlerFunc) http.HandlerFunc {
head := Headers{ return Headers{Next: next, Rules: rules}.ServeHTTP
Next: next,
Rules: rules,
}
return head.ServeHTTP
}, nil }, nil
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment