router

package
v2.3.3+incompatible Latest Latest
Warning

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

Go to latest
Published: Mar 7, 2019 License: OSL-3.0 Imports: 25 Imported by: 0

README

Router Module

Provides basic routing functionality for flamingo

You can use this package either standalone, or together with the prefixrouter

Basic Routing concept

For the path of an url a standard routing concept is applied, where at the end the URL is matched to a controller.

  • a route is assigned to a handle. (A handle is a string that represents a unique name). A handle can be something like "cms.page.view"
  • for a handle a Controller can be registered. The indirection through handles allows us to register different controllers for certain handlers in different contexts.

Routes can be configured the following ways (See Basic Usage below):

  • Via router.Registry in your modules initialisation (typical in module.go)
  • As part of the project configuration. This again allows us to have different routing paths configured for different contexts.

Basic Usage:

Registering Routes in Modules

Routes are registered normaly during initialisation of your flamingo module.

In order to register new Routes you need to bind a new Router Module

router.Bind(injector, new(routes))

routes need to implement the type:

// Module defines a router Module, which is able to register routes
Module interface {
  Routes(registry *Registry)
}

Insides the Routes method you can then use the Registry to register new Routes.

For example:

func (r *routes) Routes(registry *router.Registry) {
	registry.Route("/hello", "hello")
	registry.HandleGet("hello", r.helloController.Get)
}
Registering Routes via Configuration

Add a routes.yml in your config folder like this:

- path: /
  name: index
  controller: flamingo.render(tpl="index")

- path: /anotherPath
  controller: flamingo.render(tpl="index")

- path: /redirect
  controller: flamingo.redirect(to="index")

You can use the flamingo default controllers (see below)

Routing Details

Route

A route defines a mapping from a path to a "handler identifier".

The handler identifier is used to easily support reverse routing and rewriting mechanisms.

Handler

A "handler identifier" can be mapped to one or more Actions, e.g.:

registry.HandleGet("hello", r.helloController.Get)
registry.HandlePost("hello", r.helloController.Get)
Data Controller

Views can request arbitrary data via the data template function.

Route Format

The route format is based on the format the Play Framework is using.

Essentially there are 4 types of parts, of which the route is constructed

Static

A piece which is just static, such as /foo/bar/asd.

Parameter

A part with a named parameter, /foo/:param/ which spans the request up to the next / or . (e.g. .html).

Regex

A (optionally named) regex parameter such as /foo/$param<[0-9]+> which captures everything the regex captures, where param in this example is the name of the parameter.

Wildcard

A wildcard which captures everything, such as /foo/bar/*param. Note that slashes are not escaped here!

Router Target

The target of a route is a controller name and optional attributes.

Parameters

Parameters are comma-separated identifiers.

If no parameters are specified and not brackets are used every route parameter is available as a parameter.

  • controller.view Get's all available parameters
  • controller.view(param1, param2) param1 and param2 will be set
  • controller.view(param1 ?= "foo", param2 = "bar") param1 is optional, if not specified it is set to "foo". param2 is always set to "bar".

If specified parameters don't have a value or optional value and are not part of the path, then they are taken from GET parameters.

Catchall

It is possible to specify a catchall address, which gets all parameters and applies all "leftover" as GET parameters, use * to indicate a catchall.

Example:

controller.view(param1, *)

This is quite helpful for reverse-routing.

Default Controller

Currently Flamingo registers the following controller:

  • flamingo.redirect(to, ...) Redirects to to. All other parameters (but to) are passed on as URL parameters
  • flamingo.redirectUrl(url) Redirects to url
  • flamingo.redirectPermanent(to, ...) Redirects permanently to to. All other parameters (but to) are passed on as URL parameters
  • flamingo.redirectPermanentUrl(url) Redirects permanently to url

Configured routes

Beside registering routes in the code it is also possible to register them in your routes.yml.

The root node consists of an array of objects with:

  • controller: must name a controller to execute
  • path: optional path where this is accessable
  • name: optional name where this will be available for reverse routing

Context routes always take precedence over normal routes!

Example
- path: /
  controller: flamingo.redirect(to="cms.page.view", name="home")
  name: home
- path: /home
  controller: cms.page.view(name="home")
- path: /special
  controller: cms.page.view(name?="special")

This will result in the following accessable routes:

  • /: Redirects to /home (because there is a route for cms.page.view with name set to home. Otherwise this would go to /cms/home)
  • /home: Shows cms.page.view(name="home")
  • /special: Shows cms.page.view(name="special")
  • /special?name=foo: Shows cms.page.view(name="foo") (optional argument retrieved from GET)

The / route is now also available as a controller named home, which is just an alias for calling the flamingo.redirect controller with the parameters to="cms.page.view" and name="home".

Router filter

Router filters can be used as middleware in the dispatching process. The filters are executed before the controller action. A router filter can be registered via dingo injection in module.go's Configure function:

func (m *Module) Configure(injector *dingo.Injector) {
	injector.BindMulti(new(router.Filter)).To(myFilter{})
}

A Filter must implement the router.Filter interface by providing a Filter function: Filter(ctx web.Context, w http.ResponseWriter, fc *FilterChain) web.Response.

The filters are handled in order of dingo.Modules as defined in flamingo.App() call. You will have to return chain.Next(ctx, w) in your Filter function to call the next filter. If you return something else, the chain will be aborted and the actual controller action will not be executed.

Documentation

Overview

Package provides basic routing functionality for flamingo

Index

Constants

View Source
const (
	// FlamingoError is the Controller name for errors
	FlamingoError = "flamingo.error"
	// FlamingoNotfound is the Controller name for 404 notfound
	FlamingoNotfound = "flamingo.notfound"

	// ERROR is used to bind errors to contexts
	ERROR errorKey = iota
)

Variables

View Source
var (

	// ControllerKey exposes the current controller/handler key
	ControllerKey, _ = tag.NewKey("controller")
)

Functions

func Bind

func Bind(injector *dingo.Injector, m Module)

Bind is a convenience helper to multi-bind router modules

Types

type Action

type Action func(ctx context.Context, req *web.Request) web.Response

Action defines an explicit http action

func HTTPAction

func HTTPAction(handler http.Handler) Action

HTTPAction wraps a default http.Handler to a flamingo router action

type ControllerOption

type ControllerOption string

ControllerOption defines a type for Controller options todo still usable?

type ControllerOptionAware

type ControllerOptionAware interface {
	CheckOption(option ControllerOption) bool
}

ControllerOptionAware is an interface for Controller which want to interact with filter todo still usable?

type DataAction

type DataAction func(ctx context.Context, req *web.Request) interface{}

DataAction is a method called which does not return the web response itself, but data instead

type EventRouterProvider

type EventRouterProvider func() event.Router

EventRouterProvider for event injection

type Filter

type Filter interface {
	Filter(ctx context.Context, r *web.Request, w http.ResponseWriter, fc *FilterChain) web.Response
}

Filter is an interface which can filter requests

type FilterChain

type FilterChain struct {
	Filters []Filter
}

FilterChain defines the chain which contains all filters which will be worked off

func (*FilterChain) Next

Next calls the next filter and deletes it of the chain

type FilterProvider

type FilterProvider func() []Filter

FilterProvider for filter injection

type Handler

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

Handler defines a concrete Controller

func (*Handler) GetHandlerName

func (handler *Handler) GetHandlerName() string

GetHandlerName getter

func (*Handler) GetPath

func (handler *Handler) GetPath() string

GetPath getter

func (*Handler) Normalize

func (handler *Handler) Normalize(params ...string) *Handler

Normalize enforces a normalization of passed parameters

type Match

type Match struct {
	Values map[string]string
}

Match is the result of matching a path

type Module

type Module interface {
	Routes(registry *Registry)
}

Module defines a router Module, which is able to register routes

type OnFinishEvent

type OnFinishEvent struct {
	ResponseWriter http.ResponseWriter
	Request        *http.Request
	Error          error
}

OnFinishEvent is the event object associated to OnFinish

type OnRequestEvent

type OnRequestEvent struct {
	ResponseWriter http.ResponseWriter
	Request        *http.Request
}

OnRequestEvent contains the bare request

type OnResponseEvent

type OnResponseEvent struct {
	Response       web.Response
	Request        *http.Request
	ResponseWriter http.ResponseWriter
}

OnResponseEvent is the event associated to OnResponse

type P

type P map[string]string

P is a shorthand for parameter

type Path

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

Path is a matchable routing path

func NewPath

func NewPath(path string) *Path

NewPath returns a new path

func (*Path) Match

func (p *Path) Match(path string) *Match

Match matches a given path

func (*Path) Render

func (p *Path) Render(values map[string]string, usedValues map[string]struct{}) (string, error)

Render a path for a given list of values

type Registry

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

Registry holds a list of all routes and handlers to be registered in modules.

We have: routes: key-params -> path, for reverse routes

path: url-pattern -> key+params

Handler: key -> Controller

func NewRegistry

func NewRegistry() *Registry

NewRegistry creates a new Registry

func (*Registry) Alias

func (registry *Registry) Alias(name, to string)

Alias for an existing router definition

func (*Registry) GetRoutes

func (registry *Registry) GetRoutes() []*Handler

GetRoutes returns registered Routes

func (*Registry) HandleAny

func (registry *Registry) HandleAny(name string, action Action)

HandleAny serves as a fallback to handle HTTP requests which are not taken care of by other handlers

func (*Registry) HandleData

func (registry *Registry) HandleData(name string, action DataAction)

HandleData sets the controllers data action

func (*Registry) HandleDelete

func (registry *Registry) HandleDelete(name string, action Action)

HandleDelete handles HTTP DELETE requests

func (*Registry) HandleGet

func (registry *Registry) HandleGet(name string, action Action)

HandleGet handles a HTTP GET request

func (*Registry) HandleHead

func (registry *Registry) HandleHead(name string, action Action)

HandleHead handles HTTP HEAD requests

func (*Registry) HandleMethod

func (registry *Registry) HandleMethod(method, name string, action Action)

HandleMethod handles requests for the specified HTTP Method

func (*Registry) HandleOptions

func (registry *Registry) HandleOptions(name string, action Action)

HandleOptions handles HTTP OPTIONS requests

func (*Registry) HandlePost

func (registry *Registry) HandlePost(name string, action Action)

HandlePost handles HTTP POST requests

func (*Registry) HandlePut

func (registry *Registry) HandlePut(name string, action Action)

HandlePut handles HTTP PUT requests

func (*Registry) Has

func (registry *Registry) Has(method, name string) bool

Has checks if a method is set for a given handler name

func (*Registry) HasAny

func (registry *Registry) HasAny(name string) bool

HasAny checks if an any handler is set for a given name

func (*Registry) HasData

func (registry *Registry) HasData(name string) bool

HasData checks if a data handler is set for a given name

func (*Registry) Reverse

func (registry *Registry) Reverse(name string, params map[string]string) (string, error)

Reverse builds the path from a named route with params

func (*Registry) Route

func (registry *Registry) Route(path, handler string) *Handler

Route assigns a route to a Handler

type RegistryProvider

type RegistryProvider func() []Module

RegistryProvider is called to retrieve registered routes

type Router

type Router struct {
	Sessions            sessions.Store      `inject:",optional"` // Sessions storage, which are used to retrieve user-context session
	SessionName         string              `inject:"config:session.name"`
	EventRouterProvider EventRouterProvider `inject:""`

	Injector               *dingo.Injector  `inject:""`
	RouterRegistryProvider RegistryProvider `inject:""`
	RouterRegistry         *Registry        `inject:""`
	RouterTimeout          float64          `inject:"config:flamingo.router.timeout"`
	NotFoundHandler        string           `inject:"config:flamingo.router.notfound"`
	ErrorHandler           string           `inject:"config:flamingo.router.error"`
	FilterProvider         FilterProvider   `inject:",optional"`
	// contains filtered or unexported fields
}

Router defines the basic Router which is used for holding a context-scoped setup This includes DI resolving etc

func NewRouter

func NewRouter() *Router

NewRouter factory

func (*Router) Base

func (router *Router) Base() *url.URL

Base URL getter

func (*Router) Data

func (router *Router) Data(ctx context.Context, handler string, params map[interface{}]interface{}) interface{}

Data calls a flamingo data controller

func (*Router) Init

func (router *Router) Init(routingConfig *config.Area) *Router

Init the router

func (*Router) ServeHTTP

func (router *Router) ServeHTTP(rw http.ResponseWriter, req *http.Request)

ServeHTTP shadows the internal mux.Router's ServeHTTP to defer panic recoveries and logging.

func (*Router) SetBase

func (router *Router) SetBase(u *url.URL)

SetBase for router

func (*Router) TryURL

func (router *Router) TryURL(name string, params map[string]string) (u *url.URL, err error)

TryURL is the same as URL below, but checks if the url is possible and returns an error

func (*Router) URL

func (router *Router) URL(name string, params map[string]string) *url.URL

URL helps resolving URL's by it's name.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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