Apache Commons UrlValidator不支持unicode。替代方案可用吗?

时间:2010-07-21 02:58:31

标签: java validation url

我尝试url验证。 但是UrlValidator不支持unicode。 这是代码

public static boolean isValidHttpUrl(String url) {
    String[] schemes = {"http", "https"};
    UrlValidator urlValidator = new UrlValidator(schemes);
    if (urlValidator.isValid(url)) {
        System.out.println("url is valid");
        return true;
    }
    System.out.println("url is invalid");
    return false;
}

String url = "ftp://hi.com";
boolean isValid = isValidHttpUrl(url);
assertFalse(isValid);

url = "http:// hi.com";
isValid = isValidHttpUrl(url);
assertFalse(isValid);

url = "http://hi.com";
isValid = isValidHttpUrl(url);
assertTrue(isValid);

// this is problem... it's not true... 
url = "http://안녕.com";
isValid = isValidHttpUrl(url);
assertTrue(isValid);

你知道任何替代url验证器支持unicode吗?

我添加了一些案例...... http://seapy_hi.com无效。为什么? underbar是有效域名,为什么无效?

3 个答案:

答案 0 :(得分:4)

它不支持IDN。您需要先将URL转换为Punycode。试试这个,

  isValid = isValidHttpUrl(IDN.toASCII(url));

答案 1 :(得分:0)

可能有一个更新的RFC取代了这个,但从技术上讲,URL不支持Unicode。 RFC1738

特别是相关部分:

  

没有相应的图形US-ASCII:

     

网址只能用   图形可打印字符   US-ASCII编码字符集。该   八位字节80-FF十六进制不是
  用于US-ASCII和八位字节00-1F   和7F十六进制代表
  控制字符;这些必须是   编码。

答案 2 :(得分:0)

正如 Kaerber 在对已接受答案的评论中提到的那样 - 如果字符串以方案开头,则会出现错误。 所以这是我的解决方案:

public static String convertUnicodeURLToAscii(String url) throws URISyntaxException {
    if(url == null) {
        return null;
    }
    url = url.trim();
    URI uri = new URI(url);
    boolean includeScheme = true;

    // URI needs a scheme to work properly with authority parsing
    if(uri.getScheme() == null) {
        uri = new URI("http://" + url);
        includeScheme = false;
    }

    String scheme = uri.getScheme() != null ? uri.getScheme() + "://" : null;
    String authority = uri.getRawAuthority() != null ? uri.getRawAuthority() : ""; // includes domain and port
    String path = uri.getRawPath() != null ? uri.getRawPath() : "";
    String queryString = uri.getRawQuery() != null ? "?" + uri.getRawQuery() : "";
    String fragment = uri.getRawFragment() != null ? "#" + uri.getRawFragment() : "";

    // Must convert domain to punycode separately from the path
    url = (includeScheme ? scheme : "") + IDN.toASCII(authority) + path + queryString + fragment;

    // Convert path from unicode to ascii encoding
    return new URI(url).normalize().toASCIIString();
}