Closed ianstormtaylor closed 5 years ago
Hey, for sure! But that's not Trouter's responsibility.
This component is meant for storing routes with their handlers, and then returning a digest of that route when asked to find match(es). For that, it only cares about the HTTP method & adequate path "stuffs" to satisfy the pattern definition. The contents of the pattern are irrelevant (to Trouter).
That means that URL decoding must happen before a match is requested. Again, since Trouter doesn't necessarily care about the URL details, it'll work with & parse whatever you send it.
Here's how I'm using it in (the next version of) Polka: https://github.com/lukeed/polka/blob/next/packages/polka/index.js#L53-L54
And here's similar setup with Polkadot, which is basically a micro
alternative: https://github.com/lukeed/polkadot/blob/master/examples/with-router/router.js
Polkadot also handles decoding internally, though
polkadot@next
has a better URL parser in it.
So anyone who wants to use the library has to then post-process the params
to make a call to decodeURIComponent
themselves? Or at what point in those examples is polkadot
decoding the path? I'm not finding it.
If you have a route like:
/items/:id
And you make a request to:
/items/0dk2,3039
Then the pathname
of the URL will be:
/items/0dk2%2C3039
The params
object will end up as:
{
id: '0dk2%2C3039',
}
Which isn't really what you expect when getting the params back from the router? I'd have expected that it would at some point be decoded. Otherwise it seems very error prone.
Well, no, you'd preprocess the URL before calling trouter.find
. Trouter doesn't have a listen()
method on it, so it's not designed to be the only component of your stack. You still have to pass HTTP requests to it, so while in that process, you decode the URL. Trouter will then send back params that are decoded segments of the fully decoded URL you sent it.
const Trouter = require('trouter');
const { createServer } = require('http');
const router = new Trouter();
router.get('/items/:id', (req, res) => {
res.setHeader('Content-Type', 'text/plain; charset=utf-8');
res.end(req.params.id);
});
createServer((req, res) => {
// Here, call "@polka/url" OR manually decode
// For demo only: manually decode here to skip dependency magic
req.url = decodeURIComponent(req.url);
// 99% routing only cares about pathnames, so trim it
const idx = req.url.indexOf('?');
req.path = idx === -1 ? req.url : req.url.substring(0, idx);
// Find the handler(s) and params. (We are decoded)
const { params, handlers } = router.find(req.method, req.path);
req.params = params;
// Demo shortcut – doesn't matter from here on
if (handlers.length > 0) {
handlers[0](req, res);
} else {
res.statusCode = 404;
res.end('Not found');
}
}).listen(8080);
curl http://localhost:8080/items/f%C3%B8%C3%B8%C3%9Far
# => føøßar%
curl http://localhost:8080/items/0dk2%2C3039
# => 0dk2,3039%
curl http://localhost:8080/items/0dk2,3039
# => 0dk2,3039%
Also, Polkadot does its decoding here via the @polka/url
component.
These are all modular pieces of a full HTTP stack.
Ahh, I missed that branch in @polka/url
. Thank you, that explains it.
Ah yeah, sorry! Most of the goodies are in next
right now, including the correct way of decoding.
Teh whole Polka-ecosystem is moving towards a 1.0, promoting all this stuff into stable ASAP
If a param is sent with a
,
in it for instance, it will show up as%2C
after being added to theparams
object. I think they need to be URL decoded.