我有以下问题。我联系了一个我知道使用301重定向的地址。
使用HttpWebRequest loHttp = (HttpWebRequest)WebRequest.Create(lcUrl);
和loHttp.AllowAutoRedirect = false;
以便我不会被重定向。
现在我得到了回复的标题,以便识别新的网址。
使用loWebResponse.GetResponseHeader("Location");
问题在于,由于此网址包含希腊字符,因此返回的字符串全部混乱(由于编码)。
完整的图片代码:
HttpWebRequest loHttp = (HttpWebRequest)WebRequest.Create(lcUrl);
loHttp.ContentType = "application/x-www-form-urlencoded";
loHttp.Method = "GET";
Timeout = 10000;
loHttp.AllowAutoRedirect = false;
HttpWebResponse loWebResponse = (HttpWebResponse)loHttp.GetResponse();
string url= loWebResponse.Headers["Location"];
答案 0 :(得分:6)
如果您让默认行为(loHttp.AllowAutoRedirect = true
)和您的代码不起作用(您没有被重定向到新资源),则意味着服务器没有对Location
标头进行编码正确。重定向是否在浏览器中工作?
例如,如果重定向网址为http://site/Μία_Σελίδα
,则位置标头必须与http://site/%CE%95%CE%BD%CE%B9%CE%B1%CE%AF%CE%BF_%CE%94%CE%B5%CE%
类似。
更新:
在进一步调查此问题之后,我开始怀疑HttpWebRequest
有一些奇怪的。发送请求时,服务器发送以下响应:
HTTP/1.1 301 Moved Permanently
Date: Fri, 11 Dec 2009 17:01:04 GMT
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
Location: http://www.site.com/buy/κινητή-σταθερή-τηλεφωνία/c/cn69569/
Content-Length: 112
Content-Type: text/html; Charset=UTF-8
Cache-control: private
Connection: close
Set-Cookie: BIGipServerpool_webserver_gr=1007732746.36895.0000; path=/
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
我们可以看到Location
标头包含非url编码的希腊字符。根据{{3}},我不太确定这是否有效。我们可以肯定地说,网络浏览器正确地解释了它。
这是有趣的部分。似乎HttpWebRequest
不使用UTF-8编码来解析响应头,因为在分析Location
标头时它会给出:http://www.site.com/buy/κινηÏή-ÏÏαθεÏή-ÏηλεÏÏνία/c/cn69569/
,这当然是错误的,当它尝试时重定向到此位置,服务器将使用新的重定向进行响应,依此类推,直到达到最大重定向数并抛出异常。
在解析响应头时,我找不到任何方法来指定HttpWebRequest
使用的编码。如果我们手动使用HTTP specification,它的效果非常好:
using (var client = new TcpClient())
{
client.Connect("www.site.com", 80);
using (var stream = client.GetStream())
{
var writer = new StreamWriter(stream);
writer.WriteLine("GET /default/defaultcatg.asp?catg=69569 HTTP/1.1");
writer.WriteLine("Host: www.site.com");
writer.WriteLine("User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.2) Gecko/20090805 Shiretoko/3.5.2");
writer.WriteLine("Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
writer.WriteLine("Accept-Language: en-us,en;q=0.5");
writer.WriteLine("Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7");
writer.WriteLine("Connection: close");
writer.WriteLine(string.Empty);
writer.WriteLine(string.Empty);
writer.WriteLine(string.Empty);
writer.Flush();
var reader = new StreamReader(stream);
var response = reader.ReadToEnd();
// When looking at the response it correctly reads
// Location: http://www.site.com/buy/κινητή-σταθερή-τηλεφωνία/c/cn69569/
}
}
所以我对这种行为感到很困惑。有没有办法指定HttpWebRequest
使用的正确编码?也许应该设置一些请求标头?
作为一种解决方法,您可以尝试修改执行重定向的asp
页面,并对Location
标头进行urlencode。例如,在ASP.NET应用程序中执行Response.Redirect(location)
时,该位置将自动进行html编码,并且任何非标准字符都将转换为其对应的实体。
例如,如果您在ASP.NET应用程序中执行:Response.Redirect("http://www.site.com/buy/κινητή-σταθερή-τηλεφωνία/c/cn69569/");
,Location
标头将设置为:
http://www.site.com/buy/%ce%ba%ce%b9%ce%bd%ce%b7%cf%84%ce%ae-%cf%83%cf%84%ce%b1%ce%b8%ce%b5%cf%81%ce%ae-%cf%84%ce%b7%ce%bb%ce%b5%cf%86%cf%89%ce%bd%ce%af%ce%b1/c/cn69569
似乎这不是经典ASP的情况。
答案 1 :(得分:1)
我不希望返回字符串格式错误......您如何判断它是否格式不正确?该字符串应采用unfode格式,如utf-8,可以很容易地表示希腊字符串。
可能你只是没有希腊字体来表示字符串?
答案 2 :(得分:1)
正如Darin Dimitrov所解释的那样,我认为标头编码是由HttpWebResponse类中的错误引起的。我们遇到了同样的问题,我们想在标题中添加一个cookie(Set-Cookie),这个cookie将包含非Ascii字符。在我们的特殊情况下,这将是挪威字母'Æ','Ø'和'Å'(大写和小写)。我们无法弄清楚如何让HeaderEncoding
发挥作用,但我们找到了使用Cookie的 Base64-encoding 的解决方法。 请注意,这仅在您控制客户端和服务器端时才有效(或者您可以说服负责服务器端代码的人为您添加Base64编码... )
在服务器端:
var cookieData = "This text contains Norwegian letters; ÆØÅæøå";
var cookieDataAsUtf8Bytes = System.Text.Encoding.UTF8.GetBytes(cookieData);
var cookieDataAsUtf8Base64Encoded = Convert.ToBase64String(cookieDataAsUtf8Bytes);
var cookie = new HttpCookie("MyCookie", cookieDataAsUtf8Base64Encoded);
response.Cookies.Add(cookie);
在客户端:
var cookieDataAsUtf8Bytes = Convert.FromBase64String(cookieDataAsUtf8Base64Encoded);
var cookieData = System.Text.Encoding.UTF8.GetString(cookieDataAsUtf8Bytes);
请注意,客户端cookieDataAsUtf8Base64Encoded
是Cookie的数据部分(即'MyCookie = [data]',其中'MyCookie ='被删除)。