如何在express中处理非UTF-8编码的url

时间:2015-09-18 13:22:56

标签: javascript node.js iis url-encoding bing

我们有一个节点js应用程序,我们最近从IIS 7上运行(通过IIS节点)转移到在Linux上运行(Elastic Beanstalk)。自从我们切换以来,我们已经将大量非UTF-8网址发送到我们的应用程序(主要来自爬虫),例如:

IIS正在转换为Bj%F6rk

Björk。现在这被传递给我们的应用程序,我们的Web框架(express)最终调用

decodeURIComponent('Bj%F6rk'); URIError: URI malformed at decodeURIComponent (native) at repl:1:1 at REPLServer.self.eval (repl.js:110:21) at repl.js:249:20 at REPLServer.self.eval (repl.js:122:7) at Interface.<anonymous> (repl.js:239:12) at Interface.emit (events.js:95:17) at Interface._onLine (readline.js:203:10) at Interface._line (readline.js:532:8) at Interface._ttyWrite (readline.js:761:14)

在发送url字符串表示之前,是否有推荐的安全方式我们可以执行与IIS相同的转换?

铭记

  1. 我们正在接收对这些编码错误的网址和
  2. 的请求
  3. 有一种方法可以使用deprecated unescape javascript function
  4. 解码它们
  5. 这些网址的大部分请求来自Bing Bot,我们希望尽量减少对搜索排名的不利影响。

    • 我们真的应该为所有传入的网址执行此操作吗?
    • 我们应该关注是否存在任何安全或性能影响?
    • 我们是否应该关注unescape在不久的将来被删除?
    • 是否有更好/更安全的方法来解决这个问题(是的,我们确实读过上面链接的MDN文章)

3 个答案:

答案 0 :(得分:10)

  

我们真的应该为所有传入的网址执行此操作吗?

不,你不应该。正在进行的请求使用非UTF8 URI组件。这不应该是你的问题。

  

我们应该有任何安全或性能影响   关心?

URI组件的编码不是安全问题。通过查询字符串或路径参数进行注入尝试。但这是另一个主题。在性能方面,每个中间件都会让您的响应花费更长的时间。但我甚至不担心这一点。如果您想自己解码URI,那就去做吧。它只需要几毫秒。

  

我们是否应该关注在近处移除unescape   未来?

其实你应该。不推荐使用unescape。如果你还想使用它;只是检查它是否存在。即'unescape' in global。您还可以使用内置备用:require('querystring').unescape(),它在每种情况下都不会产生相同的结果,但它不会抛出URIError。 (不推荐)。

尽量减少对搜索排名的任何不利影响:

确定您的快递应用在这些情况下返回的状态代码。可能 500 (内部服务器错误)看起来很糟糕且 404 (未找到)会告诉抓取工具您没有查询结果(这可能不是真的)。

在这些情况下,我建议您通过返回客户端错误(例如 400 (BAD REQUEST)来覆盖此错误,因为问题的根源是请求的格式错误的URI组件,应该是在UTF-8中,但事实并非如此。爬虫/机器人应该关注这一点。

// middleware for responding with BAD REQUEST
app.use(function (err, req, res, next) {
    if (err instanceof URIError) {
        res.status(400).send();
    }
});

最重要的是,尝试返回格式错误的URI的结果会产生其他副作用。首先,你将允许一个糟糕的请求 - 不是很好:)。其次,它意味着你有一个错误的URI的结果,当它们获得200 OK响应时它将被爬虫/机器人存储并且它将被传播。然后,您将不得不处理更多不良请求。

结束;不要通过unescape进行解码。 Express已尝试通过适当的解码来解码:decodeURIComponent。如果失败了,就让它成为。

答案 1 :(得分:1)

Node.js queryString库可以安全地实施escapeunescape方法。它们都使用utf-8编码。 unescape首先尝试decodeURIComponent,当失败时,会尝试使用safe fast alternative implementation

> querystring.escape('ö')
'%C3%B6'
> querystring.unescape('%C3%B6')
'ö'

但是您有latin-1个编码字符串(%F6而非%C3%B6),因此querystring.unescape会产生意外结果,但它不会破坏您的代码:

> querystring.unescape('Bj%F6rk')
'Bj�rk'

您可以将latin1转换为utf-8,并使用iconviconv-lite包获取正确的字符串。但是URL encoding应该是UTF-8。因此,我认为忽略其他编码字符串并使用querystring.unescape

是安全的

在express 4.7.x中,您可以将query parser配置设置为simple,以使用内部使用querystring.parse的{​​{1}}。

querystring.unescape

答案 2 :(得分:0)

我推荐Nodejs decode-uri-charset,https://www.npmjs.com/package/decode-uri-charset

var url_decode = require('decode-uri-charset');
console.log(url_decode('%C7%CF%C0%CC', 'euc-kr'))