3

I'm using next.js with a custom express server when the params of a request contains % it causes this error:

URIError: Failed to decode param '%%faker'
at decodeURIComponent (<anonymous>)
at decode_param (D:\ahmed\coding\react js\with-redux-app\node_modules\express\lib\router\layer.js:172:12)
at Layer.match (D:\ahmed\coding\react js\with-redux-app\node_modules\express\lib\router\layer.js:148:15)
at matchLayer (D:\ahmed\coding\react js\with-redux-app\node_modules\express\lib\router\index.js:574:18)
at next (D:\ahmed\coding\react js\with-redux-app\node_modules\express\lib\router\index.js:220:15)
at middleware (D:\ahmed\coding\react js\with-redux-app\node_modules\http-proxy-middleware\lib\index.js:43:7)
at Layer.handle [as handle_request] (D:\ahmed\coding\react js\with-redux-app\node_modules\express\lib\router\layer.js:95:5)
at trim_prefix (D:\ahmed\coding\react js\with-redux-app\node_modules\express\lib\router\index.js:317:13)
at D:\ahmed\coding\react js\with-redux-app\node_modules\express\lib\router\index.js:284:7
at Function.process_params (D:\ahmed\coding\react js\with-redux-app\node_modules\express\lib\router\index.js:335:12)
at next (D:\ahmed\coding\react js\with-redux-app\node_modules\express\lib\router\index.js:275:10)
at expressInit (D:\ahmed\coding\react js\with-redux-app\node_modules\express\lib\middleware\init.js:40:5)
at Layer.handle [as handle_request] (D:\ahmed\coding\react js\with-redux-app\node_modules\express\lib\router\layer.js:95:5)
at trim_prefix (D:\ahmed\coding\react js\with-redux-app\node_modules\express\lib\router\index.js:317:13)
at D:\ahmed\coding\react js\with-redux-app\node_modules\express\lib\router\index.js:284:7
at Function.process_params (D:\ahmed\coding\react js\with-redux-app\node_modules\express\lib\router\index.js:335:12)

for example if the request is http://localhost:3000/summoner/eune/%%faker the error happens but if it's http://localhost:3000/summoner/eune/^^faker the ^^ gets encoded and the url becomes http://localhost:3000/summoner/eune/%5E%5Efaker and everything works perfectly.i could fix this error by following this answer Express handling URIError: Failed to decode param like so:

server.use((err, req, res, next) => {
  if (err instanceof URIError) {
    err.message = "Failed to decode param: " + req.url;
    err.status = err.statusCode = 400;
    console.log(err);
    return res.redirect(`http://${req.get("Host")}${req.url}`);
    // return app.render(req, res, "/_error");
  }
});

return res.redirect(`http://${req.get("Host")}${req.url}`); this will redirect the user from http://localhost:3000/summoner/eune/%%faker to http://localhost:3000/summoner/eune/%25%25faker and if i use return app.render(req, res, "/_error"); it will send the default error page provided by next.js back to user but this is not what i want. I want to handle the % like ^.

so my questions are:

  1. why the % doesn't get encoded to %25 and if there is a way to make it happen?
  2. who is responsible for encoding the browser or express?
  3. what is the best way to handle this error?

I'm using node v8.9.1, express ^4.16.3. Please, make the answer detailed i'm a beginner developer. Thanks for your time.

Community
  • 1
  • 1
Ahmed Mokhtar
  • 2,388
  • 1
  • 9
  • 19

1 Answers1

4

Like you pointed out, urls are percent-encoded and http://localhost:3000/summoner/eune/%%faker is just not valid as an url.

When you type an invalid url, most browsers are kind enough to change it to something valid, ex: http://localhost:3000/test test is automatically changed to http://localhost:3000/test%20test, but it's just a fallback to avoid too many errors.

In your case, % is not automatically changed to %25 because browsers cannot know when to substitute % and when to leave it. Ex: when you type %25%25faker, should this url be used as is or should it be replaced to %2525%2525faker ?

In summary: You must use valid urls at any point in time and not rely on browser kindness.

Clément Prévost
  • 8,000
  • 2
  • 36
  • 51