IDN识别工具,用于将人类可读IRI编码/解码到有效URI

时间:2010-05-14 09:19:31

标签: javascript python html idn iri

假设用户输入某些资源的地址,我们需要将其翻译为:

<a href="valid URI here">human readable form</a>

HTML4规范是指RFC 3986,它只允许ASCII字母数字字符和主机部分中的破折号,其他部分中的所有非ASCII字符都应进行百分比编码。这就是我想要放在href属性中以使链接在所有浏览器中正常工作。 IDN应使用Punycode进行编码。

HTML5草案引用RFC 3987,它还允许主机部分中的百分比编码的unicode字符和主机和其他部分中的大部分unicode,而不对其进行编码。用户可以以任何这些形式输入地址。为了提供它的可读形式,我需要解码所有可打印的字符。请注意,地址的某些部分可能与有效的UTF-8序列不对应,通常是在目标站点使用其他字符编码时。

我想得到的一个例子:

<a href="http://xn--80aswg.xn--p1ai/%D0%BF%D1%83%D1%82%D1%8C?%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81">
http://сайт.рф/путь?запрос</a>

是否有任何工具可以解决这些问题?我对Python和JavaScript的库特别感兴趣。

更新:我知道有一种方法可以在Python和JavaScript中进行百分比和Punycode(没有适当的规范化,但我可以忍受它)编码/解码。整个任务需要更多的工作,并且存在一些缺陷(一些字符应该总是编码或从不编码,具体取决于上下文)。我想知道是否有准备使用库来解决整个问题,因为它似乎很常见,现代浏览器已经进行了这样的转换(尝试在Google Chrome中输入http://%D1%81%D0%B0%D0%B9%D1%82.%D1%80%D1%84/,它会是替换为http://сайт.рф/,但在HTTP请求中使用Host: xn--80aswg.xn--p1ai

Update2 :Vinay Sajip指出Werkzeug有iri_to_uri和uri_to_iri函数可以正确处理大多数情况。到目前为止,我只发现了2个失败的情况:百分比编码的主机(非常容易修复)和无效的utf-8序列(做得好有点棘手,但不应该有问题)。

我仍然在寻找JavaScript中的库。写起来并不难,但我宁愿避免发明轮子。

1 个答案:

答案 0 :(得分:2)

如果我理解正确,那么你可以使用Python中包含的电池:

# -*- coding: utf-8 -*-

import urllib
import urlparse

URL1 = u'http://сайт.рф/путь?запрос'
URL2 = 'http://%D1%81%D0%B0%D0%B9%D1%82.%D1%80%D1%84/'

def to_idn(url):
    parts = list(urlparse.urlparse(url))
    parts[1] = parts[1].encode('idna')
    parts[2:] = [urllib.quote(s.encode('utf-8')) for s in parts[2:]]
    return urlparse.urlunparse(parts)

def from_idn(url):
    return urllib.unquote(url)

print to_idn(URL1)
print from_idn(URL2)
print to_idn(from_idn(URL2).decode('utf-8'))

打印

http://xn--80aswg.xn--p1ai/%D0%BF%D1%83%D1%82%D1%8C?%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81
http://сайт.рф/
http://xn--80aswg.xn--p1ai/

看起来像你想要的。我不确定你的意思是什么特殊情况 - 也许你可以举出一些你所指的陷阱的例子?

更新:我记得,Werkzeug在版本0.6及更高版本中有iri_to_uriuri_to_iri个函数(链接到文档的相关部分)。

进一步更新:抱歉,我没有注意到您正在寻找JavaScript实现以及Python实现。 punycode的现有公共域Javascript实现是here。不过,我无法保证。当然,您可以使用内置的JavaScript encodeURI / decodeURI API。