Exemplo n.º 1
0
        internal void SendHeaders(bool closing, MemoryStream ms, bool isWebSocketHandshake = false)
        {
            if (!isWebSocketHandshake)
            {
                if (_webHeaders["Server"] == null)
                {
                    _webHeaders.Set("Server", "Microsoft-NetCore/2.0");
                }

                if (_webHeaders["Date"] == null)
                {
                    _webHeaders.Set("Date", DateTime.UtcNow.ToString("r", CultureInfo.InvariantCulture));
                }

                if (_boundaryType == BoundaryType.None)
                {
                    if (HttpListenerRequest.ProtocolVersion <= HttpVersion.Version10)
                    {
                        _keepAlive = false;
                    }
                    else
                    {
                        _boundaryType = BoundaryType.Chunked;
                    }

                    if (CanSendResponseBody(_httpContext.Response.StatusCode))
                    {
                        _contentLength = -1;
                    }
                    else
                    {
                        _boundaryType  = BoundaryType.ContentLength;
                        _contentLength = 0;
                    }
                }

                if (_boundaryType != BoundaryType.Chunked)
                {
                    if (_boundaryType != BoundaryType.ContentLength && closing)
                    {
                        _contentLength = CanSendResponseBody(_httpContext.Response.StatusCode) ? -1 : 0;
                    }

                    if (_boundaryType == BoundaryType.ContentLength)
                    {
                        _webHeaders.Set("Content-Length", _contentLength.ToString("D", CultureInfo.InvariantCulture));
                    }
                }

                /* Apache forces closing the connection for these status codes:
                 *	HttpStatusCode.BadRequest               400
                 *	HttpStatusCode.RequestTimeout           408
                 *	HttpStatusCode.LengthRequired           411
                 *	HttpStatusCode.RequestEntityTooLarge    413
                 *	HttpStatusCode.RequestUriTooLong        414
                 *	HttpStatusCode.InternalServerError      500
                 *	HttpStatusCode.ServiceUnavailable       503
                 */
                bool conn_close = (_statusCode == (int)HttpStatusCode.BadRequest || _statusCode == (int)HttpStatusCode.RequestTimeout ||
                                   _statusCode == (int)HttpStatusCode.LengthRequired || _statusCode == (int)HttpStatusCode.RequestEntityTooLarge ||
                                   _statusCode == (int)HttpStatusCode.RequestUriTooLong || _statusCode == (int)HttpStatusCode.InternalServerError ||
                                   _statusCode == (int)HttpStatusCode.ServiceUnavailable);

                if (!conn_close)
                {
                    conn_close = !_httpContext.Request.KeepAlive;
                }

                // They sent both KeepAlive: true and Connection: close
                if (!_keepAlive || conn_close)
                {
                    _webHeaders.Set("Connection", "Close");
                    conn_close = true;
                }

                if (SendChunked)
                {
                    _webHeaders.Set("Transfer-Encoding", "Chunked");
                }

                int reuses = _httpContext.Connection.Reuses;
                if (reuses >= 100)
                {
                    _forceCloseChunked = true;
                    if (!conn_close)
                    {
                        _webHeaders.Set("Connection", "Close");
                        conn_close = true;
                    }
                }

                if (HttpListenerRequest.ProtocolVersion <= HttpVersion.Version10)
                {
                    if (_keepAlive)
                    {
                        Headers["Keep-Alive"] = "true";
                    }

                    if (!conn_close)
                    {
                        _webHeaders.Set("Connection", "Keep-Alive");
                    }
                }

                ComputeCookies();
            }

            Encoding     encoding = _textEncoding.GetDefaultEncoding();
            StreamWriter writer   = new StreamWriter(ms, encoding, 256);

            writer.Write("HTTP/1.1 {0} ", _statusCode); // "1.1" matches Windows implementation, which ignores the response version
            writer.Flush();
            byte[] statusDescriptionBytes = WebHeaderEncoding.GetBytes(StatusDescription);
            ms.Write(statusDescriptionBytes, 0, statusDescriptionBytes.Length);
            writer.Write("\r\n");

            writer.Write(FormatHeaders(_webHeaders));
            writer.Flush();
            int preamble = encoding.GetPreamble().Length;

            EnsureResponseStream();

            /* Assumes that the ms was at position 0 */
            ms.Position = preamble;
            SentHeaders = !isWebSocketHandshake;
        }
Exemplo n.º 2
0
        internal void SendHeaders(bool closing, MemoryStream ms)
        {
            Encoding encoding = content_encoding;

            if (encoding == null)
            {
                encoding = _textEncoding.GetDefaultEncoding();
            }

            if (content_type != null)
            {
                if (content_encoding != null && content_type.IndexOf("charset=", StringComparison.OrdinalIgnoreCase) == -1)
                {
                    string enc_name = content_encoding.WebName;
                    headers.SetInternal("Content-Type", content_type + "; charset=" + enc_name);
                }
                else
                {
                    headers.SetInternal("Content-Type", content_type);
                }
            }

            if (headers["Server"] == null)
            {
                headers.SetInternal("Server", "Mono-HTTPAPI/1.0");
            }

            CultureInfo inv = CultureInfo.InvariantCulture;

            if (headers["Date"] == null)
            {
                headers.SetInternal("Date", DateTime.UtcNow.ToString("r", inv));
            }

            if (!chunked)
            {
                if (!cl_set && closing)
                {
                    cl_set         = true;
                    content_length = 0;
                }

                if (cl_set)
                {
                    headers.SetInternal("Content-Length", content_length.ToString(inv));
                }
            }

            Version v = context.Request.ProtocolVersion;

            if (!cl_set && !chunked && v >= HttpVersion.Version11)
            {
                chunked = true;
            }

            /* Apache forces closing the connection for these status codes:
             *	HttpStatusCode.BadRequest       400
             *	HttpStatusCode.RequestTimeout       408
             *	HttpStatusCode.LengthRequired       411
             *	HttpStatusCode.RequestEntityTooLarge    413
             *	HttpStatusCode.RequestUriTooLong    414
             *	HttpStatusCode.InternalServerError  500
             *	HttpStatusCode.ServiceUnavailable   503
             */
            bool conn_close = status_code == 400 || status_code == 408 || status_code == 411 ||
                              status_code == 413 || status_code == 414 ||
                              status_code == 500 ||
                              status_code == 503;

            if (conn_close == false)
            {
                conn_close = !context.Request.KeepAlive;
            }

            // They sent both KeepAlive: true and Connection: close!?
            if (!keep_alive || conn_close)
            {
                headers.SetInternal("Connection", "close");
                conn_close = true;
            }

            if (chunked)
            {
                headers.SetInternal("Transfer-Encoding", "chunked");
            }

            //int reuses = context.Connection.Reuses;
            //if (reuses >= 100)
            //{
            //    _logger.Debug("HttpListenerResponse - keep alive has exceeded 100 uses and will be closed.");

            //    force_close_chunked = true;
            //    if (!conn_close)
            //    {
            //        headers.SetInternal("Connection", "close");
            //        conn_close = true;
            //    }
            //}

            if (!conn_close)
            {
                if (context.Request.ProtocolVersion <= HttpVersion.Version10)
                {
                    headers.SetInternal("Connection", "keep-alive");
                }
            }

            if (location != null)
            {
                headers.SetInternal("Location", location);
            }

            if (cookies != null)
            {
                foreach (Cookie cookie in cookies)
                {
                    headers.SetInternal("Set-Cookie", cookie.ToString());
                }
            }

            using (StreamWriter writer = new StreamWriter(ms, encoding, 256, true))
            {
                writer.Write("HTTP/{0} {1} {2}\r\n", version, status_code, status_description);
                string headers_str = headers.ToStringMultiValue();
                writer.Write(headers_str);
                writer.Flush();
            }

            int preamble = encoding.GetPreamble().Length;

            if (output_stream == null)
            {
                output_stream = context.Connection.GetResponseStream();
            }

            /* Assumes that the ms was at position 0 */
            ms.Position = preamble;
            HeadersSent = true;
        }