示例#1
0
        private void ParseRequestLine(TRequestHandler handler, ReadOnlySpan <byte> requestLine)
        {
            // Get Method and set the offset
            var method = requestLine.GetKnownMethod(out var methodEnd);

            if (method == HttpMethod.Custom)
            {
                methodEnd = GetUnknownMethodLength(requestLine);
            }

            var versionAndMethod = new HttpVersionAndMethod(method, methodEnd);

            // Use a new offset var as methodEnd needs to be on stack
            // as its passed by reference above so can't be in register.
            // Skip space
            var offset = methodEnd + 1;

            if ((uint)offset >= (uint)requestLine.Length)
            {
                // Start of path not found
                RejectRequestLine(requestLine);
            }

            var ch = requestLine[offset];

            if (ch == ByteSpace || ch == ByteQuestionMark || ch == BytePercentage)
            {
                // Empty path is illegal, or path starting with percentage
                RejectRequestLine(requestLine);
            }

            // Target = Path and Query
            var targetStart = offset;
            var pathEncoded = false;

            // Skip first char (just checked)
            offset++;

            // Find end of path and if path is encoded
            for (; (uint)offset < (uint)requestLine.Length; offset++)
            {
                ch = requestLine[offset];
                if (ch == ByteSpace || ch == ByteQuestionMark)
                {
                    // End of path
                    break;
                }
                else if (ch == BytePercentage)
                {
                    pathEncoded = true;
                }
            }

            var path = new TargetOffsetPathLength(targetStart, length: offset - targetStart, pathEncoded);

            // Query string
            if (ch == ByteQuestionMark)
            {
                // We have a query string
                for (; (uint)offset < (uint)requestLine.Length; offset++)
                {
                    ch = requestLine[offset];
                    if (ch == ByteSpace)
                    {
                        break;
                    }
                }
            }

            var queryEnd = offset;

            // Consume space
            offset++;

            // Version + CR is 9 bytes which should take us to .Length
            // LF should have been dropped prior to method call
            if ((uint)offset + 9 != (uint)requestLine.Length || requestLine[offset + sizeof(ulong)] != ByteCR)
            {
                RejectRequestLine(requestLine);
            }

            // Version
            var remaining   = requestLine.Slice(offset);
            var httpVersion = remaining.GetKnownVersion();

            versionAndMethod.Version = httpVersion;
            if (httpVersion == HttpVersion.Unknown)
            {
                // HTTP version is unsupported.
                RejectUnknownVersion(remaining);
            }

            // We need to reinterpret from ReadOnlySpan into Span to allow path mutation for
            // in-place normalization and decoding to transform into a canonical path
            var startLine = MemoryMarshal.CreateSpan(ref MemoryMarshal.GetReference(requestLine), queryEnd);

            handler.OnStartLine(versionAndMethod, path, startLine);
        }
示例#2
0
 public void OnStartLine(HttpVersionAndMethod versionAndMethod, TargetOffsetPathLength targetPath, Span <byte> startLine)
 {
     var targetStart = targetPath.Offset;
     // Slice out target
     var target = startLine[targetStart..];
示例#3
0
 public void OnStartLine(HttpVersionAndMethod versionAndMethod, TargetOffsetPathLength targetPath, Span <byte> startLine)
 => Connection.OnStartLine(versionAndMethod, targetPath, startLine);