Exemplo n.º 1
0
        private static Stream DoStreamRequestHttp2Response(
            Http2Connection.Http2Stream s,
            Request request,
            Uri uri,
            bool doPost)
        {
            Dictionary <string, string> rxheaders;

            if (doPost)
            {
                if (request.Expect100Continue)
                {
                    rxheaders = s.ReceiveHeaders();
                    string status;
                    if (!rxheaders.TryGetValue(":status", out status))
                    {
                        s.SendRstStream(Http2Connection.Http2ErrorCode.ProtocolError);
                        throw new BadHttpResponseException("Not a HTTP response");
                    }

                    if (status != "100")
                    {
                        int statusCode;
                        if (!int.TryParse(status, out statusCode))
                        {
                            statusCode = 500;
                        }
                        request.StatusCode = (HttpStatusCode)statusCode;

                        if (statusCode == 401 && request.Authorization != null && request.Authorization.CanHandleUnauthorized(rxheaders))
                        {
                            using (GetResponseBodyStream(request, rxheaders, s))
                            {
                                /* just consume it */
                            }
                            throw new RedoAfter401Exception();
                        }

                        if (statusCode == 401)
                        {
                            string data;
                            if (rxheaders.TryGetValue("www-authenticate", out data))
                            {
                                string authtype;
                                Dictionary <string, string> authpara = ParseWWWAuthenticate(data, out authtype);
                                if (authpara == null)
                                {
                                    s.SendRstStream(Http2Connection.Http2ErrorCode.StreamClosed);
                                    throw new BadHttpResponseException("Invalid WWW-Authenticate");
                                }
                                else if (request.IsExceptionDisabled())
                                {
                                    return(GetResponseBodyStream(request, rxheaders, s));
                                }
                                else
                                {
                                    string realm;
                                    if (!authpara.TryGetValue("realm", out realm))
                                    {
                                        realm = string.Empty;
                                    }
                                    using (GetResponseBodyStream(request, rxheaders, s))
                                    {
                                        /* just consume it */
                                    }
                                    throw new HttpUnauthorizedException(authtype, realm, authpara);
                                }
                            }
                        }

                        if (request.IsExceptionDisabled())
                        {
                            return(GetResponseBodyStream(request, rxheaders, s));
                        }
                        else
                        {
                            using (GetResponseBodyStream(request, rxheaders, s))
                            {
                                /* just consume it */
                            }
                            throw new HttpException(statusCode, statusCode == 404 ? statusCode.ToString() + " (" + uri + ")" : statusCode.ToString());
                        }
                    }
                }

                /* append request POST data */
                request.RequestBodyDelegate(s);
                s.SendEndOfStream();
            }

            s.ReadTimeout = request.TimeoutMs;
            rxheaders     = s.ReceiveHeaders();

            IDictionary <string, string> headers = request.Headers;

            if (headers != null)
            {
                headers.Clear();
                foreach (KeyValuePair <string, string> kvp in rxheaders)
                {
                    headers.Add(kvp.Key, kvp.Value);
                }
            }
            string statusVal;

            if (!rxheaders.TryGetValue(":status", out statusVal))
            {
                s.SendRstStream(Http2Connection.Http2ErrorCode.ProtocolError);
                throw new BadHttpResponseException("Missing status");
            }

            if (!statusVal.StartsWith("2"))
            {
                int statusCode;
                if (!int.TryParse(statusVal, out statusCode))
                {
                    statusCode = 500;
                }

                request.StatusCode = (HttpStatusCode)statusCode;

                if (statusCode == 401 && request.Authorization != null && request.Authorization.CanHandleUnauthorized(rxheaders))
                {
                    using (GetResponseBodyStream(request, rxheaders, s))
                    {
                        /* just consume it */
                    }
                    throw new RedoAfter401Exception();
                }

                if (statusCode == 401)
                {
                    string data;
                    if (rxheaders.TryGetValue("www-authenticate", out data))
                    {
                        string authtype;
                        Dictionary <string, string> authpara = ParseWWWAuthenticate(data, out authtype);
                        if (authpara == null)
                        {
                            s.SendRstStream(Http2Connection.Http2ErrorCode.StreamClosed);
                            throw new BadHttpResponseException("Invalid WWW-Authenticate");
                        }
                        else if (request.IsExceptionDisabled())
                        {
                            return(GetResponseBodyStream(request, rxheaders, s));
                        }
                        else
                        {
                            string realm;
                            if (!authpara.TryGetValue("realm", out realm))
                            {
                                realm = string.Empty;
                            }

                            using (GetResponseBodyStream(request, rxheaders, s))
                            {
                                /* just consume it */
                            }
                            throw new HttpUnauthorizedException(authtype, realm, authpara);
                        }
                    }
                }
                else
                {
                    request.Authorization?.ProcessResponseHeaders(rxheaders);
                }

                if (request.IsExceptionDisabled())
                {
                    return(GetResponseBodyStream(request, rxheaders, s));
                }
                else
                {
                    using (GetResponseBodyStream(request, rxheaders, s))
                    {
                        /* just consume it */
                    }
                    throw new HttpException(statusCode, statusCode == 404 ? statusVal + " (" + uri + ")" : statusVal);
                }
            }
            else
            {
                request.StatusCode = (HttpStatusCode)int.Parse(statusVal);
            }

            request.Authorization?.ProcessResponseHeaders(rxheaders);

            return(GetResponseBodyStream(request, rxheaders, s));
        }
Exemplo n.º 2
0
        public Http2Request(Http2Connection.Http2Stream stream, string callerIP, bool isBehindProxy, bool isSsl, X509Certificate remoteCertificate, HttpRequest upgradeReq = null, Stream upgradeBody = null)
            : base(isSsl, remoteCertificate)
        {
            MajorVersion = 2;
            MinorVersion = 0;
            m_Stream     = stream;
            if (upgradeReq == null)
            {
                foreach (KeyValuePair <string, string> kvp in m_Stream.ReceiveHeaders())
                {
                    m_Headers[kvp.Key] = kvp.Value;
                }
            }
            else
            {
                foreach (KeyValuePair <string, string> kvp in upgradeReq.m_Headers)
                {
                    m_Headers[kvp.Key] = kvp.Value;
                }
                m_Headers[":method"] = upgradeReq.Method;
                m_Headers[":path"]   = upgradeReq.RawUrl;
            }

            string value;

            if (!m_Headers.TryGetValue(":method", out value))
            {
                m_Stream.SendRstStream(Http2Connection.Http2ErrorCode.ProtocolError);
                throw new InvalidDataException();
            }
            Method = value;
            if (!m_Headers.TryGetValue(":path", out value))
            {
                m_Stream.SendRstStream(Http2Connection.Http2ErrorCode.ProtocolError);
                throw new InvalidDataException();
            }
            RawUrl         = value;
            ConnectionMode = HttpConnectionMode.Close;

            Expect100Continue = false;
            if (m_Headers.ContainsKey("expect") &&
                m_Headers["expect"] == "100-continue")
            {
                Expect100Continue = true;
            }

            bool havePostData = false;

            if (upgradeReq != null && upgradeReq.IsH2CUpgradableAfterReadingBody)
            {
                /* skip following postdata handling here since it is already decoded */
                m_Body = upgradeBody;
            }
            else if (m_Headers.ContainsKey("content-length") || m_Headers.ContainsKey("content-type") ||
                     m_Headers.ContainsKey("transfer-encoding"))
            {
                /* there is a body */
                m_Body = new RequestBodyStream(this);

                if (m_Headers.ContainsKey("transfer-encoding"))
                {
                    foreach (string transferEncoding in m_Headers["transfer-encoding"].Split(new char[] { '\t', ' ' }, StringSplitOptions.RemoveEmptyEntries))
                    {
                        if (transferEncoding == "gzip" || transferEncoding == "x-gzip")
                        {
                            m_Body = new GZipStream(m_Body, CompressionMode.Decompress);
                        }
                        else if (transferEncoding == "deflate")
                        {
                            m_Body = new DeflateStream(m_Body, CompressionMode.Decompress);
                        }
                        else
                        {
                            ConnectionMode = HttpConnectionMode.Close;
                            ErrorResponse(HttpStatusCode.NotImplemented, "Transfer-Encoding " + transferEncoding + " not implemented");
                            throw new InvalidDataException();
                        }
                    }
                }

                havePostData = true;
            }

            if (havePostData)
            {
                string contentEncoding = string.Empty;
                if (m_Headers.ContainsKey("content-encoding"))
                {
                    contentEncoding = m_Headers["content-encoding"];
                }
                else if (m_Headers.ContainsKey("x-content-encoding"))
                {
                    contentEncoding = m_Headers["x-content-encoding"];
                }
                else
                {
                    contentEncoding = "identity";
                }

                /* check for gzip encoding */
                if (contentEncoding == "gzip" || contentEncoding == "x-gzip") /* x-gzip is deprecated as per RFC7230 but better accept it if sent */
                {
                    m_Body = new GZipStream(m_Body, CompressionMode.Decompress);
                }
                else if (contentEncoding == "deflate")
                {
                    m_Body = new DeflateStream(m_Body, CompressionMode.Decompress);
                }
                else if (contentEncoding == "identity")
                {
                    /* word is a synomyn for no-encoding so we use it for code simplification */
                    /* no additional action required, identity is simply transfer as-is */
                }
                else
                {
                    ConnectionMode = HttpConnectionMode.Close;
                    ErrorResponse(HttpStatusCode.NotImplemented, "Content-Encoding not accepted");
                    throw new InvalidDataException();
                }
            }

            CallerIP = (m_Headers.ContainsKey("x-forwarded-for") && isBehindProxy) ?
                       m_Headers["x-forwarded-for"] :
                       callerIP;
        }