我需要创建一个发送到我们网站的网页请求,但我也需要能够设置主机头信息。我已经尝试使用HttpWebRequest,但Header信息是只读的(至少它的主机部分是)。我需要这样做,因为我们想在用户可以之前执行页面的初始请求。我们有10个负载均衡的Web服务器,因此我们需要从每个Web服务器请求该文件。
我尝试了以下内容:
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://192.168.1.5/filename.htm");
request.Headers.Set("Host", "www.mywebsite.com");
WebResponse response = request.GetResponse();
显然这不起作用,因为我无法更新标题,我不知道这是否确实是正确的方法。
答案 0 :(得分:10)
虽然这是一个非常晚的答案,但也许有人可以从中受益
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(new Uri("http://192.168.1.1"));
request.Headers.GetType().InvokeMember("ChangeInternal", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod, null, request.Headers, new object[] {"Host","www.mysite.com"});
反思是你的朋友:)
答案 1 :(得分:9)
我已经设法通过使用套接字找到更长的绕线路线。我在IPEndPoint的MSDN页面中找到了答案:
string getString = "GET /path/mypage.htm HTTP/1.1\r\nHost: www.mysite.mobi\r\nConnection: Close\r\n\r\n";
Encoding ASCII = Encoding.ASCII;
Byte[] byteGetString = ASCII.GetBytes(getString);
Byte[] receiveByte = new Byte[256];
Socket socket = null;
String strPage = null;
try
{
IPEndPoint ip = new IPEndPoint(IPAddress.Parse("10.23.1.93"), 80);
socket = new Socket(ip.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
socket.Connect(ip);
}
catch (SocketException ex)
{
Console.WriteLine("Source:" + ex.Source);
Console.WriteLine("Message:" + ex.Message);
}
socket.Send(byteGetString, byteGetString.Length, 0);
Int32 bytes = socket.Receive(receiveByte, receiveByte.Length, 0);
strPage = strPage + ASCII.GetString(receiveByte, 0, bytes);
while (bytes > 0)
{
bytes = socket.Receive(receiveByte, receiveByte.Length, 0);
strPage = strPage + ASCII.GetString(receiveByte, 0, bytes);
}
socket.Close();
答案 2 :(得分:4)
我遇到的问题是我使用的URL dns有几个不同的IP地址,我想在主机中使用相同的dns名称分别调用每个地址 - 解决方案是使用代理:
string retVal = "";
// Can't change the 'Host' header property because .NET protects it
// HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
// request.Headers.Set(HttpRequestHeader.Host, DEPLOYER_HOST);
// so we must use a workaround
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Proxy = new WebProxy(ip);
using (WebResponse response = request.GetResponse())
{
using (TextReader reader = new StreamReader(response.GetResponseStream()))
{
string line;
while ((line = reader.ReadLine()) != null)
retVal += line;
}
}
return retVal;
主机标头由.NET自动设置为'url','ip'包含您要联系的Web服务器的实际地址(您也可以在此处使用dns名称)
答案 3 :(得分:2)
我知道这是旧的,但我遇到了同样的问题,我找到了更好的解决方案,然后使用套接字或反射......
我所做的是创建一个来自WebHeaderCollection的新类,并绕过你在其中的内容验证:
public class MyHeaderCollection:WebHeaderCollection
{
public new void Set(string name, string value)
{
AddWithoutValidate(name, value);
}
//or
public new string this[string name]
{
get { return base[name]; }
set { AddWithoutValidate(name, value); }
}
}
以下是您使用它的方式:
var http = WebRequest.Create("http://example.com/");
var headers = new MyHeaderCollection();
http.Headers = headers;
//Now you can add/override anything you like without validation:
headers.Set("Host", http.RequestUri.Host);
//or
headers["Host"] = http.RequestUri.Host;
希望这有助于任何寻找此事的人!
答案 4 :(得分:1)
我知道这是一个老问题,但是现在,你可以这样做。
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://192.168.1.5/filename.htm");
request.Host = "www.mywebstite.com";
WebResponse response = request.GetResponse();
答案 5 :(得分:0)
好吧,稍微研究了一下:
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=384456
似乎MS 可能会在某些时候对此做些什么。
答案 6 :(得分:0)
“Host”标头受保护,无法以编程方式进行修改。我想解决这个问题,您可以尝试通过反射绑定到WebRequest对象的私有“InnerCollection”属性,并在其上调用“Set”ar“Add”方法来修改Host标头。我没试过这个,但是从快速查看Reflector中的源代码,我认为它很容易实现。但是,绑定到框架对象的私有属性并不是完成任务的最佳方法。 :)只有你必须使用。
编辑:或者像其他人在链接问题中提到的那样,只需打开一个套接字并手动快速“GET”。如果你不需要修改其他东西,比如cookie或HttpWebRequest提供的任何其他细节,那就应该不费吹灰之力。
答案 7 :(得分:0)
你可以使用我的解决方案解决这个问题,它发布在这里:
How to set custom "Host" header in HttpWebRequest?
这可以帮助您编辑主机头,并避免使用代理和直接套接字请求。
答案 8 :(得分:0)
Necromancing。
对于仍然使用.NET 2.0的用户
事实上,如果你知道如何,这很容易。
问题是,您无法设置主机标头,因为框架不允许您在运行时更改该值。 (.net framework 4.0+将允许您覆盖httpwebrequest中的主机)。
下一次尝试将使用反射设置标题 - 如此处的顶部upvoted答案所示 - 绕过它,这将允许您更改标题值。但是在运行时,它会用
如果dns-name不存在,坦率地说,这是你想要首先做到这一点的唯一情况,你就不能设置它,因为.NET可以'解决它,你不能覆盖.NET DNS解析器。
但是你可以做的是设置一个与目标服务器完全相同的webproxy。
因此,如果您的服务器IP是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; // or return request; if you don't neet this
}
}
瞧,现在
myweb wc = new myweb();
string str = wc.DownloadString("http://redmine.netexistantdomain.com");
如果28.14.88.71是具有基于虚拟名称的托管(基于http-host-header)的网络服务器,则会返回正确的页面。
现在,对于WebRequest和WebClient,您对原始问题的答案都是正确的。我认为使用自定义套接字执行此操作将是错误的方法,尤其是在应该使用SSL时,以及当实际解决方案如此简单时...