zijianhe / koa-router Goto Github PK
View Code? Open in Web Editor NEWRouter middleware for koa.
License: MIT License
Router middleware for koa.
License: MIT License
Not matching methods always returns a 501, because a return statement is missing after this I think
// matches path but not method, so return 405 Method Not Allowed
// unless this is an OPTIONS request.
this.status = (this.method === 'OPTIONS' ? 204 : 405);
this.set('Allow', Object.keys(methodsAvailable).join(", "));
Also I have this configuration:
public.get('/:role/:id/picture', require('./users/picture').getPicture)
private.put('/:role/:id/picture', require('./users/picture').setPicture)
var api = compose([
public.middleware(),
auth(), me(), acl(),
private.middleware()
])
calling PUT /admins/5/picture will always respond with 405. Any advice on how to shape this?
less relevant with generators, but it was handy in express-resource
When using app.resource('users', require('./user'))
How can I call next on my user controller to continue with the following middleware or bubble up if it's the last one?
Can't figure out... sorry if it's a dumb question
Can you also add the functions get,post,... to the router prototype?
I'd like to use the router as standalone middleware that does not modify the app object. Instead, I want to define the routes directly on the router.
For example:
var app = koa();
app.use(router()
.get("/",indexPageMiddleware)
.get("/sub/",subPageMiddleware)
);
app.listen(80)
also, I could imagine the need for nested routers, which is currently not possible. Adding the methods also to router instances would solve this problem, too.
What do you think?
It would be awesome to have a respondTo(format)
method or similar plumbing in this.
E.g.
app.resource('users', {
// GET /users (default format: html)
// GET /users.json
// GET /users.xml
// GET /users.csv
index: function *(next) {
// this.format in ['html', 'json', 'xml', 'csv']
}
});
It would be great to have the ability to know if the path + http method is going to be resolved to an endpoint or 404.
The classical example is an auth middleware right before the router middleware.
If the route is 404 I want to save the query to check the auth token and all the business logic.
module.exports = function () {
return function *auth(next) {
if (this.pathIsResoved()) {
this.auth = yield authorize.call(this, this.get('x-auth-token'))
}
yield next
}
}
pathIsResoved
sucks as name, but you get the idea :)
app.get("/", function *(){
this.body = yield this.render("index");
});
then throw
TypeError: Object # has no method 'render'
/Opening a new issue, apart from basics in #74/
Express had a great, polished up parameter preprocessing.
How about to implement it in koa-router?
Citing http://expressjs.com/api#app.param:
This example is a bit more advanced. It is checking if the second argument is a regular expression, returning the callback, which acts much like the "user" param example.
app.param(function(name, fn){
if (fn instanceof RegExp) {
return function(req, res, next, val){
var captures;
if (captures = fn.exec(String(val))) {
req.params[name] = captures;
next();
} else {
next('route');
}
}
}
});
The method could now be used to effectively validate parameters (and optionally parse them to provide capture groups):
app.param('id', /^\d+$/);
app.get('/user/:id', function(req, res){
res.send('user ' + req.params.id);
});
app.param('range', /^(\w+)\.\.(\w+)?$/);
app.get('/range/:range', function(req, res){
var range = req.params.range;
res.send('from ' + range[1] + ' to ' + range[2]);
});
Express implementation covers both regexp matching (I can convert /^.*?Id$/
to ids) and validation which is kind-a cool. A passthrough function instead of == param.name
comparison is flexible and neat.
could you please bump? otherwise I'll use a tarball
Is it possible to generate url for specific route not to hardcode them in templates?
Might it be useful to make capture groups available in this.params somehow, when using a regexp to match the path? Something like this (in route.match) when using a regexp like /_\/([^\/]+)\/([^\/]+)/
to match a path like /_/foo/bar
?
for (var len = this.paramsArray.length, i=0; i<len; i++) {
if (this.isRegexp) { // or something similar
this.params['m' + i] = this.paramsArray[i];
} else {
if (this.paramNames[i]) {
this.params[this.paramNames[i].name] = this.paramsArray[i];
}
}
}
resulting in this.params containing:
{ m0: 'foo', m1: 'bar' }
This was useful to me, but that could be because Iโm thinking about it wrongly.
it is throwing in strict-mode as described here koajs/compose#14 and fixed by @visionmedia in 2.3.0
Is there a way to get the name of the named route once koa is running?
Thanks
I may be wrong but I think npm
assumes that modules author are following the Semantic Versioning spec. This means that when adding dependencies with --save
it will automatically add an entry inside package.json
like: "koa-router": "~2.3.1"
.
It implies that npm
can safely install any versions >=2.3.1-0 <2.4.0-0
of that module because the author is not going to introduce any non backwards-compatible bug fixes.
Unfortunately, between versions 2.3.1 and 2.3.2 you allowed multiple routes to be matched changing the behaviour for apps relying on your module.
Would you mind applying the recommendation below "What do I do if I accidentally release a backwards incompatible change as a minor version?"?
Thanks ๐
Express had a way to post-process app.params
.
For example, a param with name :id
could be cast to ObjectId
(and if fails, throw 404), or :userId
becomes the autoloaded user.
In the particular case of using Mongo/Mongoose that was quite helpful, because if a param does not validate as ObjectId
, then findById(id)
and findOne(_id: id)
methods throw CastError
.
To handle the error, we need to either to validate it manually (in try..catch) in every route which uses user-provided id, or just rely on a global agreement (implemented by post-processing params) ":id
or :...Id
" are ObjectIds" could be helpful.
P.S. This functionality seems to exist for koa-route: https://github.com/segmentio/koa-params
Why not to implement it here, it fits nicely.
Is it possible to have a base URL for all resources like api/v1
? Or should that be handled elsewhere via proxy or mount?
would be rad!
I would like to create a koa-router plugin that opens an api on koa-router's internal structures :
have you given a thought already about such a thing ? I don't know for example if koa-router should be extended with an object allowing for more meta fields on each routes (created_dt, registered_dt, documentation, ...) or if the 'name' of the route should be used as a sort of primary key in the plugin to allow for configuration of routes kept in the external plugin. Since name is optional that could be a problem.
thanks for your feedback
app.get('/api'๏ผ...)
when get:
/api?a=1
will 40
Ideally, you should be able to define stacks of middleware like so:
router.define('parse', [
cookieParser,
bodyParser
]);
router.get('/', 'parse', handler);
Refactor to use Routington for trie-based route matching.
Routes of this type broke in v3.2.2 (worked fine in v3.2.1):
app.get('my_route', /^\/my\/route$/, function* myRoute(next) {
// ...
});
This is the error being thrown:
Error: get `my_route`: `middleware` must be a function, not `object`
To support full utf-8 strings in params this.params
values should return URI decoded values using decodeURIComponent
.
I have an application like this:
app.get("/time", function * (next) {
})
.get("/scroll", function * (next) {
})
.get("/track",function * (next) {
});
Now the client is sending requests via a web bug like:
(new Image()).src = APP + '/track?' + data;
And I'm getting puzzled because requests that should go to the track route are also going to the scroll route and throwing errors, what could I be doing wrong?
npm seems to be still @ 2.3.3, looking forward the RegExp params =)))
~/workspace/az/routific-landing/api $ npm i
npm WARN package.json [email protected] No repository field.
npm http GET https://registry.npmjs.org/koa-router/2.4.2
npm http 404 https://registry.npmjs.org/koa-router/2.4.2
npm ERR! Error: version not found: 2.4.2 : koa-router/2.4.2
GET /users/
is fine
would be rad, will try and patch soon if i have a chance
Since 2.3.0 nested resources routing doesn't work right. Here is simple example:
var app = require('koa')()
, router = require('koa-router')(app)
app.use(router);
var forums = app.resource('forums', {
// GET /forums
index: function *(next) {
this.body = { route: 'forums/' }
console.log(this.params)
},
// GET /forums/new
new: function *(next) {},
// POST /forums
create: function *(next) {},
// GET /forums/:id
show: function *(next) {
this.body = 'Response from forums'
// console.log(this.params)
},
// GET /forums/:id/edit
edit: function *(next) {},
// PUT /forums/:id
update: function *(next) {},
// DELETE /forums/:id
destroy: function *(next) {}
});
var threads = app.resource('threads', {
// GET /threads
index: function *(next) {
this.body = { route: 'threads/' }
console.log(this.params)
},
// GET /threads/new
new: function *(next) {},
// POST /threads
create: function *(next) {},
// GET /threads/:id
show: function *(next) {
this.body = { route: '/forums/:forum/threads/:thread',
'forum':this.params['forum'],
'thread':this.params['thread']
}
console.log(this.params)
},
// GET /threads/:id/edit
edit: function *(next) {},
// PUT /threads/:id
update: function *(next) {},
// DELETE /threads/:id
destroy: function *(next) {}
});
// nested resources routing
forums.add(threads);
// response
app.use(function *(){
this.body = 'Try GET /forums/54/threads/12';
});
app.listen(3000);
When you will try to GET /forums/54/threads/12 then this.params
will contain this:
[ thread: '54' ]
Parametr forum
is missing and parametr thread
contains wrong value 54 instead of 12.
With a PUT
-request you signal that you are to replace the entire document you've selected, whilst PATCH
-request tells that the fields passed should be merged with whatever exists.
Under the multiple routers example we have a function mount
in scope but it doesn't show where this comes from.
As somebody trying koa out for the first time, I don't know what I need to require to bring this function in.
node: v0.11.10
koa: 0.3.0
koa-router: 2.4.1
app.resource('name',{ index: function*(){ this.body = 'Ok' } });
works correctly. If i open http://127.0.0.1/name
I get Ok.
If I omit the resource name, what I expect to happen is what you state in README.md:
Omit the resource name to specify a top-level resource:
So the following code
var app = require('koa')();
var kr = require('koa-router');
app.use(kr(app));
app.resource({ index: function *(){ this.body = 'Index';} });
app.listen(8080);
should give "Index" when I point the browser to http://127.0.0.1:8080 but all I get is "Not Found".
The debugger says:
Tue, 28 Jan 2014 11:54:39 GMT koa-router GET /
Am I doing something wrong?
var candidates = router.resource('candidates', require('./candidates'))
var jobs = router.resource('jobs', require('./jobs'))
// replaces "/candidates" with "/jobs/:id/candidates"
jobs.add(candidates)
API proposal
var candidates = router.resource('candidates', require('./candidates'))
var jobs = router.resource('jobs', require('./jobs'))
// keeps both "/candidates" and "/jobs/:id/candidates"
jobs.add(candidates, copy=true)
or
var candidates = router.resource('candidates', require('./candidates'))
var jobs = router.resource('jobs', require('./jobs'))
router.root.add(candidates)
jobs.add(candidates)
temp workaround
var candidates = router.resource('candidates', require('./candidates'))
var jobs = router.resource('jobs', require('./jobs'))
// replaces "/candidates" with "/jobs/:id/candidates"
jobs.add(candidates)
// readds "/candidates"
router.resource('candidates', require('./candidates'))
currently, the router looks to be just iterating through the callbacks, yield
ing each one, then building an arg list.
for (var len = route.callbacks.length, i=0; i<len; i++) {
...
It would be really nice if a callback could trigger a short circuit and finish. a common use case would be to validate in the first callback, then either return a validation error or continue on.
I can think of a few workarounds that would work currently, like bypassing the multiple callback paradigm and just passing the router 1 generated function that wraps everything up. I'm sure there are other ways.
A change like this may break any current router implementations though....
Am I correct that this is not possible:
app.all(/^\/api/, function *(next) {
if (this.cookies.get('secret' !== 'foo') this.throw('unauthorized');
yield next;
});
app.post('/api/something', function *(next) {
// API user is authenticated
});
Would it make any sense to support this kind of filters?
to get a better idea of what's being defined internally when debugging an app, specifically for the resources/routes defined and then match attempts so you can see if a regexp was failing etc
Please have a look at this issue as it might be of you interest.
I've runned the same Makefile with DEBUG=koa-router and the output is
koa-router defined route GET /test/print +0ms
koa-router defined route POST /test/:v +8ms
koa-router POST /test/42 +1s
koa-router test "/test/print" /^\/test\/print\/?$/i +1ms
koa-router test "/test/:v" /^\/test\/(?:([^\/]+?))\/?$/i +0ms
koa-router match "/test/:v" /^\/test\/(?:([^\/]+?))\/?$/i +1ms
koa-router dispatch "/test/:v" /^\/test\/(?:([^\/]+?))\/?$/i +0ms
TypeError: Cannot set property 'value' of undefined
koa-router GET /test/print +2s
koa-router test "/test/print" /^\/test\/print\/?$/i +0ms
koa-router match "/test/print" /^\/test\/print\/?$/i +0ms
koa-router test "/test/:v" /^\/test\/(?:([^\/]+?))\/?$/i +0ms
koa-router match "/test/:v" /^\/test\/(?:([^\/]+?))\/?$/i +0ms
koa-router dispatch "/test/print" /^\/test\/print\/?$/i +1ms
TypeError: Cannot read property 'value' of undefined
Hello,
currently koa-router uses path-to-regexp for the pattern matching. It would interesting to be able to define more complex routing schemes while keeping the named aspect of things.
for example in hapi https://github.com/spumko/hapi/blob/master/docs/Reference.md#path-processing they have
/a/{name}/b
/a{name}/b/{var*2}
the fact the you have a start delimiter + and end delimiter allows to have more complex patterns.
/{name}ly/b versus
/:namely/b
This is just one example there are probably yet other ways of defining programmer-friendly routes. Maybe even the pattern matcher should be pluggable.
app.use(mount('/v1', APIv1.middleware()));
Hello all!
When trying to post
{"title":"test"}
to this
app.post('/users/:id', function *(next) {
console.log(this.params.title)
console.log(this.params.id)
});
it outputs that title is undefined, but ID is not.
Is there something I'm missing?
It could be a cool addition to koa router to integrate a rule-matcher in its API :
step1: match the path with a regexp (using :notation of {notation})
step2: validate the rules according to a definition (path rules, query rules, post rules)
It should not be coded inside koa-router since koa-router could leverage on existing rule matchers such as https://github.com/spumko/joi. There are probably other out there and the best would be to have a consolidate
for rule matchers if it does not already exist.
Might want to use that for Express parity, otherwise good stuff :D
Would be great to have middleware on a per-route basis.
I use koa-router just like connect, but I found it din't work, here is my code in connect:
app.use( '/', m1 );
app.use( '/test', m2 );
r1 = new KoaRouter();
r2 = new KoaRouter();
r1.get( '/', m1 );
r2.get( '/test', m2 );
app.use( r1.middleware() );
app.use( r2.middleware() );
or like this way.
app.use( KoaRouter( app ) );
app.get( '/', m1 );
app.get( '/test', m2 );
Is there some problem in my code? I want to log some access information.
Thank you every much.
app.get(
'/test/:id',
function *(next) {
this.user = { id: 17, name: "Alex" };
yield next;
},
function *(next) {
this.body = this.user;
}
);
results in
Error: yield a function, promise, generator, array, or object
at next (/Users/Malte/Projects/PhotoApp/node_modules/koa/node_modules/co/index.js:108:12)
at Object.<anonymous> (/Users/Malte/Projects/PhotoApp/node_modules/koa/node_modules/co/index.js:56:5)
at next (/Users/Malte/Projects/PhotoApp/node_modules/koa/node_modules/co/index.js:92:21)
at Object.<anonymous> (/Users/Malte/Projects/PhotoApp/node_modules/koa/node_modules/co/index.js:56:5)
at next (/Users/Malte/Projects/PhotoApp/node_modules/koa/node_modules/co/index.js:92:21)
at Object.<anonymous> (/Users/Malte/Projects/PhotoApp/node_modules/koa/node_modules/co/index.js:56:5)
at next (/Users/Malte/Projects/PhotoApp/node_modules/koa/node_modules/co/index.js:92:21)
at Object.<anonymous> (/Users/Malte/Projects/PhotoApp/node_modules/koa/node_modules/co/index.js:56:5)
at next (/Users/Malte/Projects/PhotoApp/node_modules/koa/node_modules/co/index.js:92:21)
at Object.<anonymous> (/Users/Malte/Projects/PhotoApp/node_modules/koa/node_modules/co/index.js:56:5)
What would the correct way to handle static file requests through sitename.com/
and api requests through api.sitename.com/
with koa-router. Maybe a bit of a general question, but I was hoping you could point me in the right direction.
using jade normally lets you set the pretty
flag upon rendering ( https://github.com/visionmedia/jade#options ).
not here?
support for PATCH as first class citizen
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.