Pergunta

Eu tenho o seguinte problema. Entro em contato com um endereço que conheço emprega um redirecionamento 301.

usando HttpWebRequest loHttp = (HttpWebRequest)WebRequest.Create(lcUrl);e loHttp.AllowAutoRedirect = false; para que eu não seja redirecionado.

Agora eu recebo o cabeçalho da resposta para identificar o novo URL.

usando loWebResponse.GetResponseHeader("Location");

O problema é que, como esse URL contém caracteres gregos, a string retornada está toda confusa (devido à codificação).

A sede de imagem completa:

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"];
Foi útil?

Solução

Se você deixar o comportamento padrão (loHttp.AllowAutoRedirect = true) e seu código não funciona (você não é redirecionado para o novo recurso), significa que o servidor não está codificando o Location cabeçalho corretamente. O redirecionamento está trabalhando no navegador?

Por exemplo, se o URL de redirecionamento for http://site/Μία_Σελίδα o cabeçalho da localização deve parecer http://site/%CE%95%CE%BD%CE%B9%CE%B1%CE%AF%CE%BF_%CE%94%CE%B5%CE%.


ATUALIZAR:

Depois de investigar mais uma questão, começo a suspeitar que há algo estranho com HttpWebRequest. Quando a solicitação é enviada, o servidor envia a seguinte resposta:

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">

Como podemos ver o Location O cabeçalho contém caracteres gregos que não são codificados por URL. Não tenho certeza se isso é válido de acordo com o Especificação HTTP. O que podemos dizer com certeza é que um navegador da web o interpreta corretamente.

Aí vem a parte interessante. Parece que HttpWebRequest não usa a codificação do UTF-8 para analisar os cabeçalhos de resposta, porque ao analisar o Location Cabeçalho que dá: http://www.site.com/buy/κινηÏή-ÏÏαθεÏή-ÏηλεÏÏνία/c/cn69569/, o que obviamente está errado e, quando tenta redirecionar para este local, o servidor responde com um novo redirecionamento e assim por diante até que o número máximo de redirecionamentos seja alcançado e uma exceção seja lançada.

Não consegui encontrar nenhuma maneira de especificar a codificação usada por HttpWebRequest Ao analisar os cabeçalhos de resposta. Se usarmos TcpClient manualmente, funciona perfeitamente bem:

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/
    }
}

Então, estou realmente intrigado com esse comportamento. Existe alguma maneira de especificar a codificação correta usada por HttpWebRequest? Talvez algum cabeçalho de solicitação deva ser definido?

Como solução alternativa, você pode tentar modificar o asp página que executa o redirecionamento e urlencode o Location cabeçalho. Por exemplo, quando em um aplicativo ASP.NET você executa um Response.Redirect(location), o local será automaticamente codificado HTML e quaisquer caracteres não padrão serão convertidos em suas entidades correspondentes.

Por exemplo, se você fizer: Response.Redirect("http://www.site.com/buy/κινητή-σταθερή-τηλεφωνία/c/cn69569/"); em um aplicativo ASP.NET, o Location O cabeçalho será definido como:

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

Parece que esse não é o caso do ASP clássico.

Outras dicas

Eu não esperaria que a string de retorno fosse malformada ... como você está determinando que ela é malformada? A string deve estar em um formato Unicode como o UTF-8, que seria capaz de representar a sequência grega facilmente.

Pode ser que você simplesmente não tenha as fontes gregas para representar a string?

Como Darin Dimitrov explica, acredito que a codificação do cabeçalho é causada por um bug na classe HTTPWEBRESPONSE. Tivemos o mesmo problema em que queríamos adicionar um cookie ao cabeçalho (set-cookie) e esse cookie conteria caracteres não-ASCII. Em nosso caso específico, essas seriam as letras norueguesas 'æ', 'Ø' e 'Å' (em caso superior e inferior). Não conseguimos descobrir como obter o HeaderEncoding para trabalhar, mas encontramos uma subida usando Base64 codificação do biscoito. Observe que isso só funcionará se você estiver no controle do cliente e do servidor (Ou você pode convencer as pessoas encarregadas do código lateral do servidor para adicionar a codificação base64 para você ...)

No lado do servidor:

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);

No lado do cliente:

var cookieDataAsUtf8Bytes = Convert.FromBase64String(cookieDataAsUtf8Base64Encoded);
var cookieData = System.Text.Encoding.UTF8.GetString(cookieDataAsUtf8Bytes);

Observe que cookieDataAsUtf8Base64Encoded No lado do cliente, é a parte dos dados do cookie (ou seja, 'Mycookie = [Data]', onde 'Mycookie =' é retirado).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top