Commit 35225fe2 authored by Matthew Holt's avatar Matthew Holt

Docs and comments, la la

parent 01266ece
......@@ -47,6 +47,7 @@ func (c *controller) Port() string {
return c.parser.cfg.Port
}
// Context returns the path scope that the Controller is in.
func (c *controller) Context() middleware.Path {
return middleware.Path(c.pathScope)
}
......@@ -5,10 +5,11 @@ import (
"fmt"
)
// dispenser is a type that gets exposed to middleware
// generators so that they can parse tokens to configure
// their instance. It basically dispenses tokens but can
// do so in a structured manner.
// dispenser is a type that dispenses tokens, similarly to
// a lexer, except that it can do so with some notion of
// structure. Its methods implement part of the
// middleware.Controller interface, so refer to that
// documentation for more info.
type dispenser struct {
filename string
cursor int
......@@ -18,15 +19,13 @@ type dispenser struct {
// Next loads the next token. Returns true if a token
// was loaded; false otherwise. If false, all tokens
// have been consumed.
// TODO: Have the other Next functions call this one...?
// have already been consumed.
func (d *dispenser) Next() bool {
if d.cursor >= len(d.tokens)-1 {
return false
} else {
if d.cursor < len(d.tokens)-1 {
d.cursor++
return true
}
return false
}
// NextArg loads the next token if it is on the same
......@@ -49,8 +48,10 @@ func (d *dispenser) NextArg() bool {
return false
}
// TODO: Assert that there's a line break and only advance
// the token if that's the case? (store an error otherwise)
// NextLine loads the next token only if it is not on the same
// line as the current token, and returns true if a token was
// loaded; false otherwise. If false, there is not another token
// or it is on the same line.
func (d *dispenser) NextLine() bool {
if d.cursor < 0 {
d.cursor++
......@@ -96,7 +97,8 @@ func (d *dispenser) NextBlock() bool {
return true
}
// Val gets the text of the current token.
// Val gets the text of the current token. If there is no token
// loaded, it returns empty string.
func (d *dispenser) Val() string {
if d.cursor < 0 || d.cursor >= len(d.tokens) {
return ""
......@@ -105,23 +107,6 @@ func (d *dispenser) Val() string {
}
}
// ArgErr returns an argument error, meaning that another
// argument was expected but not found. In other words,
// a line break or open curly brace was encountered instead of
// an argument.
func (d *dispenser) ArgErr() error {
if d.Val() == "{" {
return d.Err("Unexpected token '{', expecting argument")
}
return d.Err("Unexpected line break after '" + d.Val() + "' (missing arguments?)")
}
// Err generates a custom parse error with a message of msg.
func (d *dispenser) Err(msg string) error {
msg = fmt.Sprintf("%s:%d - Parse error: %s", d.filename, d.tokens[d.cursor].line, msg)
return errors.New(msg)
}
// Args is a convenience function that loads the next arguments
// (tokens on the same line) into an arbitrary number of strings
// pointed to in targets. If there are fewer tokens available
......@@ -157,3 +142,20 @@ func (d *dispenser) RemainingArgs() []string {
return args
}
// ArgErr returns an argument error, meaning that another
// argument was expected but not found. In other words,
// a line break or open curly brace was encountered instead of
// an argument.
func (d *dispenser) ArgErr() error {
if d.Val() == "{" {
return d.Err("Unexpected token '{', expecting argument")
}
return d.Err("Unexpected line break after '" + d.Val() + "' (missing arguments?)")
}
// Err generates a custom parse error with a message of msg.
func (d *dispenser) Err(msg string) error {
msg = fmt.Sprintf("%s:%d - Parse error: %s", d.filename, d.tokens[d.cursor].line, msg)
return errors.New(msg)
}
......@@ -119,13 +119,18 @@ func (p *parser) parseOne() error {
// executes the top-level functions (the generator function)
// to expose the second layers which are the actual middleware.
// This function should be called only after p has filled out
// p.other and that the entire server block has been consumed.
// p.other and the entire server block has already been consumed.
func (p *parser) unwrap() error {
if len(p.other) == 0 {
// no middlewares were invoked
return nil
}
for _, directive := range registry.ordered {
// TODO: For now, we only support the first and default path scope ("/")
// but when we implement support for path scopes, we will have to
// change this logic to loop over them and order them. We need to account
// for situations where multiple path scopes overlap, regex (??), etc...
// TODO: For now, we only support the first and default path scope ("/", held in p.other[0])
// but when we implement support for path scopes, we will have to change this logic
// to loop over them and order them. We need to account for situations where multiple
// path scopes overlap, regex (??), etc...
if disp, ok := p.other[0].directives[directive]; ok {
if generator, ok := registry.directiveMap[directive]; ok {
mid, err := generator(disp)
......@@ -141,6 +146,7 @@ func (p *parser) unwrap() error {
}
}
}
return nil
}
......
......@@ -11,6 +11,11 @@ import (
"github.com/mholt/caddy/middleware"
)
// Gzip is a http.Handler middleware type which gzips HTTP responses.
type Gzip struct {
Next http.HandlerFunc
}
// New creates a new gzip middleware instance.
func New(c middleware.Controller) (middleware.Middleware, error) {
return func(next http.HandlerFunc) http.HandlerFunc {
......@@ -19,12 +24,6 @@ func New(c middleware.Controller) (middleware.Middleware, error) {
}, nil
}
// Gzip is a http.Handler middleware type which gzips HTTP responses.
type Gzip struct {
Next http.HandlerFunc
// TODO: Compression level, other settings
}
// ServeHTTP serves a gzipped response if the client supports it.
func (g Gzip) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if !strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") {
......
......@@ -13,23 +13,76 @@ type (
// and returns the inner layer, which is the actual HandlerFunc.
Middleware func(http.HandlerFunc) http.HandlerFunc
// Controller is the type which middleware generators use to access
// tokens and the server and any other information they need to
// configure themselves.
// A Control provides structured access to tokens from a configuration file
// and also to properties of the server being configured. Middleware generators
// use a Controller to construct their middleware instance.
Controller interface {
// Next loads the next token. Returns true if a token
// was loaded; false otherwise. If false, all tokens
// have already been consumed.
Next() bool
// NextArg loads the next token if it is on the same
// line. Returns true if a token was loaded; false
// otherwise. If false, all tokens on the line have
// been consumed.
NextArg() bool
// NextLine loads the next token only if it is NOT on the same
// line as the current token, and returns true if a token was
// loaded; false otherwise. If false, there is not another token
// or it is on the same line.
NextLine() bool
// NextBlock advances the cursor to the next token only
// if the current token is an open curly brace on the
// same line. If so, that token is consumed and this
// function will return true until the closing curly
// brace gets consumed by this method. Usually, you would
// use this as the condition of a for loop to parse
// tokens while being inside a block.
NextBlock() bool
// Val gets the text of the current token.
Val() string
// Args is a convenience function that loads the next arguments
// (tokens on the same line) into an arbitrary number of strings
// pointed to in arguments. If there are fewer tokens available
// than string pointers, the remaining strings will not be changed
// and false will be returned. If there were enough tokens available
// to fill the arguments, then true will be returned.
Args(...*string) bool
// RemainingArgs is a convenience function that loads any more arguments
// (tokens on the same line) into a slice and returns them. If an open curly
// brace token is encountered before the end of the line, that token is
// considered the end of the arguments (and the curly brace is not consumed).
RemainingArgs() []string
// ArgErr returns an argument error, meaning that another
// argument was expected but not found. In other words,
// a line break, EOF, or open curly brace was encountered instead of
// an argument.
ArgErr() error
// Err generates a custom parse error with a message of msg.
Err(string) error
// Startup registers a function to execute when the server starts.
Startup(func() error)
// Root returns the file path from which the server is serving.
Root() string
// Host returns the hostname the server is bound to.
Host() string
// Port returns the port that the server is listening on.
Port() string
// Context returns the path scope that the Controller is in.
// Note: This is not currently used, but may be in the future.
Context() Path
}
)
......@@ -71,7 +71,6 @@ func (s *Server) Serve() error {
server := &http.Server{
Addr: s.config.Address(),
Handler: s,
// TODO: Make more of the server configurable, also more http2 configurability
}
http2.ConfigureServer(server, nil) // TODO: This may not be necessary after HTTP/2 merged into std lib
......
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