Example #1
0
        public HttpStatusLine(HttpVersion version,
                              int code,
                              string reason)
            : this()
        {
            if (null == version)
            {
                throw new ArgumentNullException("version");
            }

            if (0 > code)
            {
                throw new ArgumentOutOfRangeException("code");
            }

            if (null == reason)
            {
                throw new ArgumentNullException("reason");
            }

            if (0 == reason.Length)
            {
                throw new ArgumentOutOfRangeException("reason");
            }

            Version = version;
            Code = code;
            Reason = reason;
        }
Example #2
0
 public HttpRequest(HttpMethod method, Uri path, HttpVersion version, Dictionary<string, string> headerDictionary, string content)
 {
     Version = version;
     Method = method;
     Path = path;
     Headers = headerDictionary;
     Content = content;
 }
        /// <summary>
        /// Creates a new instance of the http response class with the specified parameters.
        /// </summary>
        /// <param name="version">The http version.</param>
        /// <param name="state">The http state.</param>
        public HttpResponse(HttpVersion version, HttpState state)
        {
            if (!Enum.IsDefined(typeof(HttpVersion), version))
                throw new ArgumentException("The argument is not valid.", nameof(version));

            if (state == InvalidCode)
                throw new ArgumentException("The argument is not valid.", nameof(state));

            HttpVersion = version;
            State = state;
        }
Example #4
0
        public static MessageBody For(
            HttpVersion httpVersion,
            FrameRequestHeaders headers,
            Frame context)
        {
            // see also http://tools.ietf.org/html/rfc2616#section-4.4
            var keepAlive = httpVersion != HttpVersion.Http10;

            var connection = headers.HeaderConnection;
            var upgrade    = false;

            if (connection.Count > 0)
            {
                var connectionOptions = FrameHeaders.ParseConnection(connection);

                upgrade   = (connectionOptions & ConnectionOptions.Upgrade) == ConnectionOptions.Upgrade;
                keepAlive = (connectionOptions & ConnectionOptions.KeepAlive) == ConnectionOptions.KeepAlive;
            }

            var transferEncoding = headers.HeaderTransferEncoding;

            if (transferEncoding.Count > 0)
            {
                var transferCoding = FrameHeaders.GetFinalTransferCoding(headers.HeaderTransferEncoding);

                // https://tools.ietf.org/html/rfc7230#section-3.3.3
                // If a Transfer-Encoding header field
                // is present in a request and the chunked transfer coding is not
                // the final encoding, the message body length cannot be determined
                // reliably; the server MUST respond with the 400 (Bad Request)
                // status code and then close the connection.
                if (transferCoding != TransferCoding.Chunked)
                {
                    context.ThrowRequestRejected(RequestRejectionReason.FinalTransferCodingNotChunked, transferEncoding.ToString());
                }

                if (upgrade)
                {
                    context.ThrowRequestRejected(RequestRejectionReason.UpgradeRequestCannotHavePayload);
                }

                return(new ForChunkedEncoding(keepAlive, context));
            }

            if (headers.ContentLength.HasValue)
            {
                var contentLength = headers.ContentLength.Value;

                if (contentLength == 0)
                {
                    return(keepAlive ? _zeroContentLengthKeepAlive : _zeroContentLengthClose);
                }
                else if (upgrade)
                {
                    context.ThrowRequestRejected(RequestRejectionReason.UpgradeRequestCannotHavePayload);
                }

                return(new ForContentLength(keepAlive, contentLength, context));
            }

            // Avoid slowing down most common case
            if (!object.ReferenceEquals(context.Method, HttpMethods.Get))
            {
                // If we got here, request contains no Content-Length or Transfer-Encoding header.
                // Reject with 411 Length Required.
                if (HttpMethods.IsPost(context.Method) || HttpMethods.IsPut(context.Method))
                {
                    var requestRejectionReason = httpVersion == HttpVersion.Http11 ? RequestRejectionReason.LengthRequired : RequestRejectionReason.LengthRequiredHttp10;
                    context.ThrowRequestRejected(requestRejectionReason, context.Method);
                }
            }

            if (upgrade)
            {
                return(new ForUpgrade(context));
            }

            return(keepAlive ? _zeroContentLengthKeepAlive : _zeroContentLengthClose);
        }
 public WebSocketRequestBuilder HttpVersion(HttpVersion value)
 {
     this.httpVersion = value;
     return(this);
 }
 public void OnStartLine(HttpMethod method, HttpVersion version, Span <byte> target, Span <byte> path, Span <byte> query, Span <byte> customMethod, bool pathEncoded)
 {
 }
Example #7
0
 public void OnStartLine(HttpMethod method, HttpVersion version, Span <byte> target, Span <byte> path, Span <byte> query, Span <byte> customMethod, bool pathEncoded)
 => RequestHandler.Connection.OnStartLine(method, version, target, path, query, customMethod, pathEncoded);
Example #8
0
        private int ParseMethodLine(byte[] array, int offset, int length, out HttpMethod method, out HttpVersion version, out RequestTarget requestTarget)
        {
            int    crlfIndex        = IndexOfCrlf(array, offset, length);
            string methodLineString = Encoding.ASCII.GetString(array, offset, crlfIndex - offset);

            string[] methodLineData = methodLineString.Split(' ');

            if (methodLineData.Length != 3 || string.IsNullOrWhiteSpace(methodLineString))
            {
                throw new RequestHeaderParserException("Invalid format of method line");
            }

            method        = ParseMethod(methodLineData[0]);
            requestTarget = ParseRequestTarget(methodLineData[1]);
            version       = ParseVersion(methodLineData[2]);

            return(crlfIndex - offset + 2);
        }
Example #9
0
        public static MessageBody For(
            HttpVersion httpVersion,
            HttpRequestHeaders headers,
            Http1Connection context)
        {
            // see also http://tools.ietf.org/html/rfc2616#section-4.4
            var keepAlive = httpVersion != HttpVersion.Http10;

            var upgrade = false;

            if (headers.HasConnection)
            {
                var connectionOptions = HttpHeaders.ParseConnection(headers.HeaderConnection);

                upgrade   = (connectionOptions & ConnectionOptions.Upgrade) == ConnectionOptions.Upgrade;
                keepAlive = (connectionOptions & ConnectionOptions.KeepAlive) == ConnectionOptions.KeepAlive;
            }

            if (upgrade)
            {
                if (headers.HeaderTransferEncoding.Count > 0 || (headers.ContentLength.HasValue && headers.ContentLength.Value != 0))
                {
                    BadHttpRequestException.Throw(RequestRejectionReason.UpgradeRequestCannotHavePayload);
                }

                return(new Http1UpgradeMessageBody(context));
            }

            if (headers.HasTransferEncoding)
            {
                var transferEncoding = headers.HeaderTransferEncoding;
                var transferCoding   = HttpHeaders.GetFinalTransferCoding(transferEncoding);

                // https://tools.ietf.org/html/rfc7230#section-3.3.3
                // If a Transfer-Encoding header field
                // is present in a request and the chunked transfer coding is not
                // the final encoding, the message body length cannot be determined
                // reliably; the server MUST respond with the 400 (Bad Request)
                // status code and then close the connection.
                if (transferCoding != TransferCoding.Chunked)
                {
                    BadHttpRequestException.Throw(RequestRejectionReason.FinalTransferCodingNotChunked, in transferEncoding);
                }

                // TODO may push more into the wrapper rather than just calling into the message body
                // NBD for now.
                return(new Http1ChunkedEncodingMessageBody(keepAlive, context));
            }

            if (headers.ContentLength.HasValue)
            {
                var contentLength = headers.ContentLength.Value;

                if (contentLength == 0)
                {
                    return(keepAlive ? MessageBody.ZeroContentLengthKeepAlive : MessageBody.ZeroContentLengthClose);
                }

                return(new Http1ContentLengthMessageBody(keepAlive, contentLength, context));
            }

            // If we got here, request contains no Content-Length or Transfer-Encoding header.
            // Reject with 411 Length Required.
            if (context.Method == HttpMethod.Post || context.Method == HttpMethod.Put)
            {
                var requestRejectionReason = httpVersion == HttpVersion.Http11 ? RequestRejectionReason.LengthRequired : RequestRejectionReason.LengthRequiredHttp10;
                BadHttpRequestException.Throw(requestRejectionReason, context.Method);
            }

            return(keepAlive ? MessageBody.ZeroContentLengthKeepAlive : MessageBody.ZeroContentLengthClose);
        }
Example #10
0
        // Compare with Http2Stream.TryValidatePseudoHeaders
        private void OnOriginFormTarget(HttpMethod method, HttpVersion version, Span <byte> target, Span <byte> path, Span <byte> query, Span <byte> customMethod, bool pathEncoded)
        {
            Debug.Assert(target[0] == ByteForwardSlash, "Should only be called when path starts with /");

            _requestTargetForm = HttpRequestTarget.OriginForm;

            if (target.Length == 1)
            {
                // If target.Length == 1 it can only be a forward slash (e.g. home page)
                // and we know RawTarget and Path are the same and QueryString is Empty
                RawTarget   = ForwardSlash;
                Path        = ForwardSlash;
                QueryString = string.Empty;
                // Clear parsedData as we won't check it if we come via this path again,
                // an setting to null is fast as it doesn't need to use a GC write barrier.
                _parsedRawTarget = _parsedPath = _parsedQueryString = null;
                return;
            }

            // 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"

            try
            {
                var disableStringReuse = ServerOptions.DisableStringReuse;
                // Read raw target before mutating memory.
                var previousValue = _parsedRawTarget;
                if (disableStringReuse ||
                    previousValue == null || previousValue.Length != target.Length ||
                    !StringUtilities.BytesOrdinalEqualsStringAndAscii(previousValue, target))
                {
                    // The previous string does not match what the bytes would convert to,
                    // so we will need to generate a new string.
                    RawTarget = _parsedRawTarget = target.GetAsciiStringNonNullCharacters();

                    previousValue = _parsedQueryString;
                    if (disableStringReuse ||
                        previousValue == null || previousValue.Length != query.Length ||
                        !StringUtilities.BytesOrdinalEqualsStringAndAscii(previousValue, query))
                    {
                        // The previous string does not match what the bytes would convert to,
                        // so we will need to generate a new string.
                        QueryString = _parsedQueryString = query.GetAsciiStringNonNullCharacters();
                    }
                    else
                    {
                        // Same as previous
                        QueryString = _parsedQueryString;
                    }

                    if (path.Length == 1)
                    {
                        // If path.Length == 1 it can only be a forward slash (e.g. home page)
                        Path = _parsedPath = ForwardSlash;
                    }
                    else
                    {
                        Path = _parsedPath = PathNormalizer.DecodePath(path, pathEncoded, RawTarget, query.Length);
                    }
                }
                else
                {
                    // As RawTarget is the same we can reuse the previous parsed values.
                    RawTarget   = _parsedRawTarget;
                    Path        = _parsedPath;
                    QueryString = _parsedQueryString;
                }
            }
            catch (InvalidOperationException)
            {
                ThrowRequestTargetRejected(target);
            }
        }
Example #11
0
 public Response(ResponseSettings settings, HttpStatus status = HttpStatus.Ok, HttpVersion protocolVersion = HttpVersion.HTTP11)
 {
     Headers         = settings.StaticResponseHeaders?.Clone() ?? new Dictionary <string, string>();
     Status          = status;
     ProtocolVersion = protocolVersion;
 }
Example #12
0
 public HttpRequest(HttpMethod method, string path, HttpVersion httpVersion, ICollection <HttpHeader> headers, ICollection <HttpCookie> cookies)
     : this(method, path, httpVersion)
 {
     this.headers = headers;
     this.cookies = cookies;
 }
        /// <summary>
        /// Creates a new instane of the http request class with the specified parameters.
        /// </summary>
        /// <param name="method">The http method.</param>
        /// <param name="url">The requested, relative url.</param>
        /// <param name="version">The http version.</param>
        public HttpRequest(HttpMethod method, Uri url, HttpVersion version)
        {
            if (url == null)
                throw new ArgumentNullException(nameof(url));

            if (url.IsAbsoluteUri)
                throw new ArgumentException("The specified url must not be absolute.", nameof(url));

            if (!Enum.IsDefined(typeof(HttpVersion), version))
                throw new ArgumentException("The argument is not valid.", nameof(version));

            _requestUrl = url;
            _method = method;
            HttpVersion = version;
        }
Example #14
0
        public static HttpRequest Parse(string request)
        {
            string[] lines             = request.Split(new string[] { NewLine }, StringSplitOptions.None);
            string[] requestLineTokens = lines[0].Split(' ');

            if (requestLineTokens.Length != 3)
            {
                throw new BadRequestException(InvalidRequestLine);
            }

            string[] linkTokens = requestLineTokens[1].Split(new char[] { '?' }, 2);

            HttpMethod  method  = HttpMethod.Parse(requestLineTokens[0]);
            string      path    = linkTokens[0];
            HttpVersion version = HttpVersion.Parse(requestLineTokens[2]);

            HttpRequest httpRequest = new HttpRequest(method, path, version);


            if (linkTokens.Length == 2)
            {
                httpRequest.FormData = HttpFormData.Parse(linkTokens[1]);
            }

            int i = 0;

            try
            {
                while (!string.IsNullOrEmpty(lines[++i]))
                {
                    HttpHeader header = HttpHeader.Parse(lines[i]);

                    if (header.Name.ToLower() == "cookie")
                    {
                        string[] cookies = header.Value.Split(new string[] { "; " }, StringSplitOptions.RemoveEmptyEntries);

                        foreach (var cookie in cookies)
                        {
                            string[] cookieKvp = cookie.Split('=');

                            if (cookieKvp.Length != 2)
                            {
                                throw new BadRequestException(InvalidCookieHeader);
                            }

                            httpRequest.AddCookie(new HttpCookie(cookieKvp[0], cookieKvp[1]));
                        }
                    }
                    else
                    {
                        httpRequest.AddHeader(header);
                    }
                }
            }
            catch (IndexOutOfRangeException ex)
            {
                throw new BadRequestException(NoEndOfHeaders, ex);
            }

            if (i < lines.Length - 1)
            {
                StringBuilder body = new StringBuilder();

                while (++i != lines.Length)
                {
                    string line = lines[i];

                    body.Append(line + NewLine);
                }

                httpRequest.Body = body.ToString()
                                   .TrimEnd(new char[] { '\r', '\n' });

                if (!string.IsNullOrEmpty(httpRequest.Body))
                {
                    httpRequest.FormData = HttpFormData.Parse(httpRequest.Body);
                }
            }

            return(httpRequest);
        }
Example #15
0
        public static void AppendHttpRequestLine <TFormatter>(this TFormatter formatter, HttpMethod method, HttpVersion version, string path) where TFormatter : ITextOutput
        {
            if (formatter.SymbolTable == SymbolTable.InvariantUtf8)
            {
                switch (method)
                {
                case HttpMethod.Get: formatter.AppendBytes(s_GetUtf8); break;

                case HttpMethod.Post: formatter.AppendBytes(s_PostUtf8); break;

                case HttpMethod.Put: formatter.AppendBytes(s_PutUtf8); break;

                case HttpMethod.Delete: formatter.AppendBytes(s_DeleteUtf8); break;

                default: formatter.Append(method.ToString()); formatter.Append(' '); break;
                }

                formatter.Append(path);

                switch (version)
                {
                case HttpVersion.V1_0: formatter.AppendBytes(s_Http10Utf8); break;

                case HttpVersion.V1_1: formatter.AppendBytes(s_Http11Utf8); break;

                case HttpVersion.V2_0: formatter.AppendBytes(s_Http20Utf8); break;

                default: throw new ArgumentException(nameof(version));
                }
            }
            else
            {
                formatter.Append(method.ToString());
                formatter.Append(' ');
                formatter.Append(path);
                formatter.Append(' ');
                switch (version)
                {
                case HttpVersion.V1_0: formatter.Append(Http10); break;

                case HttpVersion.V1_1: formatter.Append(Http11); break;

                case HttpVersion.V2_0: formatter.Append(Http20); break;

                default: throw new ArgumentException(nameof(version));
                }
                formatter.AppendHttpNewLine();
            }
        }
Example #16
0
        public static void AppendHttpStatusLine <TFormatter>(this TFormatter formatter, HttpVersion version, int statusCode, Utf8Span reasonCode) where TFormatter : ITextOutput
        {
            switch (version)
            {
            case HttpVersion.V1_0: formatter.Append(Http10); break;

            case HttpVersion.V1_1: formatter.Append(Http11); break;

            case HttpVersion.V2_0: formatter.Append(Http20); break;

            default: throw new ArgumentException(nameof(version));
            }

            formatter.Append(" ");
            formatter.Append(statusCode);
            formatter.Append(" ");
            formatter.Append(reasonCode);
            formatter.AppendHttpNewLine();
        }
Example #17
0
        private static void TestHttpRequest(string httpString, string expectedMethodString = null, string expectedUri = null, HttpVersion expectedVersion = null, HttpHeader expectedHeader = null, string expectedBodyString = null)
        {
            Datagram expectedBody = expectedBodyString == null ? null : new Datagram(Encoding.ASCII.GetBytes(expectedBodyString));
            HttpRequestMethod expectedMethod = expectedMethodString == null ? null : new HttpRequestMethod(expectedMethodString);

            Packet packet = BuildPacket(httpString);

            // HTTP
            HttpDatagram http = packet.Ethernet.IpV4.Tcp.Http;
            Assert.IsTrue(http.IsRequest, "IsRequest " + httpString);
            Assert.IsFalse(http.IsResponse, "IsResponse " + httpString);
            Assert.AreEqual(expectedVersion, http.Version, "Version " + httpString);
            Assert.AreEqual(expectedHeader, http.Header, "Header " + httpString);
            if (expectedHeader != null)
                Assert.AreEqual(expectedHeader.ToString(), http.Header.ToString(), "Header " + httpString);

            HttpRequestDatagram request = (HttpRequestDatagram)http;
            Assert.AreEqual(expectedMethod, request.Method, "Method " + httpString);
            Assert.AreEqual(expectedUri, request.Uri, "Uri " + httpString);
            Assert.AreEqual(expectedBody, request.Body, "Body " + httpString);
        }
Example #18
0
 private void ReturnResponse(HttpRequestHeader request, int responseCode, string message, string method, HttpVersion version, DataAdapterToStream stm)
 {
     ReturnResponse(request, responseCode, message, method, version, new KeyDataPair <string> [0], stm);
 }
Example #19
0
        // TODO: this is not a very general purpose routine. Maybe should not be in this base class?
        protected static void WriteCommonHeaders(
            HttpResponse formatter,
            HttpVersion version,
            int statuCode,
            string reasonCode,
            bool keepAlive)
        {
            var currentTime = DateTime.UtcNow;
            formatter.Headers.AppendHttpStatusLine(version, statuCode, new Utf8String(reasonCode));
            formatter.Headers.Append(new Utf8String("Date : ")); formatter.Headers.Append(currentTime, 'R');
            formatter.Headers.AppendHttpNewLine();
            formatter.Headers.Append("Server : .NET Core Sample Server");
            formatter.Headers.AppendHttpNewLine();
            formatter.Headers.Append("Content-Type : text/html; charset=UTF-8");
            formatter.Headers.AppendHttpNewLine();

            if (!keepAlive)
            {
                formatter.Headers.Append("Connection : close");
            }
        }
Example #20
0
 protected DefaultHttpMessage(HttpVersion version) : this(version, true, false)
 {
 }
 IHttpClientBuilder IHttpClientBuilder.SetVersion(HttpVersion version)
 {
     return(this.SetVersion(version));
 }
Example #22
0
 public void OnStartLine(HttpMethod method, HttpVersion version, Span <byte> target, Span <byte> path, Span <byte> query, Span <byte> customMethod, bool pathEncoded)
 {
     Console.WriteLine("On start line");
 }
Example #23
0
        private void ReturnResponse(HttpRequestHeader request, int responseCode, string message, string method, HttpVersion version, IEnumerable <KeyDataPair <string> > sendHeaders, DataAdapterToStream stm)
        {
            if (request != null)
            {
                FlushRequest(request);
            }

            HttpResponseDataChunk response = new HttpResponseDataChunk();

            if (_config.Version10Proxy && !version.IsVersionUnknown)
            {
                response.Version = HttpVersion.Version10;
            }
            else
            {
                response.Version = version;
            }

            response.ResponseCode = responseCode;
            response.Message      = message;
            response.FinalChunk   = true;
            response.Body         = new byte[0];

            List <KeyDataPair <string> > headers = new List <KeyDataPair <string> >(sendHeaders);

            headers.Add(new KeyDataPair <string>("X-Proxy-Server", "CANAPE"));

            if (response.Body.Length > 0)
            {
                headers.Add(new KeyDataPair <string>("Content-Type", "text/html"));
            }

            response.Headers = headers.ToArray();

            if (method.Equals("HEAD", StringComparison.OrdinalIgnoreCase))
            {
                response.HeadResponse = true;
            }
            else if (method.Equals("CONNECT", StringComparison.OrdinalIgnoreCase))
            {
                response.ConnectResponse = true;
            }

            response.WriteChunk(new DataWriter(stm));
        }
 /// <summary>
 /// 设置 HTTP 协议版本号。
 /// </summary>
 /// <param name="version"></param>
 /// <returns></returns>
 public new WxpayApiClientBuilder SetVersion(HttpVersion version)
 {
     base.SetVersion(version);
     return(this);
 }
Example #25
0
        private void OnOriginFormTarget(HttpMethod method, HttpVersion version, Span <byte> target, Span <byte> path, Span <byte> query, Span <byte> customMethod, bool pathEncoded)
        {
            Debug.Assert(target[0] == ByteForwardSlash, "Should only be called when path starts with /");

            _requestTargetForm = HttpRequestTarget.OriginForm;

            // 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 = null;
            string rawTarget      = null;

            try
            {
                // Read raw target before mutating memory.
                rawTarget = target.GetAsciiStringNonNullCharacters();

                if (pathEncoded)
                {
                    // URI was encoded, unescape and then parse as UTF-8
                    var pathLength = UrlEncoder.Decode(path, path);

                    // Removing dot segments must be done after unescaping. From RFC 3986:
                    //
                    // URI producing applications should percent-encode data octets that
                    // correspond to characters in the reserved set unless these characters
                    // are specifically allowed by the URI scheme to represent data in that
                    // component.  If a reserved character is found in a URI component and
                    // no delimiting role is known for that character, then it must be
                    // interpreted as representing the data octet corresponding to that
                    // character's encoding in US-ASCII.
                    //
                    // https://tools.ietf.org/html/rfc3986#section-2.2
                    pathLength = PathNormalizer.RemoveDotSegments(path.Slice(0, pathLength));

                    requestUrlPath = GetUtf8String(path.Slice(0, pathLength));
                }
                else
                {
                    var pathLength = PathNormalizer.RemoveDotSegments(path);

                    if (path.Length == pathLength && query.Length == 0)
                    {
                        // If no decoding was required, no dot segments were removed and
                        // there is no query, the request path is the same as the raw target
                        requestUrlPath = rawTarget;
                    }
                    else
                    {
                        requestUrlPath = path.Slice(0, pathLength).GetAsciiStringNonNullCharacters();
                    }
                }
            }
            catch (InvalidOperationException)
            {
                ThrowRequestTargetRejected(target);
            }

            QueryString = query.GetAsciiStringNonNullCharacters();
            RawTarget   = rawTarget;
            Path        = requestUrlPath;
        }
 public HeaderLine(HttpMethod method, Uri uri, HttpVersion version)
 {
     Method  = method;
     Uri     = uri;
     Version = version;
 }
        protected override int ProcessData(byte[] data, bool writeExcess)
        {
            ThrowIfEnded();
            bool run = true; int i = 0;

            for (; i < data.Length && run; i++)
            {
                char c = (char)data[i];
                switch (State)
                {
                case ResponseParserState.Version:
                    if (c != WHITESPACE)
                    {
                        StringQueue.Append(c);
                    }
                    else
                    {
                        if (!HttpVersion.TryParse(StringQueue.Next(), out HttpVersion result))
                        {
                            End();
                            return(-1);
                        }
                        Incoming.Version = result;
                        StringQueue.New();
                        State = ResponseParserState.StatusCode;
                    }
                    break;

                case ResponseParserState.StatusCode:
                    if (c != WHITESPACE)
                    {
                        StringQueue.Append(c);
                    }
                    else
                    {
                        if (!ushort.TryParse(StringQueue.Next(), out ushort result))
                        {
                            End();
                            return(-1);
                        }
                        Incoming.StatusCode = result;
                        StringQueue.New();
                        State = ResponseParserState.StatusDescription;
                    }
                    break;

                case ResponseParserState.StatusDescription:
                    if (c != CR)
                    {
                        StringQueue.Append(c);
                    }
                    else
                    {
                        Incoming.StatusDescription = StringQueue.Next();
                        StringQueue.New();
                        State = ResponseParserState.FirstLf;
                    }
                    break;

                case ResponseParserState.FirstLf:
                    if (c != LF)
                    {
                        End(); return(-1);
                    }
                    State = ResponseParserState.HeaderName;
                    break;

                case ResponseParserState.HeaderName:
                    if (c == CR)
                    {
                        State = ResponseParserState.Lf;
                    }
                    else if (c != COLON)
                    {
                        StringQueue.Append(c);
                    }
                    else
                    {
                        StringQueue.New();
                        State = ResponseParserState.HeaderValue;
                    }
                    break;

                case ResponseParserState.HeaderValue:
                    if (c != CR)
                    {
                        StringQueue.Append(c);
                    }
                    else
                    {
                        Incoming.Headers.Set(StringQueue.Next(), StringQueue.Next().Trim());
                        State = ResponseParserState.HeaderLf;
                    }
                    break;

                case ResponseParserState.HeaderLf:
                    if (c != LF)
                    {
                        End(); return(-1);
                    }
                    else
                    {
                        StringQueue.New();
                        State = ResponseParserState.HeaderName;
                    }
                    break;

                case ResponseParserState.Lf:
                    if (c != LF)
                    {
                        End(); return(-1);
                    }
                    run = false;
                    PushIncoming();
                    State = ResponseParserState.Version;
                    break;
                }
            }
            if (writeExcess)
            {
                int    len    = data.Length - i;
                byte[] sliced = new byte[len];
                System.Buffer.BlockCopy(data, i, sliced, 0, len);
                Bwrite(sliced);
            }
            return(i);
        }
Example #28
0
 public void OnStartLine(HttpMethod method, HttpVersion version, Span <byte> target, Span <byte> path, Span <byte> query, Span <byte> customMethod, bool pathEncoded)
 => Frame.OnStartLine(method, version, target, path, query, customMethod, pathEncoded);
Example #29
0
 /// <summary>
 /// Handle a HTTP request
 /// </summary>
 /// <param name="method">The HTTP method</param>
 /// <param name="path">The HTTP path</param>
 /// <param name="body">The body of the data</param>
 /// <param name="headers">A dictionary of headers</param>
 /// <param name="version">HTTP version</param>
 /// <param name="logger">A logger to log data to</param>
 /// <returns>A HTTP response data object, or null if no response</returns>
 protected abstract HttpServerResponseData HandleRequest(string method, string path, byte[] body,
                                                         Dictionary <string, string> headers, HttpVersion version, Logger logger);
Example #30
0
 public HttpResponse(ResponseCode responseCode,
                     HttpVersion version = HttpVersion.Http11)
 {
     ResponseCode = responseCode;
     HttpVersion  = version;
 }
Example #31
0
        protected override HttpServerResponseData HandleRequest(string method, string path, byte[] body,
                                                                Dictionary <string, string> headers, HttpVersion version, Logger logger)
        {
            Regex pathRegex             = GeneralUtils.GlobToRegex(Config.HttpPath);
            HttpServerResponseData data = new HttpServerResponseData();

            data.CloseAfterSending = Config.CloseAfterSending;

            if (pathRegex.IsMatch(path))
            {
                data.ResponseCode = 200;
                data.Message      = "OK";
                if (Config.ValidResponseData != null)
                {
                    data.Body = Config.ValidResponseData;
                }
            }
            else
            {
                data.ResponseCode = 404;
                data.Message      = "Not Found";
                if (Config.NotFoundResponseData != null)
                {
                    data.Body = Config.NotFoundResponseData;
                }
            }

            data.Headers["Content-Type"] = Config.ContentType ?? "text/html";

            return(data);
        }
Example #32
0
        } // ValidateVerbCharacter

        // read headers
        public BaseTransportHeaders ReadHeaders()
        {
            bool bSendContinue = false;

            BaseTransportHeaders headers = new BaseTransportHeaders();

            // read first line
            String verb, requestURI, version;

            ReadFirstLine(out verb, out requestURI, out version);

            if ((verb == null) || (requestURI == null) || (version == null))
            {
                throw new RemotingException(
                          CoreChannel.GetResourceString(
                              "Remoting_Http_UnableToReadFirstLine"));
            }

            if (version.Equals("HTTP/1.1")) // most common case
            {
                _version = HttpVersion.V1_1;
            }
            else
            if (version.Equals("HTTP/1.0"))
            {
                _version = HttpVersion.V1_0;
            }
            else
            {
                _version = HttpVersion.V1_1; // (assume it will understand 1.1)
            }
            if (_version == HttpVersion.V1_1)
            {
                _allowChunkedResponse = true;
                _keepAlive            = true;
            }
            else // it's a 1.0 client
            {
                _allowChunkedResponse = false;
                _keepAlive            = false;
            }


            // update request uri to be sure that it has no channel data
            String channelURI;
            String objectURI;

            channelURI = HttpChannelHelper.ParseURL(requestURI, out objectURI);
            if (channelURI == null)
            {
                objectURI = requestURI;
            }

            headers["__RequestVerb"] = verb;
            headers.RequestUri       = objectURI;
            headers["__HttpVersion"] = version;

            // check to see if we must send continue
            if ((_version == HttpVersion.V1_1) &&
                (verb.Equals("POST") || verb.Equals("PUT")))
            {
                bSendContinue = true;
            }

            ReadToEndOfHeaders(headers, out _chunkedEncoding, out _contentLength,
                               ref _keepAlive, ref bSendContinue);

            if (bSendContinue && (_version != HttpVersion.V1_0))
            {
                SendContinue();
            }

            // add IP address and Connection Id to headers
            headers[CommonTransportKeys.IPAddress]    = ((IPEndPoint)NetSocket.RemoteEndPoint).Address;
            headers[CommonTransportKeys.ConnectionId] = _connectionId;

            return(headers);
        } // ReadHeaders
Example #33
0
 internal HttpDatagram(byte[] buffer, int offset, int length, 
     HttpVersion version, HttpHeader header, Datagram body)
     : base(buffer, offset, length)
 {
     Version = version;
     Header = header;
     Body = body;
 }
        public void GetsKnownVersion(string input, bool expectedResult, string expectedKnownString, HttpVersion version)
        {
            // Arrange
            var block = new Span <byte>(Encoding.ASCII.GetBytes(input));

            // Act
            HttpVersion knownVersion;
            var         result   = block.GetKnownVersion(out knownVersion, out var length);
            string      toString = null;

            if (knownVersion != HttpVersion.Unknown)
            {
                toString = HttpUtilities.VersionToString(knownVersion);
            }
            // Assert
            Assert.Equal(expectedResult, result);
            Assert.Equal(expectedKnownString, toString);
            Assert.Equal(expectedKnownString?.Length ?? 0, length);
        }
Example #35
0
 public HttpParser Version(out HttpVersion version)
 {
     uint? major;
     uint? minor;
     Bytes(_httpSlash).DecimalNumber(out major).Dot().DecimalNumber(out minor);
     version = major != null && minor != null ? new HttpVersion(major.Value, minor.Value) : null;
     return this;
 }
Example #36
0
 public HttpResponse(HttpVersion httpVersion, HttpResponseCode responseCode, ICollection <HttpHeader> headers, ICollection <HttpCookie> cookies)
     : this(httpVersion, responseCode)
 {
     this.headers = headers;
     this.cookies = cookies;
 }
Example #37
0
        private static void TestHttpResponse(string httpString, HttpVersion expectedVersion = null, uint? expectedStatusCode = null, string expectedReasonPhrase = null, HttpHeader expectedHeader = null, string expectedBodyString = null)
        {
            Datagram expectedBody = expectedBodyString == null ? null : new Datagram(Encoding.ASCII.GetBytes(expectedBodyString));

            Packet packet = BuildPacket(httpString);

            // HTTP
            HttpDatagram http = packet.Ethernet.IpV4.Tcp.Http;
            Assert.IsFalse(http.IsRequest, "IsRequest " + httpString);
            Assert.IsTrue(http.IsResponse, "IsResponse " + httpString);
            Assert.AreEqual(expectedVersion, http.Version, "Version " + httpString);
            Assert.AreEqual(expectedHeader, http.Header, "Header " + httpString);
            if (expectedHeader != null)
                Assert.IsNotNull(http.Header.ToString());

            HttpResponseDatagram response = (HttpResponseDatagram)http;
            Assert.AreEqual(expectedStatusCode, response.StatusCode, "StatusCode " + httpString);
            Assert.AreEqual(expectedReasonPhrase == null ? null : new Datagram(Encoding.ASCII.GetBytes(expectedReasonPhrase)), response.ReasonPhrase, "ReasonPhrase " + httpString);
            Assert.AreEqual(expectedBody, response.Body, "Body " + httpString);
        }
 public static string StringValue(this HttpVersion httpVersion)
 {
     return(httpVersion == HttpVersion.Http11 ? "HTTP/1.1" : "HTTP/1.0");
 }
Example #39
0
        private static void TestHttpRequest(string httpString, string expectedMethodString = null, string expectedUri = null, HttpVersion expectedVersion = null, HttpHeader expectedHeader = null, string expectedBodyString = null)
        {
            Datagram          expectedBody   = expectedBodyString == null ? null : new Datagram(Encoding.ASCII.GetBytes(expectedBodyString));
            HttpRequestMethod expectedMethod = expectedMethodString == null ? null : new HttpRequestMethod(expectedMethodString);

            Packet packet = BuildPacket(httpString);

            // HTTP
            HttpDatagram http = packet.Ethernet.IpV4.Tcp.Http;

            Assert.IsTrue(http.IsRequest, "IsRequest " + httpString);
            Assert.IsFalse(http.IsResponse, "IsResponse " + httpString);
            Assert.AreEqual(expectedVersion, http.Version, "Version " + httpString);
            Assert.AreEqual(expectedHeader, http.Header, "Header " + httpString);
            if (expectedHeader != null)
            {
                Assert.AreEqual(expectedHeader.ToString(), http.Header.ToString(), "Header " + httpString);
            }

            HttpRequestDatagram request = (HttpRequestDatagram)http;

            Assert.AreEqual(expectedMethod, request.Method, "Method " + httpString);
            Assert.AreEqual(expectedUri, request.Uri, "Uri " + httpString);
            Assert.AreEqual(expectedBody, request.Body, "Body " + httpString);
        }
Example #40
0
 public HttpStatusLine(HttpVersion version,
                       HttpStatusCode code)
     : this(version, (int)code, ReasonPhase(code))
 {
 }