Пример #1
0
        protected bool TakeStartLine(SocketInput input)
        {
            var scan     = input.ConsumingStart();
            var consumed = scan;

            try
            {
                string method;
                var    begin = scan;
                if (!begin.GetKnownMethod(ref scan, out method))
                {
                    if (scan.Seek(ref _vectorSpaces) == -1)
                    {
                        return(false);
                    }
                    method = begin.GetAsciiString(scan);
                    scan.Take();
                }

                begin = scan;

                var needDecode = false;
                var chFound    = scan.Seek(ref _vectorSpaces, ref _vectorQuestionMarks, ref _vectorPercentages);
                if (chFound == '%')
                {
                    needDecode = true;
                    chFound    = scan.Seek(ref _vectorSpaces, ref _vectorQuestionMarks);
                }

                var pathBegin = begin;
                var pathEnd   = scan;

                var queryString = "";
                if (chFound == '?')
                {
                    begin = scan;
                    if (scan.Seek(ref _vectorSpaces) != ' ')
                    {
                        return(false);
                    }
                    queryString = begin.GetAsciiString(scan);
                }

                scan.Take();
                begin = scan;

                string httpVersion;
                if (!begin.GetKnownVersion(ref scan, out httpVersion))
                {
                    scan = begin;
                    if (scan.Seek(ref _vectorCRs) == -1)
                    {
                        return(false);
                    }
                    httpVersion = begin.GetAsciiString(scan);

                    scan.Take();
                }
                if (scan.Take() != '\n')
                {
                    return(false);
                }

                // URIs are always encoded/escaped to ASCII https://tools.ietf.org/html/rfc3986#page-11
                // Multibyte Internationalized Resource Identifiers (IRIs) are first converted to utf8;
                // then encoded/escaped to ASCII  https://www.ietf.org/rfc/rfc3987.txt "Mapping of IRIs to URIs"
                string requestUrlPath;
                if (needDecode)
                {
                    // URI was encoded, unescape and then parse as utf8
                    pathEnd        = UrlPathDecoder.Unescape(pathBegin, pathEnd);
                    requestUrlPath = pathBegin.GetUtf8String(pathEnd);
                }
                else
                {
                    // URI wasn't encoded, parse as ASCII
                    requestUrlPath = pathBegin.GetAsciiString(pathEnd);
                }

                consumed    = scan;
                Method      = method;
                RequestUri  = requestUrlPath;
                QueryString = queryString;
                HttpVersion = httpVersion;

                bool caseMatches;

                if (!string.IsNullOrEmpty(_pathBase) &&
                    (requestUrlPath.Length == _pathBase.Length || (requestUrlPath.Length > _pathBase.Length && requestUrlPath[_pathBase.Length] == '/')) &&
                    RequestUrlStartsWithPathBase(requestUrlPath, out caseMatches))
                {
                    PathBase = caseMatches ? _pathBase : requestUrlPath.Substring(0, _pathBase.Length);
                    Path     = requestUrlPath.Substring(_pathBase.Length);
                }
                else
                {
                    Path = requestUrlPath;
                }

                return(true);
            }
            finally
            {
                input.ConsumingComplete(consumed, scan);
            }
        }
Пример #2
0
        private bool TakeStartLine(SocketInput input)
        {
            var scan     = input.ConsumingStart();
            var consumed = scan;

            try
            {
                var begin = scan;
                if (scan.Seek(' ') == -1)
                {
                    return(false);
                }
                var method = begin.GetString(scan);

                scan.Take();
                begin = scan;

                var needDecode = false;
                var chFound    = scan.Seek(' ', '?', '%');
                if (chFound == '%')
                {
                    needDecode = true;
                    chFound    = scan.Seek(' ', '?');
                }

                var pathBegin = begin;
                var pathEnd   = scan;

                var queryString = "";
                if (chFound == '?')
                {
                    begin = scan;
                    if (scan.Seek(' ') != ' ')
                    {
                        return(false);
                    }
                    queryString = begin.GetString(scan);
                }

                scan.Take();
                begin = scan;
                if (scan.Seek('\r') == -1)
                {
                    return(false);
                }
                var httpVersion = begin.GetString(scan);

                scan.Take();
                if (scan.Take() != '\n')
                {
                    return(false);
                }

                if (needDecode)
                {
                    pathEnd = UrlPathDecoder.Unescape(pathBegin, pathEnd);
                }

                var requestUrlPath = pathBegin.GetString(pathEnd);

                consumed    = scan;
                Method      = method;
                RequestUri  = requestUrlPath;
                QueryString = queryString;
                HttpVersion = httpVersion;
                Path        = RequestUri;
                return(true);
            }
            finally
            {
                input.ConsumingComplete(consumed, scan);
            }
        }