Documentation ¶
Overview ¶
Package web is a very lightweight framework for web applications.
It adds clean seamless and easy to use support for:
- access logging
- pipelines
- template management
- shared storage
- ...
TEMPLATES ¶
Templates support optimized management of templates for the whole application.
The model is as below:
- Each view page (e.g. landing page) corresponds to a given Template (set)
- A config file defines the templates, so we can re-use templates
- A Tree is used, so that a TemplateSet can be easily configured to share templates. E.g. All the core templates share the same header and footers.
Typical usage for loading from within main app
vcn = new(web.ViewConfigNode) myVfs = new(util.VFS) err = myVfs.AddIfExist("templates.zip", "templates") f, err = os.Open("resources/core/web/views.json") err = json.NewDecoder(f).Decode(vcn) views = web.NewViews() views.FnMap["Eq"] = reflect.DeepEqual // MUST register functions BEFORE adding templates views.AddTemplates(myVfs, regexp.MustCompile(`.*\.thtml`)) // ... views.Load(vcn)
The View Handlers can call:
views.Views["core.landing"].Execute(writer, "main", data)
WEBSTORE ¶
WebStore allows us store information along with a namespace. It simply maintains a non-synchronized map[interface{}] map[string]interface{} for each namespace. It expects that the namespace represents usage within a single goroutine.
An example usage is within a web environment where the namespace can be the *http.Request object.
It is generally recommended to pass structures around in function calls. However, there may be times where using this is the only option, and in those situations, use with care.
It can be used in a web environment, where you want to store data on behalf of a request. In this context, the namespace is the request.
Index ¶
- Constants
- Variables
- func AddHandlerMessages(r *http.Request, w http.ResponseWriter, ckName string, ...) (err error)
- func NewCookie(host, name, value string, ttlsec int, encode bool) *http.Cookie
- func NewGzipWriterPool(level, initPoolLen, poolCap int) *pool.T
- type AccessLogger
- type BufferPipe
- type FlusherPipe
- type GzipPipe
- type HTTPServer
- type HandlerMessage
- type HttpHandlerPipe
- type Listener
- func (s *Listener) Accept() (c net.Conn, err error)
- func (s *Listener) Addr() net.Addr
- func (s *Listener) Close() (err error)
- func (s *Listener) HardPause()
- func (s *Listener) IsClosed() bool
- func (s *Listener) ResetMaxNumConn(maxNumConn int32)
- func (s *Listener) ResumeFromHardPause()
- func (s *Listener) Run(onClosed, onPaused, onRun func())
- func (s *Listener) WaitZeroInflight()
- type OnPanicFlags
- type Pipe
- type Pipeline
- type ResponseWriter
- type ViewConfigNode
- type Views
- type WebStore
Constants ¶
const FlashMessage = "FlashMessage"
const MinMimeSniffLen = 64 // 512 is default
Variables ¶
var ClosedErr = errors.New("<closed>")
Functions ¶
func AddHandlerMessages ¶
func AddHandlerMessages(r *http.Request, w http.ResponseWriter, ckName string, messages ...HandlerMessage, ) (err error)
func NewCookie ¶
Returns a new cookie. Note: NewCookie sets the domain from the Host if possible (as an appropriate .XYZ.tld) The cookie domain is only set if the app Host is not localhost, and is a real Hostname.
func NewGzipWriterPool ¶
Types ¶
type AccessLogger ¶
type AccessLogger struct {
// contains filtered or unexported fields
}
AccessLogger handles access logging, including opening/closing files and buffering output. It also acts as a pipe, so it can participate in the execution of a request.
func NewAccessLogger ¶
func NewAccessLogger(filename string) *AccessLogger
func (*AccessLogger) Close ¶
func (s *AccessLogger) Close() (err error)
func (*AccessLogger) Reopen ¶
func (s *AccessLogger) Reopen() (err error)
func (*AccessLogger) Reset ¶
func (s *AccessLogger) Reset(name string) (err error)
func (*AccessLogger) ServeHttpPipe ¶
func (s *AccessLogger) ServeHttpPipe(w ResponseWriter, r *http.Request, f *Pipeline)
log access in the combined log format.
type BufferPipe ¶
type BufferPipe struct {
// contains filtered or unexported fields
}
BufferPipe allows you use a Buffer, especially close to the lowest handler, to ensure that handlers up the chain do not get results in tiny quantities.
Templates may write out results in bytes of length 1, 2, 17, etc. Some pipes may need to determine the content type before converting the result (e.g. gzip pipe). BufferPipe helps here.
func NewBufferPipe ¶
func NewBufferPipe(size, initPoolLen, poolCap int) (s *BufferPipe)
func (*BufferPipe) ServeHttpPipe ¶
func (s *BufferPipe) ServeHttpPipe(w ResponseWriter, r *http.Request, f *Pipeline)
type FlusherPipe ¶
type FlusherPipe struct{}
Flusher pipe just does a flush after calling Next. May be a good candidate to put on the end of the pipeline closest. This way, it calls Flush across the whole pipeline chain.
func (FlusherPipe) ServeHttpPipe ¶
func (s FlusherPipe) ServeHttpPipe(w ResponseWriter, r *http.Request, f *Pipeline)
type GzipPipe ¶
type GzipPipe struct {
// contains filtered or unexported fields
}
GzipPipe will convert http responseWriter to write out the compressed bits if accept-encoding contains gzip, and deciphered content-type is text/* or matches typical text types (xml, html, json, javascript, css).
func NewGzipPipe ¶
func (*GzipPipe) ServeHttpPipe ¶
func (s *GzipPipe) ServeHttpPipe(w ResponseWriter, r *http.Request, f *Pipeline)
type HTTPServer ¶
Server implements net.Listener and http.Handler.
Typical Usage:
l, err = net.Listen("tcp", ":8080") lis = web.NewListener(l, 1000, OnPanicRecover) httpWebSvr = web.NewServer(lis) httpWebSvr.AddPipe(web.HttpHandlerPipe{myHandler}) http.Serve(httpWebSvr, httpWebSvr)
func (*HTTPServer) ServeHTTP ¶
func (s *HTTPServer) ServeHTTP(w http.ResponseWriter, r *http.Request)
ServeHTTP serves the request as a pipeline.
func (*HTTPServer) ServeHttpPipe ¶
func (s *HTTPServer) ServeHttpPipe(w ResponseWriter, r *http.Request, f *Pipeline)
type HandlerMessage ¶
type HttpHandlerPipe ¶
Wraps a standard http.Handler into a Pipe. It calls its ServeHTTP, and then calls pipeline's next.
func (HttpHandlerPipe) ServeHttpPipe ¶
func (h HttpHandlerPipe) ServeHttpPipe(w ResponseWriter, r *http.Request, f *Pipeline)
ServeHttpPipe calls the wrapped Handlers ServeHTTP, calls pipeline's next.
type Listener ¶
type Listener struct {
// contains filtered or unexported fields
}
Listener implements net.Listener
It keeps track of connections doing work. It will pause accepting new connections if maxConn is above a given max, and resume accepting when below.
It will also close gracefully, giving in-flight requests time to shutdown gracefully.
Closing the listener also returns an appropriate error (ClosedErr) so that users know that it was closed gracefully.
func NewListener ¶
func NewListener(l net.Listener, maxNumConn int32, panicFlags OnPanicFlags) (s *Listener)
Return a new listener.
func (*Listener) ResetMaxNumConn ¶
func (*Listener) ResumeFromHardPause ¶
func (s *Listener) ResumeFromHardPause()
func (*Listener) WaitZeroInflight ¶
func (s *Listener) WaitZeroInflight()
type OnPanicFlags ¶
type OnPanicFlags uint8
const ( OnPanicRecover OnPanicFlags = 1 << iota OnPanicLogStack OnPanicLog OnPanicAll = 0xff // convenience all flags set )
type Pipe ¶
type Pipe interface {
ServeHttpPipe(w ResponseWriter, r *http.Request, f *Pipeline)
}
Pipe is a step in handling a web request. A Pipe can do some work, call the next pipe in the chain, and finish up its work when that returns.
Note that Pipes should still be smart about when to call Flush. The general guideline is that Pipes that do internally buffering should call Flush at the end of their ServeHttpPipe (after calling Pipeline.Next).
type Pipeline ¶
type Pipeline struct {
// contains filtered or unexported fields
}
Pipeline contains a sequence of pipes, which work together to handle a request. You can have an accesslogger, security checker, gzipper, etc in the pipeline.
func NewPipeline ¶
type ResponseWriter ¶
type ResponseWriter interface { http.ResponseWriter http.CloseNotifier http.Flusher http.Hijacker // Write(b []byte) (i int, err error) // Header() http.Header // WriteHeader(code int) // Flush() // CloseNotify() <-chan bool // Hijack() (net.Conn, *bufio.ReadWriter, error) IsHeaderWritten() bool NumBytesWritten() int64 ResponseCode() int }
ResponseWriter is a fat interface encompassing http.ResponseWriter, and adding all net/http responsewriter interfaces (Hijacker, Flusher, CloseNotifier). This is done so that all pipe writers can be hijacked, flushed, etc. It also adds some tracking methods.
func AsResponseWriter ¶
func AsResponseWriter(w http.ResponseWriter) ResponseWriter
type ViewConfigNode ¶
type ViewConfigNode struct { Name string AliasTo string Parent *ViewConfigNode Children []*ViewConfigNode Views map[string]string }
A node that is parseable from an external source, that defines a tree of configured views. Each view is eventually used to construct a template.Set
type Views ¶
type Views struct { FnMap template.FuncMap Views map[string]*template.Template // contains filtered or unexported fields }
Manage all the template sets for the application. Web Handlers should call TemplateSet.Execute(...) to render their content. Note that we really share templates (ie by sharing the actual parse trees).
func (*Views) AddTemplates ¶
An app can call this function multiple times passing a VFS and a regexp. It will Load all the templates matching that regexp, and parse them. (We need to add funcMap so that we can parse/find functions defined at parse time, etc).
func (*Views) Load ¶
func (views *Views) Load(vcn *ViewConfigNode) (err error)
This is called after templates have been found. Using the map, it will create TemplateSets for each view (sharing templates performantly)
type WebStore ¶
type WebStore struct {
// contains filtered or unexported fields
}
func NewWebStore ¶
func NewWebStore() *WebStore
func (*WebStore) Clear ¶
func (rc *WebStore) Clear(ns interface{})
Ensure this clear method is called at the appropriate time to clear out the namespace entries.
For example, in a web context, where information is stored on behalf of the request, ensure this method is called at the end of the request.