How to send lower-case Keep-Alive header through H

2020-02-09 19:33发布

I'm writing a bot, which should emulate firefox as closely as possible. By examining the headers that it is sending, I've found one minor difference, that I do not know how to get rid off:

Firefox uses following keep-alive header:

Connection: keep-alive

While c# always sends out:

Connection: Keep-Alive

I know that it probably does not matter, but I'd still love to know if there is any way/hack to modify that header to be all lower case.

Any ideas how to do this?

3条回答
Ridiculous、
2楼-- · 2020-02-09 19:48

Connection: keep-alive is default header of Chrome and Firefox browser.

Connection: Keep-Alive is default header of Internet Explorer. Absolutely

Connection: Keep-Alive is default header of HttpWebRequest. I think you should writing a bot like IE is best choice if using HttpWebRequest.

查看更多
Juvenile、少年°
3楼-- · 2020-02-09 20:06

I also need to do this using C# and have been trying with HttpWebRequest. A non .NET SOAP web service I want to call expects Connection: keep-alive in lower case too.

I would rather not go down the route of doing socket programming for this, so if you have any suggestions on how you worked around this, if you did it would be very helpful.

My investigation so far :

When using http Protocol version 1.1, the header isn't even sent, even if you specify the property.

e.g.

var request = (HttpWebRequest)WebRequest.Create(Endpoint); 
request.KeepAlive = true;

The solution for this is to use System.Reflection to modify the httpBehaviour which will mean Keep-Alive is sent. This will send an initial upper-case K and A 'Keep-Alive' on every request.

var sp = request.ServicePoint; 
var prop = sp.GetType().GetProperty("HttpBehaviour", BindingFlags.Instance | BindingFlags.NonPublic);
prop.SetValue(sp, (byte)0, null);

I tried using System.Reflection to modify the header too. The below code will add the flag correctly in lower case :

request.Headers.GetType().InvokeMember("ChangeInternal", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.InvokeMethod, Type.DefaultBinder, request.Headers, new object[] { "Connection", "keep-alive" });

However, at the point where I am calling GetResponse

var response = (HttpWebResponse)request.GetResponse()

The header is wiped out. Looking at the source code for HttpWebRequest.cs, this happens right before sending headers to the wire.

    //
    // The method is called right before sending headers to the wire*
    // The result is updated internal _WriteBuffer
    //
    // See ClearRequestForResubmit() for the matching cleanup code path.
    // 
    internal void SerializeHeaders() {

    ....
    ....

        string connectionString = HttpKnownHeaderNames.Connection; 
        if (UsesProxySemantics || IsTunnelRequest ) { 
            _HttpRequestHeaders.RemoveInternal(HttpKnownHeaderNames.Connection);
            connectionString = HttpKnownHeaderNames.ProxyConnection; 
            if (!ValidationHelper.IsBlankString(Connection)) {
                _HttpRequestHeaders.AddInternal(HttpKnownHeaderNames.ProxyConnection, _HttpRequestHeaders[HttpKnownHeaderNames.Connection]);
            }
        } 
        else {
            _HttpRequestHeaders.RemoveInternal(HttpKnownHeaderNames.ProxyConnection); 
        } 

RemoveInternal will also remove the header we have hacked in using Reflection.

So this still leaves me stuck.

Are there other any way around this other than going at a socket level? Are there other classes or 3rd party libraries which allow me to amend headers as I wish?

Sorry this is not an answer, but I can't yet comment on your question.

查看更多
做自己的国王
4楼-- · 2020-02-09 20:07

In .net 4.0 this works:

request.Headers.GetType().InvokeMember(
    "ChangeInternal",
    BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.InvokeMethod,
    Type.DefaultBinder, 
    request.Headers, 
    new object[] { "Connection", "keep-alive" }
);

Just be sure you don't actually set the KeepAlive property on the request

查看更多
登录 后发表回答