Beispiel #1
0
        public async Task ExecuteAsync()
        {
            try
            {
                // Read the request header, minimum required prior processing the request;
                await _request.WaitForHttpHeaderAsync();

                _logger.Debug($"{_request.Header.Method} {_request.Header.Uri}");

                // Got the header.
                // Very likely that we just woke up from a keep-alive sleep,
                // Abort the watch dog to avoid being killed.
                if (_keepAliveService.IsRegistered(_connection))
                {
                    _keepAliveService.Deregister(_connection);
                }

                // Process the request-response
                SetDefaultResponseHeaders();
                await ProcessRequestResponseAsync();

                // Before continuing to the next HTTP session in the connection loop,
                // the response header + body of this message must be completely written
                // (or abort the connection),
                // otherwise it causes unexpected behaviour for the other HTTP client.
                await _response.Body.CompleteAsync();

                // If we promised the client to keep alive, do it.
                if (!StringCI.Compare(
                        _response.Header[HttpKeys.Connection], HttpKeys.CloseValue))
                {
                    _keepAliveService.Register(_connection);
                }
            }
            catch (HttpBadRequestException ex)
            {
                // Caused by malformed HTTP request message
                // sent by the client;
                // We'll return with an 400 BadRequest
                _logger.Warn(ex.Message);
                await TryRespondErrorAsync(
                    400,
                    $"<h1>Bad Request</h1><br />{ex.ToString()}");
            }
            catch (TcpException) {
                throw;
            }
            catch (Exception ex) {
                // Unexpected error caused by us,
                // We'll return with an internal error
                _logger.Error(ex);
                await TryRespondErrorAsync(
                    500,
                    $"<h1>Internal Server Error</h1><br />{ex.ToString()}");

                // Let the connection loop handle this exception,
                // probably by closing the connection.
                throw;
            }
        }
Beispiel #2
0
        /// <summary>
        /// Based on the request header and keep-alive service state,
        /// should we keep the current connection alive?
        /// </summary>
        bool ShoudKeepAlive()
        {
            if (false == _keepAliveService.CanRegister(_connection))
            {
                return(false);
            }

            // https://tools.ietf.org/html/rfc7230#section-6
            // If the "close" connection option is present, the connection will
            // not persist after the current response; else,
            if (_request.Header.ContainsKey(HttpKeys.Connection) &&
                StringCI.Compare(_request.Header[HttpKeys.Connection], HttpKeys.CloseValue))
            {
                return(false);
            }

            // If the received protocol is HTTP/1.1 (or later), the connection
            // will persist after the current response; else,
            if (_request.Header.Protocol == HttpProtocol.Http11)
            {
                return(true);
            }

            // If the received protocol is HTTP / 1.0, the "keep-alive" connection
            // option is present, the recipient is not a proxy, and the recipient
            // wishes to honor the HTTP/ 1.0 "keep-alive" mechanism, the
            // connection will persist after the current response; otherwise,
            if (_request.Header.Protocol == HttpProtocol.Http10 &&
                _request.Header.ContainsKey(HttpKeys.Connection) &&
                StringCI.Compare(_request.Header[HttpKeys.Connection], HttpKeys.KeepAliveValue))
            {
                return(true);
            }

            // Else, the connection will close after the current response.
            return(false);
        }