Comment puis-je définir un en-tête Host personnalisé dans HttpWebRequest? Je sais que normalement cette classe ne vous permet pas de le faire mais est-ce qu'il y a de toute façon à utiliser la réflexion ou quelque chose comme ça sans réellement besoin de moi pour envoyer le paquet entier avec TCPClient?Comment définir l'en-tête "Host" personnalisé dans HttpWebRequest?
Répondre
Il y a une façon détournée pour ce faire, comme décrit ici:
http://blogs.msdn.com/feroze_daud/archive/2005/03/31/404328.aspx
Cependant, la prochaine version du cadre (.NET Framework 4.0) sera plus facile.
http://blogs.msdn.com/ncl/archive/2009/07/20/new-ncl-features-in-net-4-0-beta-2.aspx
Hope this helps.
J'ai vu cette page bien qu'il y ait beaucoup de problèmes dans cette solution de contournement à côté de cela c'est une solution de contournement vraiment sale :) –
Dommage que je n'utilise pas .NET 4 qui semble bon. –
vous pouvez utiliser le proxy, voir ma réponse à: Request Web Page in c# spoofing the Host
Vous pouvez utiliser ce hack, conçu pour résoudre ce problème dans .Net 3.5.
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Reflection;
namespace ConsoleApplication6
{
class Program
{
static void Main(string[] args)
{
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create("http://198.252.206.16");
FieldInfo headersFieldInfo = request.GetType().GetField("_HttpRequestHeaders", System.Reflection.BindingFlags.NonPublic
| System.Reflection.BindingFlags.Instance
| System.Reflection.BindingFlags.GetField);
CusteredHeaderCollection WssHeaders = new CusteredHeaderCollection("stackoverflow.com");
headersFieldInfo.SetValue(request, WssHeaders);
request.Proxy = null;
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
StreamReader sr = new StreamReader(response.GetResponseStream());
string result = sr.ReadToEnd();
Console.WriteLine(result);
Console.ReadLine();
}
public class CusteredHeaderCollection : WebHeaderCollection
{
public bool HostHeaderValueReplaced { get;private set; }
public string ClusterUrl { get; private set; }
public CusteredHeaderCollection(string commonClusterUrl) : base()
{
if (string.IsNullOrEmpty("commonClusterUrl"))
throw new ArgumentNullException("commonClusterUrl");
this.ClusterUrl = commonClusterUrl;
}
public override string ToString()
{
this["Host"] = this.ClusterUrl;
string tmp = base.ToString();
this.HostHeaderValueReplaced = true;
return tmp;
}
}
}
}
WebClient le permet.
var client = new WebClient();
client.Headers.Add("Host", WebHeader);
Je ne pourrais pas vous dire pourquoi. La documentation indique clairement que Host est un en-tête système.
Nécromage.
Pour ceux qui sont encore sur. NET 2.0
C'est en fait assez facile, si vous savez comment.
Le problème est que vous ne pouvez pas définir l'en-tête de l'hôte car le framework ne vous laissera pas modifier la valeur au moment de l'exécution. (.net framework 4.0+ vous permettra de remplacer l'hôte dans un httpwebrequest).
La prochaine tentative sera de définir l'en-tête avec réflexion, pour contourner le problème, ce qui vous permettra de changer la valeur de l'en-tête. Mais lors de l'exécution, il écrasera cette valeur avec la partie hôte de l'URL, ce qui signifie que la réflexion ne vous apportera rien. Si le nom DNS n'existe pas, ce qui est vraiment le seul cas dans lequel vous voulez le faire en premier lieu, vous ne pouvez pas le définir, car .NET ne peut pas le résoudre, et vous ne pouvez pas remplacer le résolveur DNS .NET. Mais ce que vous pouvez faire, c'est de configurer une webproxy avec exactement la même adresse IP que le serveur de destination.
Donc, si votre adresse IP du serveur est 28.14.88.71:
public class myweb : System.Net.WebClient
{
protected override System.Net.WebRequest GetWebRequest(System.Uri address)
{
System.Net.WebRequest request = (System.Net.WebRequest)base.GetWebRequest(address);
//string host = "redmine.nonexistantdomain.com";
//request.Headers.GetType().InvokeMember("ChangeInternal",
// System.Reflection.BindingFlags.NonPublic |
// System.Reflection.BindingFlags.Instance |
// System.Reflection.BindingFlags.InvokeMethod, null,
// request.Headers, new object[] { "Host", host }
//);
//server IP and port
request.Proxy = new System.Net.WebProxy("http://28.14.88.71:80");
// .NET 4.0 only
System.Net.HttpWebRequest foo = (System.Net.HttpWebRequest)request;
//foo.Host = host;
// The below reflection-based operation is not necessary,
// if the server speaks HTTP 1.1 correctly
// and the firewall doesn't interfere
// https://yoursunny.com/t/2009/HttpWebRequest-IP/
System.Reflection.FieldInfo horribleProxyServicePoint = (typeof(System.Net.ServicePoint))
.GetField("m_ProxyServicePoint", System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.Instance);
horribleProxyServicePoint.SetValue(foo.ServicePoint, false);
return foo;
return request;
}
}
et le tour est joué, maintenant
myweb wc = new myweb();
string str = wc.DownloadString("http://redmine.non-existant-domain.com");
et vous récupérez la bonne page, si 28.14.88.71 est un serveur web avec virtuel hébergement basé sur le nom (basé sur http-host-header).
Nice, pour .NET 2.0. Évidemment, cela ne fonctionnera pas si vous avez réellement besoin d'utiliser un serveur proxy;) Il suffit de mettre à jour vers .NET 4.5 - WebRequest et WebClient sont tous les deux obsolètes. – User1
Que voulez-vous changer exactement dans l'en-tête? Parce que la plupart des paramètres d'en-tête peuvent être modifiés indirectement par les propriétés –
Pourquoi avez-vous besoin de définir l'en-tête "Hôte" par vous-même. Si vous faites une demande à 'www.google.com', il devient simplement l'en-tête de l'hôte. –
@Yannick Host et d'autres paramètres réservés ne peuvent pas. –