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

前端 未结 3 1552
刺人心
刺人心 2020-12-16 08:09

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 ho

3条回答
  •  天涯浪人
    2020-12-16 08:41

    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.

提交回复
热议问题