web

package
v1.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 21, 2015 License: MIT Imports: 15 Imported by: 0

Documentation

Overview

Extra datasources for Web servers.

Index

Constants

View Source
const ContentEncoding = "web.ContentEncoding"

Variables

This section is empty.

Functions

func Flush

func Flush(cxt cookoo.Context, params *cookoo.Params) (interface{}, cookoo.Interrupt)

Flush sends content to output.

If no writer is specified, this will attempt to write to whatever is in the Context with the key "http.ResponseWriter". If no suitable writer is found, it will not write to anything at all.

Params:

  • writer: A Writer of some sort. This will try to write to the HTTP response if no writer is specified.
  • content: The content to write as a body. If this is a byte[], it is sent unchanged. Otherwise. we first try to convert to a string, then pass it into a writer.
  • contentType: The content type header (e.g. text/html). Default is text/plain
  • responseCode: Integer HTTP Response Code: Default is `http.StatusOK`.
  • headers: a map[string]string of HTTP headers. The keys will be run through http.CannonicalHeaderKey()

Note that this is optimized for writing from strings or arrays, not Readers. For larger objects, you may find it more efficient to use a different command.

Context: - If this finds `web.ContentEncoding`, it will set a content-encoding header.

Returns

  • boolean true

func GuessContentType added in v1.3.0

func GuessContentType(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt)

GuessContentType guesses the MIME type of a given name.

Name should be a path-like thing with an extension. E.g. foo.html, foo/bar/baz.css

If this detects a file with extensions like gz, zip, or Z, it will also set the context `web.ContentEncoding` to the appropriate encoding.

Params:

  • name (string): The filename-like thing to use to guess the content type.

Returns:

string content-type

func RenderHTML

func RenderHTML(cxt cookoo.Context, params *cookoo.Params) (interface{}, cookoo.Interrupt)

RenderHTML renders an HTML template.

This uses the `html/template` system built into Go to render data into a writer.

Params:

  • template (required): An html/templates.Template object.
  • templateName (required): The name of the template to render.
  • values: An interface{} with the values to be passed to the template. If this is not specified, the contents of the Context are passed as a map[string]interface{}. Note that datasources, in this model, are not accessible to the template.
  • writer: The writer that data should be sent to. By default, this will create a new Buffer and put it into the context. (If no Writer was passed in, the returned writer is actually a bytes.Buffer.) To flush the contents directly to the client, you can use `.Using('writer').From('http.ResponseWriter')`.

Returns

  • An io.Writer. The template's contents have already been written into the writer.

Example:

reg.Route("GET /html", "Test HTML").
	Does(cookoo.AddToContext, "_").
		Using("Title").WithDefault("Hello World").
		Using("Body").WithDefault("This is the body.").
	Does(web.RenderHTML, "render").
		Using("template").From('cxt:templateCache').
		Using("templateName").WithDefault("index.html").
	Does(web.Flush, "_").
		Using("contentType").WithDefault("text/html").
		Using("content").From("cxt:render")

In the example above, we do three things:

  • Add Title and Body to the context. For the template rendered, it will see these as {{.Title}} and {{.Body}}.
  • Render the template located in a local file called "index.html". It is recommended that a template.Template object be created at startup. This way, all of the templates can be cached immediately and shared throughout processing.
  • Flush the result out to the client. This gives you a chance to add any additional headers.

func Serve

func Serve(reg *cookoo.Registry, router *cookoo.Router, cxt cookoo.Context)

Serve creates a new Cookoo web server.

Important details:

  • A URIPathResolver is used for resolving request names.
  • The following datasources are added to the Context:
  • url: A URLDatasource (Provides access to parts of the URL)
  • path: A PathDatasource (Provides access to parts of a path. E.g. "/foo/bar")
  • query: A QueryParameterDatasource (Provides access to URL query parameters.)
  • post: A FormValuesDatasource (Provides access to form data or the body of a request.)
  • The following context variables are set:
  • http.Request: A pointer to the http.Request object
  • http.ResponseWriter: The response writer.
  • server.Address: The server's address and port (NOT ALWAYS PRESENT)
  • The handler includes logic to redirect "not found" errors to a path named "@404" if present.

Context Params:

  • server.Address: If this key exists in the context, it will be used to determine the host/port the server runes on. EXPERIMENTAL. Default is ":8080".

Example:

package main

import (
  //This is the path to Cookoo
  "github.com/Masterminds/cookoo"
  "github.com/Masterminds/cookoo/web"
  "fmt"
)

func main() {
  // Build a new Cookoo app.
  registry, router, context := cookoo.Cookoo()

  // Fill the registry.
  registry.Route("GET /", "The index").Does(web.Flush, "example").
    Using("content").WithDefault("Hello World")

  // Create a server
  web.Serve(reg, router, cookoo.SyncContext(cxt))
}

Note that we synchronize the context before passing it into Serve(). This is optional because each handler gets its own copy of the context already. However, if commands pass the context to goroutines, the context ought to be synchronized to avoid race conditions.

Note that copies of the context are not synchronized with each other. So by declaring the context synchronized here, you are not therefore synchronizing across handlers.

func ServeFiles

func ServeFiles(cxt cookoo.Context, params *cookoo.Params) (interface{}, cookoo.Interrupt)

ServeFiles is a cookoo command to serve files from a set of filesystem directories.

If no writer is specified, this will attempt to write to whatever is in the Context with the key "http.ResponseWriter". If no suitable writer is found, it will not write to anything at all.

Example:

registry.Route("GET /**", "Serve assets").
    Does(web.ServeFiles, "fileServer").
       Using("directory").WithDefault("static")

Example 2:

registry.Route("GET /foo/**", "Serve assets").
    Does(web.ServeFiles, "fileServer").
        Using("directory").WithDefault("static").
        Using("removePrefix").WithDefault("/foo")

Params:

  • directory: A directory to serve files from.
  • removePrefix: A prefix to remove from the url before looking for it on the filesystem.
  • writer: A Writer of some sort. This will try to write to the HTTP response if no writer is specified.
  • request: A request of some sort. This will try to use the HTTP request if no request is specified.

func ServeTLS added in v1.2.0

func ServeTLS(reg *cookoo.Registry, router *cookoo.Router, cxt cookoo.Context, certFile, keyFile string)

ServeTLS does the same as Serve, but with SSL support.

If `server.Address` is not found in the context, the default address is `:4433`.

Neither certFile nor keyFile are stored in the context. These values are considered to be security sensitive.

func ServerInfo

func ServerInfo(cxt cookoo.Context, params *cookoo.Params) (interface{}, cookoo.Interrupt)

ServerInfo gets the server info for this request.

This assumes that `http.Request` and `http.ResponseWriter` are in the context, which they are by default.

Returns:

  • boolean true

Types

type CookooHandler

type CookooHandler struct {
	Registry    *cookoo.Registry
	Router      *cookoo.Router
	BaseContext cookoo.Context
}

The handler for Cookoo. You way use this handler in your own web apps, or you can use the Serve() function to create and manage a handler for you.

func NewCookooHandler

func NewCookooHandler(reg *cookoo.Registry, router *cookoo.Router, cxt cookoo.Context) *CookooHandler

Create a new Cookoo HTTP handler.

This will create an HTTP hanlder, but will not automatically attach it to a server. Implementors can take the handler and attach it to an existing HTTP server wiht http.HandleFunc() or http.ListenAndServe().

For simple web servers, using this package's Serve() function may be the easier route.

Important details:

- A URIPathResolver is used for resolving request names. - The following datasources are added to the Context:

  • url: A URLDatasource (Provides access to parts of the URL)
  • path: A PathDatasource (Provides access to parts of a path. E.g. "/foo/bar")
  • query: A QueryParameterDatasource (Provides access to URL query parameters.)
  • post: A FormValuesDatasource (Provides access to form data or the body of a request.)

- The following context variables are set:

  • http.Request: A pointer to the http.Request object
  • http.ResponseWriter: The response writer.
  • server.Address: The server's address and port (NOT ALWAYS PRESENT)

func (*CookooHandler) ServeHTTP

func (h *CookooHandler) ServeHTTP(res http.ResponseWriter, req *http.Request)

ServeHTTP is the Cookoo request handling function.

This is capable of handling HTTP and HTTPS requests.

type FormValuesDatasource

type FormValuesDatasource struct {
	// contains filtered or unexported fields
}

Access to name/value pairs in POST/PUT form data from the body. This will attempt to access form data supplied in the HTTP request's body. If the MIME type is not correct or if there is no POST data, no data will be made available.

Parsing is lazy: No form data is parsed until it is requested.

func (*FormValuesDatasource) Init

func (*FormValuesDatasource) Value

func (f *FormValuesDatasource) Value(name string) interface{}

The return value will always be a string or nil. To match the interface, we use interface{}.

type PathDatasource

type PathDatasource struct {
	PathParts []string
}

func (*PathDatasource) Init

func (d *PathDatasource) Init(path string) *PathDatasource

func (*PathDatasource) Value

func (d *PathDatasource) Value(name string) interface{}

type QueryParameterDatasource

type QueryParameterDatasource struct {
	Parameters url.Values
}

Get the query parameters by name.

func (*QueryParameterDatasource) Init

func (*QueryParameterDatasource) Value

func (d *QueryParameterDatasource) Value(name string) interface{}

type RequestHeaderDatasource added in v1.2.0

type RequestHeaderDatasource struct {
	// contains filtered or unexported fields
}

func (*RequestHeaderDatasource) Init added in v1.2.0

func (*RequestHeaderDatasource) Value added in v1.2.0

func (r *RequestHeaderDatasource) Value(name string) interface{}

type SessionDatasource

type SessionDatasource interface {
	StartSession(res http.ResponseWriter, req *http.Request) bool
	ClearSession(res http.ResponseWriter, req *http.Request) bool
}

This provides a datasource for session data.

Sessions differ a little from the other web datasources in that they may need explicit app-controlled initialization.

type URIPathResolver

type URIPathResolver struct {
	// contains filtered or unexported fields
}

Resolver for transforming a URI path into a route.

This is a more sophisticated path resolver, aware of heirarchyand wildcards.

Examples: - URI path `/foo` matches the entry `/foo` - URI path `/foo/bar` could match entries like `/foo/*`, `/foo/**`, and `/foo/bar` - URI path `/foo/bar/baz` could match `/foo/*/baz` and `/foo/**`

HTTP Verbs: This resolver also allows you to specify verbs at the beginning of a path:

  • "GET /foo" and "POST /foo" are separate (but legal) paths. "* /foo" will allow any verb.
  • There are no constrainst on verb name. Thus, verbs like WebDAV's PROPSET are fine, too. Or you can make up your own.

IMPORTANT! When it comes to matching route patterns against paths, ORDER IS IMPORTANT. Routes are evaluated in order. So if two rules (/a/b* and /a/bc) are both defined, the incomming request /a/bc will match whichever route is defined first. See the unit tests for examples.

The `**` and `/**` Wildcards: =============================

In addition to the paths described in the `path` package of Go's core, two extra wildcard sequences are defined:

- `**`: Match everything. - `/**`: a suffix that matches any sub-path.

The `**` wildcard works in ONLY ONE WAY: If the path is declared as `**`, with nothing else, then any path will match.

VALID: `**`, `GET /foo/**`, `GET /**` NOT VALID: `GET **`, `**/foo`, `foo/**/bar`

The `/**` suffix can only be added to the end of a path, and says "Match anything under this".

Examples:

  • URI paths "/foo", "GET /a/b/c", and "hello" all match "**". (The ** rule can be very dangerous for this reason.)
  • URI path "/assets/images/foo/bar/baz.jpg" matches "/assets/**"

The behavior for rules that contain `/**` anywhere other than the end have undefined behavior.

func NewURIPathResolver

func NewURIPathResolver(reg *cookoo.Registry) *URIPathResolver

Creates a new URIPathResolver.

func (*URIPathResolver) Init

func (r *URIPathResolver) Init(registry *cookoo.Registry)

func (*URIPathResolver) Resolve

func (r *URIPathResolver) Resolve(pathName string, cxt cookoo.Context) (string, error)

Resolve a path name based using path patterns.

This resolver is designed to match path-like strings to path patterns. For example, the path `/foo/bar/baz` may match routes like `/foo/*/baz` or `/foo/bar/*`

type URLDatasource

type URLDatasource struct {
	URL *url.URL
}

The datasource for URLs. This datasource knows the following items:

  • url: the URL struct
  • scheme: The scheme of the URL as a string
  • opaque: The opaque identifier
  • user: A *Userinfo
  • host: The string hostname
  • path: The entire path
  • rawquery: The query string, not decoded.
  • fragment: The fragment string.
  • query: The array of Query parameters. Usually it is better to use the 'query:foo' syntax.

func (*URLDatasource) Init

func (d *URLDatasource) Init(parsedUrl *url.URL) *URLDatasource

func (*URLDatasource) Value

func (d *URLDatasource) Value(name string) interface{}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL