pub repository
mirror.p-hatan.irshelf_route
0.11.0Routing middleware for Shelf
Readme
Router for Dart Shelf
Introduction
Provides Shelf middleware for defining routes.
Shelf Route is a powerful router that makes it easy to define routes in a modular way.
Shelf Route:
- focuses solely on routing, leaving other concerns like binding, validating, error handling etc to other middleware components
- uses Shelf Path for storing path parameters in the Shelf Request context for interoperability with compatible middleware like Shelf Bind
- supports defining routes heirarchically for greater modularity
- supports custom path formats
- supports custom handler adapters
- supports custom adapters for anything capable of creating routes
This makes it very versatile and lets you mix and match it with your other favourite Shelf middleware components.
Using
Basics
You create a router using the router function
var myRouter = router();
Use the router's get method to add a route using the GET Http method
myRouter.get('/', (_) => new Response.ok("Hello World");
Use the router's handler property to obtain a Shelf Handler
var handler = myRouter.handler;
Now you can serve up your routes with Shelf IO
io.serve(handler, 'localhost', 8080);
Http Methods
It supports all the standard http methods
myRouter..get('/', (_) => new Response.ok("Hello World"))
..post('/', (_) => new Response.ok("Hello World"))
..put('/', (_) => new Response.ok("Hello World"))
..delete('/', (_) => new Response.ok("Hello World"));
You can specify several methods by using add
myRouter.add('/', ['GET', 'PUT'], (_) => new Response.ok("Hello World"));
Path Parameters
Shelf Route uses UriPattern to define the paths to match on for each route. This means you can use whatever format for the paths that you like as long as it implements this interface.
By default it uses UriTemplate which implements the powerful standard of the same name.
UriTemplate allows binding to both:
path segmentslike /greeting/fredquery parameterslike /greeting?name=fred
It uses {parameter name} notation to denote path parameters.
myRouter.get('/{name}', (request) =>
new Response.ok("Hello ${getPathParameter(request, 'name')}"));
Path parameters are fetched via Shelf Path's getPathParameter function.
Similarly you can also bind to query parameters
myRouter.get('/{name}{?age}', myHandler);
myHandler(request) {
var name = getPathParameter(request, 'name');
var age = getPathParameter(request, 'age');
return new Response.ok("Hello $name of age $age");
}
Hierarchical Routers
To improve modularity you can break up your routes into a series of nested routes.
There are two options for setting up hierarchical routes.
Using Router.child()
For example you can add a child router for all routes starting with /banking
var rootRouter = router();
var bankingRouter = rootRouter.child('/banking');
Now you can add routes to the banking router as normal
bankingRouter
..get('/account/{accountNumber}', fetchAccountHandler)
..post('/account/{accountNumber}/deposit', makeDepositHandler);
Then serve up all the routes via the rootRouter
io.serve(rootRouter.handler, 'localhost', 8080)
Note in this case the full path of the deposit resource is actually
/banking/account/{accountNumber}/deposit
To try this out, fire up the server and do
curl -d 'lots of money' http://localhost:8080/banking/account/1235/deposit
Using Router.addAll()
Using the addAll method is more compact and is particularly ideal for smaller applications. The previous example can be set up as follows
var rootRouter =
router()..addAll((Router r) => r
..addAll((Router r) => r
..get('/', fetchAccountHandler)
..post('/deposit', makeDepositHandler),
path: '/account/{accountNumber}'),
path: '/banking');
Route Specific Middleware
You can add additional middleware to individual routes
myRouter.get('/', (_) => new Response.ok("Hello World"), middleware: logRequests());
This middleware will be applied to all requests on that route.
If you add it to a child router it will apply to all routes for that router
var bankingRouter = rootRouter.child('/banking', middleware: logRequests());
will apply to all banking routes.
Custom Path Formats
The path arguments of all the router methods accept either:
- a String or
- a UriPattern
By default String value will be parsed into a UriParser which means it is expected to conform to UriTemplate.
You can also implement your own UriPattern and use that instead. For example you may prefer the : style of path variables (e.g. :name).
In addition it allows you to create uri path definitions and potentially share between client and server. e.g.
var accountPattern = new UriParser(new UriTemplate('/account/{accountNumber}'));
You can now use this when you define a route and on the client.
myRouter.get(accountPattern, (_) => new Reponse.ok("Hello World"));
Installing a Custom Path Adapter
To make it more seamless to use your own path style you can install a path adapter into the router. This will be used by all routes in this router and any child routers unless you override it somewhere.
Install the adapter by passing it to the router function.
var colonStyleAdapter = ....; // obtain the adapter from somewhere
var myRouter = router(pathAdapter: colonStyleAdapter);
Now you can use colon style path parameters
myRouter.get('/:name', (request) =>
new Response.ok("Hello ${getPathParameter(request, 'name')}"));
Custom Handler Adapters
You can install a custom handler adapter, which allows you to transform the handlers passed into the Router's methods. This allows for more seamless integration with other Shelf packages.
For example if you want to use ordinary Dart functions as handlers you can use a package like Shelf Bind. Shelf Bind provides such an adapter out of the box.
Install the adapter by passing it to the router function.
import 'package:shelf_bind/shelf_bind.dart' as bind;
var myRouter = router(handlerAdapter: bind.handlerAdapter)
Now you can do
myRouter.get('/{name}', (name) => "Hello ${name}");
instead of
myRouter..get('/{name}', (request) =>
new Response.ok("Hello ${getPathParameter(request, 'name')}"));
Note without installing the adapter you could still call Shelf Bind's bind method directly.
myRouter.get('/{name}', bind((name) => "Hello ${name}"));
Custom Route Creators
If you have some method of creating routes then it's easy to glue in.
First implement the Routeable interface
class MyRouteCreator extends Routeable {
void createRoutes(Router router) {
router..get('/', (_) => new Response.ok("Hello World"))
..get('/greeting/{name}', (request) =>
new Response.ok("Hello ${getPathParameter(request, 'name')}"));
}
}
Then add it to another router
rootRouter.addAll(new MyRouteCreator());
This can also be done with a function
rootRouter.addAll((Router router) {
router..get('/', (_) => new Response.ok("Hello World"))
..get('/greeting/{name}', (request) =>
new Response.ok("Hello ${getPathParameter(request, 'name')}")));
Custom Routeable Adapters
Similarly to how a HandlerAdapter allows you to seamlessly integrate packages like Shelf Bind, a RouteableAdapter allows you to seamlessly integrate packages like Shelf Rest.
Installation
import 'package:shelf_rest/shelf_rest.dart' as rest;
var myRouter = router(routeableAdapter: rest.routeableAdapter)
Now you can do
myRouter.addAll(new MyRestResource(), path: '/rest');
Note without installing the adapter you could still call Shelf Rests bindResource method directly.
myRouter.addAll(rest.bindResource(new MyRestResource()), path: '/rest');
Printing Routes
It's easy to see all the routes defined for a router using the printRoutes function.
var router = r.router()
..get('/', (_) => new Response.ok("Hello World"))
..post('/', (_) => new Response.ok("Hello World"))
..get('/greeting/{name}{?age}', (request) {
var name = getPathParameter(request, 'name');
var age = getPathParameter(request, 'age');
return new Response.ok("Hello $name of age $age");
});
printRoutes(router);
prints
GET -> /
POST -> /
GET -> /greeting/{name}{?age}
Examples
See more detailed examples in the example folder under the project source.
More Information
See the wiki for more details on all the options
Contributing
Contributions are welcome. Please:
- fork the repo and implement your changes with good unit test coverage of your changes
- create a pull request and include enough detail in the description
TODO
See open issues.
Authors
Changelog
0.11.0
- Added RouteableAdpater to make it cleaner to use packages like shelf_rest
0.10.1
- split into API and implementation
- exposed a new library (extend.dart) for those wishing to subclass Router
0.10.0
- added support for mergeable handler adapters. This allows things like customObjects to be extended by child routes
Note: this is only backward incompatible if you rely on handlerAdapters not being merged. i.e. to override instead
0.9.0
- Support for Middleware directly on Router (i.e. can now add at top level)
- Unified Router and _Route via a composite pattern
Note: should be backward compatible with 0.8.x unless you depended on deprecated methods that have been removed
0.8.0+1
- Don't consume path when exact match is false
0.8.0
- Changed
Router.addAllto take a typedef rather than a class- This is backwards incompatible only for anyone that has a class that
implements Routeable. To fix this simply useextends Routeableinstead.
- This is backwards incompatible only for anyone that has a class that
This change makes it easier to set up hierarchical routes. e.g.
var myRouter = router()
..addAll((Router r) => r
..get('/foo', (_) => new Response.ok('yeah foo'))
..get('/fum', (_) => new Response.ok('boo fum'))
..addAll((Router r) => r
..get('/yup/{title}',
(req) => new Response.ok("Hello ${getPathParameter(req, 'name')}"))
..get('/nup',
(req) => new Response.ok("Hello ${getPathParameter(req, 'name')}")),
path: '/blah/{name}'),
path: '/bar'
);
0.7.1
- Added fallbackHandler to router function
- call handlerAdapter on fallbackHandler
- added ALL_METHODS constant
0.7.0+1
- Fixed use of Deprecated
0.7.0
- Fixed spelling of Adapter in several classes (thanks Michael Goodness for the contribution)
0.6.0
Major release with lots of changes including:
- custom path adapters
- Allows you to plugin any path style you like (e.g.
/:foo)
- Allows you to plugin any path style you like (e.g.
- custom handler adapters
- Seamless integration with other Shelf components like Shelf Bind so you can use ordinary Dart functions as Shelf Handlers. For example:
var myRouter = router(handlerAdapter: bind.handlerAdapter)
myRouter.get('/{name}', (name) => "Hello ${name}");
- Support for Shelf Path to remove direct dependency of handlers to Shelf Route
- Easy to add per route middleware
- print all routes in a router
- control over exact path matching
- Fixed path handling on windows
0.5.0
- Upgraded to shelf 0.5.1. Note this is only a breaking change for those that directly accessed the path variables in the header. Unfortunately the example and doco did this so I made this a major release
0.4.0
- Upgraded to shelf 0.5.0
0.3.1
- Support for custom UriPattern's
0.3.0
-
Use UriPattern and UriTemplate instead of custom path matching
- path variables now use
{}instead of:
- path variables now use
0.2.0+1
- Fixed handling of routes that are just a path variable
0.2.0
- Upgraded to shelf 0.4.0
0.1.2+1
- Fixed bug where body was missing on copied request
0.1.2
- Added helper function
getPathVariablesto encapsulate extracting path variables stored in the request
0.1.1
-
Added support for path variables.
-
Improved tests.
Installing
export PUB_HOSTED_URL=https://pub.mirror.p-hatan.ir
flutter pub add shelf_routepubspec.yaml
name: shelf_route
version: 0.11.0
author: Anders Holmgren <andersmholmgren@gmail.com>
description: Routing middleware for Shelf
homepage: https://bitbucket.org/andersmholmgren/shelf_route
environment:
sdk: '>=1.4.0 <2.0.0'
dependencies:
matcher: '>=0.10.0 <0.12.0'
mock: '>=0.11.0+1 <0.12.0'
mockito: '>=0.8.1 <0.9.0'
path: '>=1.1.0 <2.0.0'
shelf: '>=0.5.4+2 <0.6.0'
shelf_path: '>=0.1.1+1 <0.2.0'
uri: '>=0.9.2 <0.10.0'
dev_dependencies:
shelf_exception_response: '>=0.1.0 <0.2.0'
unittest: '>=0.10.1 <0.12.0'
Version history
| Version | Published | Archive | SHA-256 |
|---|---|---|---|
| 0.1.0 | 2014-04-05T01:42:32.871200Z | Download | 25b49b0ef930d513e3ae576d718d992c852d80b9b412d180d8e9bbf59b5d287f |
| 0.1.0+1 | 2014-04-05T01:45:53.983660Z | Download | e31120b07b38136a984b7acb224572f0c13b3e81f70ae142dc3111155cd4f0bd |
| 0.1.0+2 | 2014-04-05T07:11:36.732650Z | Download | fe74e11d82321c6d138877c494d7ffbb62261a2ef7e28db3e399983b775c4907 |
| 0.1.1+1 | 2014-04-06T05:36:58.393550Z | Download | 23481e07612d85f39a4fa7e0e39bfd3681552c080d69f9c0bd724d2dfb9f1f2c |
| 0.1.2 | 2014-04-07T01:55:19.090490Z | Download | 772251271f22b23c1203a3d58f61bc9138030fe8a5ba0542dc3b73b8c6c5d1f3 |
| 0.1.2+1 | 2014-04-07T02:54:32.068370Z | Download | 0ee0ac1a807e3f490de280492ce7fff6075550866914adc1e81fedd46210a867 |
| 0.2.0 | 2014-04-11T05:21:21.528060Z | Download | 70609f8398e271ab3ad145b6d514fee3d0f1896f009e6bace7ba0998777ec688 |
| 0.2.0+1 | 2014-04-12T00:53:31.449850Z | Download | 1c152007cc727a37ed49eb51d433b110c5e12bd46c18409c176eba3a7d9f7654 |
| 0.3.0 | 2014-04-12T03:38:15.180330Z | Download | 1a80fd1f86b7a79dc239877daa0c2e5028818fa6fa2ac173a1dc60c1c353e506 |
| 0.3.1 | 2014-04-12T05:22:34.890670Z | Download | ef54b51195251c63a54d11372a396d03334aabace49315e37e52b942aaeb4204 |
| 0.4.0 | 2014-04-17T22:07:44.016450Z | Download | f2e5458b8f96a11770a9354d0ddfc9e3d58ac3f7eb485fdb17ee0197307c1533 |
| 0.5.0 | 2014-04-20T01:27:29.741040Z | Download | 3493204b1501efdad70b301df95f0ec032380e4e35b053fc9e00e4341a83abc3 |
| 0.6.0 | 2014-07-13T07:21:40.436370Z | Download | a44a8a992e9a0fa9a5ebd4fcdd45466719e0a93abd9599b7baf0c31bf022238f |
| 0.7.0 | 2014-07-22T20:51:52.644530Z | Download | f6bad62a92f15d74e839f2379fafe5a8b200ff1e3559d0e15a37168b2a8607c7 |
| 0.7.0+1 | 2014-08-06T09:55:26.066900Z | Download | 3fb49faf50659dd6f7824f6fdc082963fb821350469da7730fce1de2d0acc363 |
| 0.7.1 | 2014-08-09T07:40:50.426980Z | Download | e233b1103355bc35d16bae8da188d57a1cbe0d13ea2b81fb1554293a802f80dc |
| 0.8.0 | 2014-09-30T20:17:50.098080Z | Download | 74333ef252c861fe64872fdb4c8db0240784d592a5a35bbd68116d0126f8a7a5 |
| 0.8.0+1 | 2014-10-08T07:06:03.210550Z | Download | 6fe60973c8988e10c2208538f83bc4bd655685d05475cc3cb2739ca7023c1e1b |
| 0.9.0 | 2014-10-11T01:23:32.159570Z | Download | 16e19c6634258cd0013a43b7b395048f4b28464c41a613e532daa2efd5587ca8 |
| 0.10.0 | 2014-10-17T05:51:45.692520Z | Download | 2893c304ff16aaa25a56fc98f152f051f175ce9e3d3440a479b6cc372c3f9fdd |
| 0.10.1 | 2014-10-17T23:59:42.257370Z | Download | 3127353c2819f0c568411bff33fdf61fce023071bd58771217816e480e5971ea |
| 0.11.0 | 2014-11-01T01:43:28.127Z | Download | 933c6355649cdd6995100b9859637d6ff20f1680d1e38f5b9a7484903c0e31c1 |
| 0.11.0+1 | 2014-11-08T23:13:46.970400Z | Download | 42373cb88fe67876cc2a68fcc3462d4f28d3ac87a50d0ac79a9524ef1d5341c7 |
| 0.12.0 | 2015-03-20T23:25:56.164460Z | Download | 0ad04e64806ec2e6b0ee545ccb945ce1bf6ab10c660b06d446b106521097f044 |
| 0.13.0-beta.1 | 2015-06-20T21:29:49.961Z | Download | e818d7205e1066d1c485852faf007807039836d19f6a119e127dc36b2cde12a9 |
| 0.13.0-beta.2 | 2015-06-21T18:59:01.659Z | Download | 55a9c835cf2de813c07463ce4b9a25957452f2dcdfa6908bd5b92c2772ee3545 |
| 0.13.0-beta.3 | 2015-06-23T20:50:28.882Z | Download | f3271a77d3a045444276dc1c30691b666525d41cc23664a26cce521fac1bcd0f |
| 0.13.0-beta.4 | 2015-06-25T10:37:40.689Z | Download | f3c08f381ee829cc685f772f82418570c9128d593260feeaf82a05d746410e5e |
| 0.13.0 | 2015-06-25T11:08:03.385Z | Download | 1de8644648417292dfe0f9569a52dc33c3a9ad726e5b96ce5742babed2caf2b3 |
| 0.13.1 | 2015-06-25T12:22:52.783Z | Download | e4cd7d8046fa13bfdc691a94882c512e807717f3cb5ff360692ace54ed62f3ee |
| 0.13.2 | 2015-06-26T06:58:26.421Z | Download | f38e980a87f3b4395c2b7d3f566254c174afb2bb1cb356b926521d535081927d |
| 0.13.3 | 2015-07-01T21:24:04.810Z | Download | d2cc5d7e4cb543941ece4e89754f6282c46742cd61cf105656953e71eedc4e88 |
| 0.13.4 | 2015-07-04T05:13:28.163Z | Download | dc74b577bb8f76fe223266b8358be88dc4f04d875d6200913ade3c0162b5bc4d |
| 0.13.5 | 2015-08-12T23:10:04.490Z | Download | 0e1cdb8883f3aac8e500795d08e626288b44b7615076ef570691f0f162dd401a |
| 0.14.0 | 2015-08-30T22:11:53.122Z | Download | 03a3c4faa535ca26da1b629ed0ede7636a977e37cee4e0e0b49d826deff6b153 |
| 0.14.1 | 2016-01-06T06:48:13.797Z | Download | 1639423b95704088bae9187584b67865d4e1068424957c9f9aa4b978208e669b |
| 0.14.2 | 2016-04-10T01:56:50.717Z | Download | 19a05d0c7a350cbc9c9b0c8870c836737bcbffe1270830406f9d0878e39af654 |
| 0.14.3 | 2016-10-03T00:44:06.878Z | Download | 5507724c06f120d8aa50e3925e2871e68f95129b86741d29050ebc388f071891 |
Dependencies
matcher "\u003e=0.10.0 \u003c0.12.0"
mock "\u003e=0.11.0+1 \u003c0.12.0"
mockito "\u003e=0.8.1 \u003c0.9.0"
path "\u003e=1.1.0 \u003c2.0.0"
shelf "\u003e=0.5.4+2 \u003c0.6.0"
shelf_path "\u003e=0.1.1+1 \u003c0.2.0"
uri "\u003e=0.9.2 \u003c0.10.0"