Documentation ¶
Overview ¶
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: "GET", Path: "/people/:owner_id/pets/:pet_id"}, {Name: "create_pet", Method: "POST", Path: "/people/:owner_id/pets"}, {Name: "update_pet", Method: "PUT", Path: "/people/:owner_id/pets/:pet_id"}, {Name: "delete_pet", Method: "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)
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 ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Handlers ¶
Handlers map route names to http.Handler objects. Each Handler key must match a route Name in the Routes collection.
type Params ¶
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 ¶
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 ¶
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 ¶
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 ¶
type Route struct { // Name is a key specifying which HTTP handler the router // should associate with the endpoint at runtime. Name string // Method is one of the following: GET,PUT,POST,DELETE 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 PUT POST DELETE
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
type Routes ¶
type Routes []Route
Routes is a Route collection.
func (Routes) CreatePathForRoute ¶
Path looks up a Route by it's Handler key and computes it's path with a given Params map.
func (Routes) FindRouteByName ¶
Route looks up a Route by it's Handler key.