-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for mapping route params to regexps or functions for processing #1063
Conversation
It's desirable to both use string-based routes with named params, e.g., `"/posts/:id"`, and assign some processing to route param values, e.g., `id` should be a number. This adds a feature to Router to support mapping named params to regular expressions. See the following example: var router = new Y.Router({ params: {id: /^\d+$/} }); router.route('/posts/:id', function (req) { // This route will only be executed when `id` is a number. // `req.params.id` is the result object/captures array from // `exec()`-ing the regular expression. Y.log('Show post: ' req.params.id[0]); }); router.save('/posts/1'); // => "Show post: 1" // This won't log anything because `id` is not a number. router.save('/posts/asdf');
👍 |
I kinda agree with @tivac (in IRC) that allowing functions as parameter validators would be useful. Sometimes a regex isn't the best tool. Other than that, this looks great. |
I wasn't present during the IRC conversation, but is this is supposed to be similar to https://github.com/visionmedia/express-params If so, I agree with @rgrove. Doing: var router = new Y.Router({
params: {
id: Number
}
}); Is a lot better than using regular expressions. |
@rgrove @tivac I added a "Goals" section to this PR's description. I think it's reasonable to add support for functions, but what do you guys think should be the "contract" for param functions? I'm thinking the functions should be sync (i.e. return a usable param value), if you need async use a route callback/middleware function. As for the arguments the function is called with, I'm thinking the param name and its current value parsed from the request's path. This would artificially restrict these functions since during the dispatch process where they are called we have other info like the request object, but again, if you need cross-param validation, use a route callback/middleware function instead. |
@clarle so the param function signature would look like: |
@ericf That looks good to me. 👍 Falsy return values (but not zero) should move on to the next route, like what exports.invalidParamReturnValue = function(val){
return null == val
|| false === val
|| ('number' == typeof val && isNaN(val));
}; |
Also, how should the param function's return value be interpreted as failing validation? All falsy values but empty string means failed validation? |
Sorry for editing my comment before, but yeah, empty string is fine, and zero is fine. |
@clarle oh yeah, |
I agree param functions should be synchronous, and should have the signature However, a return value of |
Now both regexps and functions are supported for route param formatting and validation.
@rgrove hmm… I'm not sure which way to side on this. I just pushed a commit that treats a |
paramHandler(value, key) : | ||
paramHandler.exec(value); | ||
|
||
if (value !== false && YLang.isValue(value)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should a false
value return from a param handler function mean the param value fails validation and therefore the current route should be skipped?
If only there were a way to change code that's already been written! ;) |
@rgrove can you give a real-world-ish example of where a |
@ericf: Off the top of my head, I can only think of contrived examples that would probably be bad URL design. So, meh. Do what you think is right. |
Supporting bare simple functions like this is a nice improvement over just regexp so I'm happy, but I'm still gonna stump for my favorite alternative. I'd like to see this create a middleware function that runs before the rest of the route & it can just choose to not call
I think this could be accomplished by changing the signature of the functions to |
@tivac Why do you want support for async param functions? Just because there's a dispatching infrastructure which supports async functions and we could use it, that doesn't mean we should without a use case. How you would expand the Goals section I wrote in this PR's description to include why async param handling is desirable? |
With the fix in #1077, these changes work in all of YUI's Target Environments. |
This is ready to be merged! |
It's desirable to both use string-based routes with named params, e.g.,
"/posts/:id"
, and assign some processing to route param values, e.g.,id
should be a number.This adds a feature to Router to support mapping named params to regular expressions or functions. See the following example:
Goals
The main goal for this feature is to enable people to stick with string-based route paths and named
req.params
while adding support for basic param processing/validation.Currently, when people want to process request parameter values, they either have to add a route callback function, or switch to using regex route paths. Adding another callback/middleware isn't the end of world, but it gets repetitive since it has to be added to every route (or to a common middleware stack). Having to switch to using regex route paths sucks because you lose named request parameters, and those route paths are hard for humans to parse.
Todos