url重定向中的Java HttpUrlConnection国际字符

时间:2012-11-12 16:54:40

标签: java httpurlconnection urlconnection

我在获取某些网站的内容时遇到问题。当我尝试导航到重定向到另一个包含国际字符的url的url时,java通常会收到错误404.当我在浏览器中关注此url时,我会获得有效数据。

例如,我想导航到hXXp://shar.es/cISmv(不能发布2个以上的有效链接)

浏览器将我正确地重定向到hXXp://www.dandy-magazine.com/la-griffe-de-la-tour-d%E2%80%99argent。从wget我可以看到,最初网站返回重定向301与现有的“位置:http://www.dandy-magazine.com/la-griffe-de-la-tour-d%E2%80%99argent

在java(关闭重定向)中,它返回带有“Location: http://www.dandy-magazine.com/la-griffe-de-la-tour-dâargent”的重定向301。使用url编码看起来像这样:“http://www.dandy-magazine.com/la-griffe-de-la-tour-d%C3%A2%C2%80%C2%99argent”。正如您所看到的,这是完全不同的网站。

示例代码(基本上版本1和版本2执行相同的操作):

// version 1 - let java handle redirects
URL url = new URL("http://shar.es/cISmv");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setInstanceFollowRedirects(true);
con.getResponseCode();
return con.getURL(); // returned url is not what it should be

// version 2 - I want to handle redirects
URL url = new URL("http://shar.es/cISmv");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setInstanceFollowRedirects(false);
con.getResponseCode();
String loc = con.getHeaderField("Location");
// here is the problem, loc is not initialized with a correct url
// returned String corresponds to url returned in version 1

寻求帮助

1 个答案:

答案 0 :(得分:1)

据我所知,当Java的值为UTF-8编码时,Java不会处理它。

网址应该看起来像...... / la-griffe-de-la-tour-d'argent。请注意,在上一句中我使用的是ASCII单引号字符。但是,网站选择使用unicode字符

而不是使用单引号字符
00002019 RIGHT SINGLE QUOTATION MARK
Glyph: ’
UTF-8: E2 80 99

wireshark跟踪显示返回的Location标头具有UTF-8编码的字符。

00e0  65 70 2d 61 6c 69 76 65  0d 0a 4c 6f 63 61 74 69   ep-alive ..Locati
00f0  6f 6e 3a 20 68 74 74 70  3a 2f 2f 77 77 77 2e 64   on: http ://www.d
0100  61 6e 64 79 2d 6d 61 67  61 7a 69 6e 65 2e 63 6f   andy-mag azine.co
0110  6d 2f 6c 61 2d 67 72 69  66 66 65 2d 64 65 2d 6c   m/la-gri ffe-de-l
0120  61 2d 74 6f 75 72 2d 64  e2 80 99 61 72 67 65 6e   a-tour-d ...argen
0130  74 0d 0a 0d 0a 30 0d 0a  0d 0a                     t....0.. ..      

我不知道这是否合法HTTP。网上肯定存在很多关于此的问题。无论它是否合法,HttpURLConnection类都不能很好地处理它。致电

String loc = con.getHeaderField("Location");

应该返回字符串http://www.dandy-magazine.com/la-griffe-de-la-tour-d’argent,其中dargent之间只有一个字符(2019)。相反,它通过将这3个UTF-8字节中的每个字节转换为字符(E2 80 99)进行哑转换来返回无效字符串。此时“loc”字符串无用。它不是一个有效的unicode字符串。

这是一个可能有用的解决方法:

  String loc = con.getHeaderField("Location");
  byte [] locbytes = new byte[loc.length()];
  for (int index = 0; index < locbytes.length; index++)
  {
     locbytes[index] = (byte) loc.charAt(index);
  }

  // use this loc instead
  String loc2 = new String(locbytes, "UTF-8");

将伪造的字符串(其中每个char具有Web服务器发送的字节的值)转换回字节数组。然后使用正确的字符集将字节数组转换回字符串。现在使用loc2作为您的URL打开一个新连接。

可能有更好的方法可以做到这一点,但我没有检查源实现,以确定有一种方法可以告诉HttpURLConnection类将标头值视为UTF-8编码。