express3.* 路由不能适配gbk编码的url 求解!!
发布于 9 年前 作者 Jason618 6033 次浏览 最后一次编辑是 8 年前 来自 问答
app.get("test/:keyword.html",function(req, res){
	var keyword = req.params["keyword"];
	console.log(keyword);
});

测试 url: localhost:3000/test/%B2%D8%BA%EC%BB%A8.html

报错:

Error: Failed to decode param '%B2%D8%BA%EC%BB%A8'
    at Route.match (E:\work\projects\src\mZhan\1.x\Code\source\msite\node_module
s\express\lib\router\route.js:65:17)
    at Router.matchRequest (E:\work\projects\src\mZhan\1.x\Code\source\msite\nod
e_modules\express\lib\router\index.js:244:17)
    at pass (E:\work\projects\src\mZhan\1.x\Code\source\msite\node_modules\expre
ss\lib\router\index.js:104:30)
    at Router._dispatch (E:\work\projects\src\mZhan\1.x\Code\source\msite\node_m
odules\express\lib\router\index.js:173:5)
    at Object.router (E:\work\projects\src\mZhan\1.x\Code\source\msite\node_modu
les\express\lib\router\index.js:33:10)
    at next (E:\work\projects\src\mZhan\1.x\Code\source\msite\node_modules\expre
ss\node_modules\connect\lib\proto.js:193:15)
    at Object.methodOverride [as handle] (E:\work\projects\src\mZhan\1.x\Code\so
urce\msite\node_modules\express\node_modules\connect\lib\middleware\methodOverri
de.js:48:5)
    at next (E:\work\projects\src\mZhan\1.x\Code\source\msite\node_modules\expre
ss\node_modules\connect\lib\proto.js:193:15)
    at Object.urlencoded [as handle] (E:\work\projects\src\mZhan\1.x\Code\source
\msite\node_modules\express\node_modules\connect\lib\middleware\urlencoded.js:41
:37)
    at next (E:\work\projects\src\mZhan\1.x\Code\source\msite\node_modules\expre
ss\node_modules\connect\lib\proto.js:193:15)
10 回复

path 中不要出现中文

@alsotang 有办法解决gbk编码的path么?

用iconv-lite模块可处理gbk。先在客户端encodeURI,然后后端decode,然后iconv-lite这样。

@pockry iconv-lite是可以解决问题,就是需要修改express源码,express里路由规则里不支持gbk编码的url.

@alsotang path里面肯定是没有中文,是采用了后端使用了按gbk字符encode的字符串。 而目前express路由匹配的时候直接使用的是decodeURIComponent,这里就抛异常了。 有好的建议么?

[@Jason618](/user/Jason618) 我是说你需要对url预处理一下,就是把%B2%D8%BA%EC%BB%A8再encode一下,这样req.params接收过来就是%B2%D8%BA%EC%BB%A8了,不做处理的话req.params是无法解析的,它用的是 node-querystring ,只能处理ASCII和UTF-8。当然还有一种方法是直接取url然后正则之最后再iconv-lite,这样就不需要req.params了。

要前排插入,不知道express可不可以

** 藏红花 **

function parser(){
  var iconv = require('iconv-lite');
  var convertUrl = function(url){
    var reg = /(\%\S\S)+/gi;
    var decodeStr = function(str){
      var arr = str.split('%');
      arr.shift();
      var buf = new Buffer(arr.length);
      arr.forEach(function(hex, i){
        var v = parseInt(hex, 16);
        buf[i] = v;
      });
      return iconv.decode(buf, 'gbk');
    };
    var result = url.match(reg).sort().reverse();
    result.forEach(function(str){
      url = url.replace(str, decodeStr(str));
    });
    return url
  }

  return function(req, res, next){
    var url = req.originalUrl;
    try{
      decodeURIComponent(url)
    }catch(e){
      req.url = req.originalUrl = encodeURI(convertUrl(url));
    }
    next();
  };
}


var express = require('express');

app = express();
app.use(parser());
app.get("/test/:keyword.html",function(req, res){
    var keyword = req.params["keyword"];
    console.log(keyword);
    res.send(keyword);
});


app.listen(3000);

@vicanso 这样处理应该是比较优雅的 先赞一个。

@pockry url是遗留url,不容易改变。 @vicanso 他的处理比较合理

回到顶部