/// <summary>
        /// contructor processes the HTTP response data
        /// </summary>
        /// <param name="messageHandler">external message handler</param>
        /// <param name="supportsGZip">are we supporting GZip compression</param>
        /// <param name="input"></param>
        /// <param name="log"></param>
        public ProxyResponseMessage(IExternalMessageHandler messageHandler, bool supportsGZip, Stream input, LogRequest log)
            : base(messageHandler, supportsGZip, input, log, false)
        {
            if (FirstHeaderLine != null)
            {
                // parse the status result for the response
                string[] parts = FirstHeaderLine.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                if (parts.Length > 1)
                {
                    log.ScStatus = parts[1];
                    log.ScSubstatus = "0";

                    messageHandler.ProcessHeaderLineResponse(log);
                    int status;
                    if ( int.TryParse(log.ScStatus, out status) == false && log.ScStatus.StartsWith("html", StringComparison.InvariantCultureIgnoreCase) )
                        log.ScStatus = "200";
                }
                else
                {
                    // default to a 200 "Success" status
                    log.ScStatus = "200";
                    log.ScSubstatus = "0";
                }

            }
        }
        /// <summary>
        /// contructor processes the HTTP request data
        /// </summary>
        /// <param name="messageHandler">external message handler</param>
        /// <param name="supportsGZip">are we supporting GZip compression</param>
        /// <param name="input"></param>
        /// <param name="log"></param>
        public ProxyRequestMessage(IExternalMessageHandler messageHandler, bool supportsGZip, Stream input, LogRequest log)
            : base(messageHandler, supportsGZip, input, log, true)
        {
            if (FirstHeaderLine != null)
            {
                // parse the first line to get header information
                string[] parts = FirstHeaderLine.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                if (parts.Length > 0)
                {
                    // method is the first token
                    log.CsMethod = parts[0];
                    if (parts.Length > 1)
                    {
                        // parse the query string
                        int index = parts[1].IndexOf('?');
                        if (index == -1)
                            log.CsUriStem = parts[1];
                        else
                        {
                            log.CsUriStem = parts[1].Substring(0, index);
                            log.CsUriQuery = parts[1].Substring(index + 1);
                        }

                        messageHandler.ProcessHeaderLineRequest(log);

                        // get the HTTP version if available
                        if (parts.Length > 2)
                            log.CsVersion = parts[2];
                    }
                }

                if (Authorization != null)
                {
                    // get header authorization infromation
                    int index = Authorization.IndexOf(_basicAuthorization);
                    if (index == 0)
                    {
                        // if basic authentication, get un/domain
                        log.CsUsername = ProcessUserNameAndPassword( Authorization.Substring(index + _basicAuthorization.Length), true, log.CsUsername);
                    }
                }
            }

            // must happen before settings code code below as it depends on username
            UserName = log.CsUsername;

            messageHandler.ProcessRequest(this, UserName);
        }
Esempio n. 3
0
        /// <summary>
        /// socket input from client or server to process
        /// </summary>
        /// <param name="messageHandler">external message handler</param>
        /// <param name="supportsGZip">are we supporting GZip compression</param>
        /// <param name="input">the client for server HTTP stream</param>
        /// <param name="log">request log structure</param>
        /// <param name="checkPreHttp">is this the request and a pre http 1.1 request</param>
        protected ProxyMessage(IExternalMessageHandler messageHandler, bool supportsGZip, Stream input, LogRequest log, bool checkPreHttp)
        {
            _messageHandler = messageHandler;

            _supportsGZip = supportsGZip;
            _rawRead = new byte[BufferSize];
            _header = new List<byte>(BufferSize);
            _content = new List<byte>(BufferSize);

            int bytes = 0;
            bool headerDone = false;
            bool contentDone = false;
            int contentLength = 0;
            // loop until we have read al the input (no bytes returned, header end character or content length reached)
            do
            {
                bytes = input.Read(_rawRead, 0, BufferSize);

                if (bytes != 0)
                {
                    if (headerDone == false)
                    {
                        // add all bytes read to the header
                        _header.AddRange(_rawRead.Take(bytes));

                        // parse the header information
                        HeaderPositions match = ParseHeader();

                        // if we read the entire HTTP header process it
                        if (match.HeaderEnd != -1)
                        {
                            // find the end of the list line
                            _firstHeaderLineEnd = match.FirstLineEnd;

                            // add any content we may have read into the content buffer based on the header end characters
                            _content.AddRange(_header.Skip(match.HeaderEnd));
                            // trim the header of any content information
                            _header.RemoveRange(match.HeaderEnd, _header.Count - match.HeaderEnd);
                            headerDone = true;

                            // if the header did not contain a content length tag, content is done
                            if (match.ContentLength == -1)
                                contentDone = true;
                            else
                            {
                                // get the "real" content length from the header
                                int pos = match.ContentLength;
                                while (_header[pos] != '\r')
                                {
                                    char c = (char)_header[pos];
                                    if (char.IsNumber(c))
                                        contentLength = ((contentLength * 10) + (c - '0'));
                                    ++pos;
                                }

                                // see if we have alread read in all the content
                                if (contentLength == 0 || _content.Count == contentLength)
                                    contentDone = true;
                            }

                            // get misc. header values
                            _contentType = ParseHeaderValue(match.ContentType);
                            _contentEncoding = ParseHeaderValue(match.ContentEncoding);
                            _cacheControl = ParseHeaderValue(match.CacheControl);

                            string transferEncoding = ParseHeaderValue(match.TransferEncoding);
                            if (transferEncoding != null && transferEncoding.IndexOf(_transferEncodingChunkedToken, StringComparison.InvariantCultureIgnoreCase) != -1)
                            {
                                _transferEncodingChunked = true;
                                contentDone = ReadChunkedContent();
                            }

                            if (match.Host != -1)
                                Host = ParseHeaderValue(match.Host, ':');

                            // have logging values
                            if (match.UserAgent != -1)
                                UserAgent = log.CsUserAgent = ParseHeaderValue(match.UserAgent);
                            if (match.Authorization != -1)
                                Authorization = ParseHeaderValue(match.Authorization);
                        }
                        else if ( match.FirstLineEnd != -1 && checkPreHttp )
                        {
                            // check pre http 1.1 headers
                            string []parts = Encoding.UTF8.GetString(_header.ToArray()).Split( new char[] { ' ', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries );
                            if (parts.Length == 2 && string.Compare(parts[0], "GET", true) == 0)
                            {
                                headerDone = true;
                                contentDone = true;
                            }
                        }
                    }
                    else
                    {
                        // if the header is complete, read the content (if specified in Content-Length)
                        _content.AddRange(_rawRead.Take(bytes));
                        if (_transferEncodingChunked)
                            contentDone = ReadChunkedContent();
                        else
                            contentDone = (_content.Count == contentLength);
                    }
                }
            }
            while (bytes != 0 && (headerDone == false || contentDone == false));

            if (_transferEncodingChunked)
                DeChunkData();

            LogHeaderContent();
        }