rata: github.com/tedsuo/rata Index | Files

package rata

import "github.com/tedsuo/rata"

Package rata provides three things: Routes, a Router, and a RequestGenerator.

Routes are structs that define which Method and Path each associated http handler should respond to. Unlike many router implementations, the routes and the handlers are defined separately. This allows for the routes to be reused in multiple contexts. For example, a proxy server and a backend server can be created by having one set of Routes, but two sets of Handlers (one handler that proxies, another that serves the request). Likewise, your client code can use the routes with the RequestGenerator to create requests that use the same routes. Then, if the routes change, unit tests in the client and proxy service will warn you of the problem. This contract helps components stay in sync while relying less on integration tests.

For example, let's imagine that you want to implement a "pet" resource that allows you to view, create, update, and delete which pets people own. Also, you would like to include the owner_id and pet_id as part of the URL path.

First off, the routes might look like this:

petRoutes := rata.Routes{
  {Name: "get_pet",    Method: rata.GET,    Path: "/people/:owner_id/pets/:pet_id"},
  {Name: "create_pet", Method: rata.POST,   Path: "/people/:owner_id/pets"},
  {Name: "update_pet", Method: rata.PUT,    Path: "/people/:owner_id/pets/:pet_id"},
  {Name: "delete_pet", Method: rata.DELETE, Path: "/people/:owner_id/pets/:pet_id"},
}

On the server, create a matching set of http handlers, one for each route:

handlers := rata.Handlers{
  "get_pet":    newGetPetHandler(),
  "create_pet": newCreatePetHandler(),
  "update_pet": newUpdatePetHandler(),
  "delete_pet": newDeletePetHandler()
}

You can create a router by mixing the routes and handlers together:

router, err := rata.NewRouter(petRoutes, handlers)
if err != nil {
  panic(err)
}

The router is just an http.Handler, so it can be used to create a server in the usual fashion:

server := httptest.NewServer(router)

The handlers can obtain parameters derived from the URL path:

ownerId := rata.Param(request, "owner_id")

Meanwhile, on the client side, you can create a request generator:

requestGenerator := rata.NewRequestGenerator(server.URL, petRoutes)

You can use the request generator to ensure you are creating a valid request:

req, err := requestGenerator.CreateRequest("get_pet", rata.Params{"owner_id": "123", "pet_id": "5"}, nil)

The generated request can be used like any other http.Request object:

res, err := http.DefaultClient.Do(req)

Index

Package Files

docs.go param.go requests.go router.go routes.go

Constants

const (
    GET     = "GET"
    HEAD    = "HEAD"
    POST    = "POST"
    PUT     = "PUT"
    PATCH   = "PATCH"
    DELETE  = "DELETE"
    CONNECT = "CONNECT"
    OPTIONS = "OPTIONS"
    TRACE   = "TRACE"
)

Supported HTTP methods.

func NewRouter Uses

func NewRouter(routes Routes, handlers Handlers) (http.Handler, error)

NewRouter combines a set of Routes with their corresponding Handlers to produce a http request multiplexer (AKA a "router"). If any route does not have a matching handler, an error occurs.

func Param Uses

func Param(req *http.Request, paramName string) string

Param returns the parameter with the given name from the given request.

type Handlers Uses

type Handlers map[string]http.Handler

Handlers map route names to http.Handler objects. Each Handler key must match a route Name in the Routes collection.

type Params Uses

type Params map[string]string

Params map path keys to values. For example, if your route has the path pattern:

/person/:person_id/pets/:pet_type

Then a correct Params map would lool like:

router.Params{
  "person_id": "123",
  "pet_type": "cats",
}

type RequestGenerator Uses

type RequestGenerator struct {
    Header http.Header
    // contains filtered or unexported fields
}

RequestGenerator creates http.Request objects with the correct path and method pre-filled for the given route object. You can also set the the host and, optionally, any headers you would like included with every request.

func NewRequestGenerator Uses

func NewRequestGenerator(host string, routes Routes) *RequestGenerator

NewRequestGenerator creates a RequestGenerator for a given host and route set. Host is of the form "http://example.com".

func (*RequestGenerator) CreateRequest Uses

func (r *RequestGenerator) CreateRequest(
    name string,
    params Params,
    body io.Reader,
) (*http.Request, error)

CreateRequest creates a new http Request for the matching handler. If the request cannot be created, either because the handler does not exist or because the given params do not match the params the route requires, then CreateRequest returns an error.

type Route Uses

type Route struct {
    // Name is a key specifying which HTTP handler the router
    // should associate with the endpoint at runtime.
    Name string
    // Method is any valid HTTP method
    Method string
    // Path contains a path pattern
    Path string
}

A Route defines properties of an HTTP endpoint. At runtime, the router will associate each Route with a http.Handler object, and use the Route properties to determine which Handler should be invoked.

Currently, the properties used for matching are Method and Path.

Method can be one of the following:

GET HEAD POST PUT PATCH DELETE CONNECT OPTIONS TRACE

Path conforms to Pat-style pattern matching. The following docs are taken from http://godoc.org/github.com/bmizerany/pat#PatternServeMux

Path Patterns may contain literals or captures. Capture names start with a colon and consist of letters A-Z, a-z, _, and 0-9. The rest of the pattern matches literally. The portion of the URL matching each name ends with an occurrence of the character in the pattern immediately following the name, or a /, whichever comes first. It is possible for a name to match the empty string.

Example pattern with one capture:

/hello/:name

Will match:

/hello/blake
/hello/keith

Will not match:

/hello/blake/
/hello/blake/foo
/foo
/foo/bar

Example 2:

/hello/:name/

Will match:

/hello/blake/
/hello/keith/foo
/hello/blake
/hello/keith

Will not match:

/foo
/foo/bar

func (Route) CreatePath Uses

func (r Route) CreatePath(params Params) (string, error)

CreatePath combines the route's path pattern with a Params map to produce a valid path.

type Routes Uses

type Routes []Route

Routes is a Route collection.

func (Routes) CreatePathForRoute Uses

func (r Routes) CreatePathForRoute(name string, params Params) (string, error)

Path looks up a Route by it's Handler key and computes it's path with a given Params map.

func (Routes) FindRouteByName Uses

func (r Routes) FindRouteByName(name string) (Route, bool)

Route looks up a Route by it's Handler key.

func (Routes) Router Uses

func (r Routes) Router(handlers Handlers) (http.Handler, error)

Router is deprecated, please use router.NewRouter() instead

Package rata imports 8 packages (graph) and is imported by 428 packages. Updated 2017-08-31. Refresh now. Tools for package owners.