예제 #1
0
        public ResponseStream GetResponseStream()
        {
            // TODO: can we get this stream before reading the input?
            if (o_stream == null)
            {
                HttpListener listener = context.Listener;

                if (listener == null)
                {
                    return(new ResponseStream(stream, context.Response, true, _logger, _connectionId));
                }

                o_stream = new ResponseStream(stream, context.Response, listener.IgnoreWriteExceptions, _logger, _connectionId);
            }
            return(o_stream);
        }
예제 #2
0
        void Init()
        {
            if (ssl_stream != null)
            {
                //ssl_stream.AuthenticateAsServer(client_cert, true, (SslProtocols)ServicePointManager.SecurityProtocol, false);
            }

            context_bound = false;
            i_stream      = null;
            o_stream      = null;
            prefix        = null;
            chunked       = false;
            ms            = new MemoryStream();
            position      = 0;
            input_state   = InputState.RequestLine;
            line_state    = LineState.None;
            context       = new HttpListenerContext(this, _logger);
        }
예제 #3
0
        public Stream GetResponseStream(bool isExpect100Continue = false)
        {
            // TODO: can we get this stream before reading the input?
            if (o_stream == null)
            {
                //context.Response.DetermineIfChunked();

                if (context.Response.SendChunked || isExpect100Continue || context.Request.IsWebSocketRequest || true)
                {
                    o_stream = new ResponseStream(stream, context.Response, _memoryStreamFactory, _textEncoding);
                }
                else
                {
                    o_stream = stream;
                    using (var headerStream = ResponseStream.GetHeaders(context.Response, _memoryStreamFactory, false))
                    {
                        headerStream.CopyTo(o_stream);
                    }
                }
            }
            return(o_stream);
        }
예제 #4
0
        internal void SendHeaders(bool closing, MemoryStream ms)
        {
            Encoding encoding = content_encoding;

            if (encoding == null)
            {
                encoding = Encoding.Default;
            }

            if (content_type != null)
            {
                if (content_encoding != null && content_type.IndexOf("charset=", StringComparison.Ordinal) == -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;
        }
예제 #5
0
        internal void Close(bool force_close)
        {
            if (sock != null)
            {
                if (!context.Request.IsWebSocketRequest || !force_close)
                {
                    Stream st = GetResponseStream();
                    if (st != null)
                    {
                        st.Close();
                    }

                    o_stream = null;
                }
            }

            if (sock != null)
            {
                force_close |= !context.Request.KeepAlive;
                if (!force_close)
                {
                    force_close = (context.Response.Headers["connection"] == "close");
                }

                /*
                 * if (!force_close) {
                 * //					bool conn_close = (status_code == 400 || status_code == 408 || status_code == 411 ||
                 * //							status_code == 413 || status_code == 414 || status_code == 500 ||
                 * //							status_code == 503);
                 *
                 *  force_close |= (context.Request.ProtocolVersion <= HttpVersion.Version10);
                 * }
                 */

                if (!force_close && context.Request.FlushInput())
                {
                    if (chunked && context.Response.ForceCloseChunked == false)
                    {
                        // Don't close. Keep working.
                        reuses++;
                        Unbind();
                        Init();
                        BeginReadRequest();
                        return;
                    }

                    reuses++;
                    Unbind();
                    Init();
                    BeginReadRequest();
                    return;
                }

                Socket s = sock;
                sock = null;
                try
                {
                    if (s != null)
                    {
                        s.Shutdown(SocketShutdown.Both);
                    }
                }
                catch
                {
                }
                finally
                {
                    if (s != null)
                    {
                        s.Close();
                    }
                }
                Unbind();
                RemoveConnection();
                return;
            }
        }
        internal void FinishInitialization()
        {
            string host = UserHostName;

            if (version > HttpVersion.Version10 && (host == null || host.Length == 0))
            {
                context.ErrorMessage = "Invalid host name";
                return;
            }

            string path;
            Uri    raw_uri = null;

            if (MaybeUri(raw_url.ToLowerInvariant()) && Uri.TryCreate(raw_url, UriKind.Absolute, out raw_uri))
            {
                path = raw_uri.PathAndQuery;
            }
            else
            {
                path = raw_url;
            }

            if ((host == null || host.Length == 0))
            {
                host = UserHostAddress;
            }

            if (raw_uri != null)
            {
                host = raw_uri.Host;
            }

            int colon = host.LastIndexOf(':');

            if (colon >= 0)
            {
                host = host.Substring(0, colon);
            }

            string base_uri = String.Format("{0}://{1}:{2}",
                                            (IsSecureConnection) ? (IsWebSocketRequest ? "wss" : "https") : (IsWebSocketRequest ? "ws" : "http"),
                                            host, LocalEndPoint.Port);

            if (!Uri.TryCreate(base_uri + path, UriKind.Absolute, out url))
            {
                context.ErrorMessage = WebUtility.HtmlEncode("Invalid url: " + base_uri + path);
                return;
            }

            CreateQueryString(url.Query);

            if (version >= HttpVersion.Version11)
            {
                string t_encoding = Headers["Transfer-Encoding"];
                is_chunked = (t_encoding != null && String.Compare(t_encoding, "chunked", StringComparison.OrdinalIgnoreCase) == 0);
                // 'identity' is not valid!
                if (t_encoding != null && !is_chunked)
                {
                    context.Connection.SendError(null, 501);
                    return;
                }
            }

            if (!is_chunked && !cl_set)
            {
                if (String.Compare(method, "POST", StringComparison.OrdinalIgnoreCase) == 0 ||
                    String.Compare(method, "PUT", StringComparison.OrdinalIgnoreCase) == 0)
                {
                    context.Connection.SendError(null, 411);
                    return;
                }
            }

            if (String.Compare(Headers["Expect"], "100-continue", StringComparison.OrdinalIgnoreCase) == 0)
            {
                ResponseStream output = context.Connection.GetResponseStream();
                output.InternalWrite(_100continue, 0, _100continue.Length);
            }
        }