예제 #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;
            }
        }
예제 #2
0
 public void Remove(StringCI key)
 {
     if (ContainsKey(key))
     {
         _keys.Remove(key);
         _entries.Remove(key);
     }
 }
예제 #3
0
 public bool ContainsKey(StringCI key)
 {
     if (key == null)
     {
         throw new ArgumentNullException(nameof(key));
     }
     return(_entries.ContainsKey(key));
 }
예제 #4
0
        public string GetFirst(StringCI key)
        {
            if (!_entries.ContainsKey(key) || _entries[key].Count == 0)
            {
                throw new InvalidOperationException($"Key does not exist {key}");
            }

            return(_entries[key][0]);
        }
예제 #5
0
 public IReadOnlyList <string> Get(StringCI key, bool getAsCopy)
 {
     if (!_entries.ContainsKey(key))
     {
         throw new InvalidOperationException($"Key does not exist {key}");
     }
     if (getAsCopy)
     {
         return(_entries[key].ToList());
     }
     return(_entries[key]);
 }
예제 #6
0
 public void Add(StringCI key, string value)
 {
     if (value == null)
     {
         throw new ArgumentNullException(nameof(value));
     }
     if (ContainsKey(key))
     {
         _entries[key].Add(value);
     }
     else
     {
         _entries[key] = new List <string>();
         _entries[key].Add(value);
         _keys.Add(key);
     }
 }
예제 #7
0
 public string this[StringCI key]
 {
     get {
         var values = Get(key, false);
         if (values.Count == 0)
         {
             throw new IndexOutOfRangeException(nameof(key));
         }
         return(values[0]);
     }
     set {
         if (ContainsKey(key))
         {
             Remove(key);
         }
         Add(key, value);
     }
 }
예제 #8
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);
        }
예제 #9
0
 public virtual void Remove(StringCI key)
 {
     _entries.Remove(key);
     InvalidCachedPlainText();
 }
예제 #10
0
 public virtual void Add(StringCI key, string value)
 {
     _entries.Add(key, value);
     InvalidCachedPlainText();
 }
예제 #11
0
 public IReadOnlyList <string> Get(StringCI key, bool getAsCopy)
 => _entries.Get(key, getAsCopy);
예제 #12
0
 public string GetFirst(StringCI key) => _entries.GetFirst(key);
예제 #13
0
 public bool ContainsKey(StringCI key) => _entries.ContainsKey(key);