Beispiel #1
0
 /// <summary>
 ///     Returns the contents of the specified byte array to the client.</summary>
 /// <param name="content">
 ///     Content to return to the client.</param>
 /// <param name="status">
 ///     HTTP status code to use in the response.</param>
 /// <param name="headers">
 ///     Headers to use in the response, or null to use default values.</param>
 public static HttpResponseContent Css(byte[] content, HttpStatusCode status = HttpStatusCode._200_OK, HttpResponseHeaders headers = null)
 {
     return(create(() => new MemoryStream(content), "text/css; charset=utf-8", status, headers));
 }
Beispiel #2
0
 /// <summary>
 ///     Returns the specified content to the client with the MIME type “text/plain; charset=utf-8”.</summary>
 /// <param name="content">
 ///     Content to return to the client.</param>
 /// <param name="status">
 ///     HTTP status code to use in the response.</param>
 /// <param name="headers">
 ///     Headers to use in the response, or null to use default values.</param>
 public static HttpResponseContent PlainText(string content, HttpStatusCode status = HttpStatusCode._200_OK, HttpResponseHeaders headers = null)
 {
     return(Create(content, "text/plain; charset=utf-8", status, headers));
 }
Beispiel #3
0
 /// <summary>
 ///     Returns the specified content to the client with the MIME type “application/json; charset=utf-8”.</summary>
 /// <param name="content">
 ///     Content to return to the client.</param>
 /// <param name="status">
 ///     HTTP status code to use in the response.</param>
 /// <param name="headers">
 ///     Headers to use in the response, or null to use default values.</param>
 public static HttpResponseContent Json(JsonValue content, HttpStatusCode status = HttpStatusCode._200_OK, HttpResponseHeaders headers = null)
 {
     return(Create(JsonValue.ToEnumerable(content), "application/json; charset=utf-8", status, headers));
 }
Beispiel #4
0
 /// <summary>
 ///     Returns an <see cref="HttpResponseWebSocket"/> which indicates to the client that the HTTP connection should
 ///     switch to the WebSocket protocol.</summary>
 /// <param name="websocket">
 ///     The <see cref="WebSocket"/> implementation to use for the remainder of the connection.</param>
 /// <param name="subprotocol">
 ///     The server’s selection of a subprotocol, if the client specified any subprotocols in the request.</param>
 /// <param name="headers">
 ///     Optional HTTP response headers.</param>
 public static HttpResponseWebSocket WebSocket(WebSocket websocket, string subprotocol = null, HttpResponseHeaders headers = null)
 {
     if (websocket == null)
         throw new ArgumentNullException("websocket");
     return new HttpResponseWebSocket(websocket, subprotocol, headers);
 }
Beispiel #5
0
 /// <summary>
 ///     Returns the specified tag content to the client.</summary>
 /// <param name="content">
 ///     Content to return to the client.</param>
 /// <param name="status">
 ///     HTTP status code to use in the response.</param>
 /// <param name="headers">
 ///     Headers to use in the response, or null to use default values.</param>
 /// <param name="buffered">
 ///     If true (default), the output is buffered for performance; otherwise, all text is transmitted as soon as
 ///     possible.</param>
 public static HttpResponseContent Html(Tag content, HttpStatusCode status = HttpStatusCode._200_OK, HttpResponseHeaders headers = null, bool buffered = true)
 {
     return(create(() => new DynamicContentStream(content.ToEnumerable(), buffered), "text/html; charset=utf-8", status, headers));
 }
Beispiel #6
0
        private static HttpResponseContent create(Func <Stream> getContentStream, string contentType, HttpStatusCode status, HttpResponseHeaders headers)
        {
            if (!status.MayHaveBody() && getContentStream != null)
            {
                throw new InvalidOperationException("A response with the {0} status cannot have a body.".Fmt(status));
            }
            if (!status.MayHaveBody() && (contentType != null || (headers != null && headers.ContentType != null)))
            {
                throw new InvalidOperationException("A response with the {0} status cannot have a Content-Type header.".Fmt(status));
            }

            headers             = headers ?? new HttpResponseHeaders();
            headers.ContentType = contentType ?? headers.ContentType;
            return(new HttpResponseContent(status, headers, getContentStream));
        }
Beispiel #7
0
 /// <summary>
 ///     Returns the contents of the specified stream to the client with the specified MIME type.</summary>
 /// <param name="content">
 ///     Content to return to the client.</param>
 /// <param name="contentType">
 ///     MIME type to use. This overrides any MIME type specified in <paramref name="headers"/> (if any).</param>
 /// <param name="status">
 ///     HTTP status code to use in the response.</param>
 /// <param name="headers">
 ///     Headers to use in the response, or null to use default values.</param>
 public static HttpResponseContent Create(Stream content, string contentType, HttpStatusCode status = HttpStatusCode._200_OK, HttpResponseHeaders headers = null)
 {
     var used = false;
     return create(content == null ? null : new Func<Stream>(() =>
     {
         if (used)
             throw new InvalidOperationException("You cannot re-use an HttpResponse instance constructed from a Stream for multiple separate HTTP requests. Instead, construct a new Stream and HttpResponse from within the request handler.");
         used = true;
         return content;
     }), contentType, status, headers);
 }
Beispiel #8
0
            private bool outputResponse(HttpResponse response, HttpStatusCode status, HttpResponseHeaders headers, Stream contentStream, UseGzipOption useGzipOption, HttpRequest originalRequest)
            {
                // IMPORTANT: Do not access properties of ‘response’. Use the other parameters instead, which contain copies.
                // The request handler can re-use HttpResponse objects between requests. Thus the properties of ‘response’ would
                // be accessed simultaneously from multiple instances of this method running in separate threads.
                // Additionally, HttpResponse is a MarshalByRefObject but HttpResponseHeaders is not, so ‘response’
                // may be a transparent proxy, in which case ‘response.Headers’ would retrieve a serialized copy.
                // ‘response’ is ONLY used to pass it to _server.ResponseExceptionHandler().

                Socket.NoDelay = false;

                try
                {
                    bool gzipRequested = false;
                    if (originalRequest.Headers.AcceptEncoding != null)
                        foreach (HttpContentEncoding hce in originalRequest.Headers.AcceptEncoding)
                            gzipRequested = gzipRequested || (hce == HttpContentEncoding.Gzip);
                    bool contentLengthKnown = false;
                    long contentLength = 0;

                    // Find out if we know the content length
                    if (contentStream == null)
                    {
                        contentLength = 0;
                        contentLengthKnown = true;
                    }
                    else if (headers.ContentLength != null)
                    {
                        contentLength = headers.ContentLength.Value;
                        contentLengthKnown = true;
                    }
                    else
                    {
                        // See if we can deduce the content length from the stream
                        try
                        {
                            if (contentStream.CanSeek)
                            {
                                contentLength = contentStream.Length;
                                contentLengthKnown = true;
                            }
                        }
                        catch (NotSupportedException) { }
                    }

                    bool useKeepAlive =
                        originalRequest.HttpVersion == HttpProtocolVersion.Http11 &&
                        originalRequest.Headers.Connection.HasFlag(HttpConnection.KeepAlive) &&
                        !headers.Connection.HasFlag(HttpConnection.Close);
                    headers.Connection = useKeepAlive ? HttpConnection.KeepAlive : HttpConnection.Close;
                    headers.ContentLength = null;

                    // Special cases: status codes that may not have a body
                    if (!status.MayHaveBody())
                    {
                        if (contentStream != null)
                            throw new InvalidOperationException("A response with the {0} status cannot have a body (GetContentStream must be null or return null).".Fmt(status));
                        if (headers.ContentType != null)
                            throw new InvalidOperationException("A response with the {0} status cannot have a Content-Type header.".Fmt(status));
                        sendHeaders(status, headers);
                        return useKeepAlive;
                    }

                    // Special case: empty body
                    if (contentLengthKnown && contentLength == 0)
                    {
                        headers.ContentLength = 0;
                        sendHeaders(status, headers);
                        return useKeepAlive;
                    }

                    // If no Content-Type is given, use default
                    headers.ContentType = headers.ContentType ?? _server.Options.DefaultContentType;

                    // If we know the content length and the stream can seek, then we can support Ranges - but it's not worth it for less than 16 KB
                    if (originalRequest.HttpVersion == HttpProtocolVersion.Http11 && contentLengthKnown && contentLength > 16 * 1024 && status == HttpStatusCode._200_OK && contentStream.CanSeek)
                    {
                        headers.AcceptRanges = HttpAcceptRanges.Bytes;

                        // If the client requested a range, then serve it
                        if (status == HttpStatusCode._200_OK && originalRequest.Headers.Range != null)
                        {
                            // Construct a canonical set of satisfiable ranges
                            var ranges = new SortedList<long, long>();
                            foreach (var r in originalRequest.Headers.Range)
                            {
                                long rFrom = r.From == null || r.From.Value < 0 ? 0 : r.From.Value;
                                long rTo = r.To == null || r.To.Value >= contentLength ? contentLength - 1 : r.To.Value;
                                if (ranges.ContainsKey(rFrom))
                                    ranges[rFrom] = Math.Max(ranges[rFrom], rTo);
                                else
                                    ranges.Add(rFrom, rTo);
                            }

                            // If one of the ranges spans the complete file, don't bother with ranges
                            if (!ranges.ContainsKey(0) || ranges[0] < contentLength - 1)
                            {
                                // Make a copy of this so that we can modify Ranges while iterating over it
                                var rangeFroms = new List<long>(ranges.Keys);

                                long prevFrom = 0;
                                bool havePrevFrom = false;
                                foreach (long from in rangeFroms)
                                {
                                    if (!havePrevFrom)
                                    {
                                        prevFrom = from;
                                        havePrevFrom = true;
                                    }
                                    else if (ranges[prevFrom] >= from)
                                    {
                                        ranges[prevFrom] = Math.Max(ranges[prevFrom], ranges[from]);
                                        ranges.Remove(from);
                                    }
                                }

                                // Note that "ContentLength" here refers to the total size of the file.
                                // The functions ServeSingleRange() and ServeRanges() will automatically
                                // set a Content-Length header that specifies the size of just the range(s).

                                // Also note that if Ranges.Count is 0, we want to fall through and handle the request without ranges
                                if (ranges.Count == 1)
                                {
                                    var range = ranges.First();
                                    serveSingleRange(headers, contentStream, originalRequest, range.Key, range.Value, contentLength);
                                    return useKeepAlive;
                                }
                                else if (ranges.Count > 1)
                                {
                                    serveRanges(headers, contentStream, originalRequest, ranges, contentLength);
                                    return useKeepAlive;
                                }
                            }
                        }
                    }

                    bool useGzip = useGzipOption != UseGzipOption.DontUseGzip && gzipRequested && !(contentLengthKnown && contentLength <= 1024) && originalRequest.HttpVersion == HttpProtocolVersion.Http11;

                    if (useGzip && useGzipOption == UseGzipOption.AutoDetect && contentLengthKnown && contentLength >= _server.Options.GzipAutodetectThreshold && contentStream.CanSeek)
                    {
                        try
                        {
                            contentStream.Seek((contentLength - _server.Options.GzipAutodetectThreshold) / 2, SeekOrigin.Begin);
                            byte[] buf = new byte[_server.Options.GzipAutodetectThreshold];
                            contentStream.Read(buf, 0, _server.Options.GzipAutodetectThreshold);
                            using (var ms = new MemoryStream())
                            {
                                using (var gzTester = new GZipOutputStream(ms))
                                {
                                    gzTester.SetLevel(1);
                                    gzTester.Write(buf, 0, _server.Options.GzipAutodetectThreshold);
                                }
                                if (ms.ToArray().Length >= 0.99 * _server.Options.GzipAutodetectThreshold)
                                    useGzip = false;
                            }
                            contentStream.Seek(0, SeekOrigin.Begin);
                        }
                        catch { }
                    }

                    headers.ContentEncoding = useGzip ? HttpContentEncoding.Gzip : HttpContentEncoding.Identity;

                    // If we know the content length and it is smaller than the in-memory gzip threshold, gzip and output everything now
                    if (useGzip && contentLengthKnown && contentLength < _server.Options.GzipInMemoryUpToSize)
                    {
                        // In this case, do all the gzipping before sending the headers.
                        // After all we want to include the new (compressed) Content-Length.
                        MemoryStream ms = new MemoryStream();
                        GZipOutputStream gz = new GZipOutputStream(ms);
                        gz.SetLevel(1);
                        byte[] contentReadBuffer = new byte[65536];
                        int bytes = contentStream.Read(contentReadBuffer, 0, 65536);
                        while (bytes > 0)
                        {
                            gz.Write(contentReadBuffer, 0, bytes);
                            bytes = contentStream.Read(contentReadBuffer, 0, 65536);
                        }
                        gz.Close();
                        byte[] resultBuffer = ms.ToArray();
                        headers.ContentLength = resultBuffer.Length;
                        sendHeaders(status, headers);
                        if (originalRequest.Method == HttpMethod.Head)
                            return useKeepAlive;
                        _stream.Write(resultBuffer);
                        return useKeepAlive;
                    }

                    Stream output;

                    if (useGzip && !useKeepAlive)
                    {
                        // In this case, send the headers first, then instantiate the GZipStream.
                        // Otherwise we run the risk that the GzipStream might write to the socket before the headers are sent.
                        // Also note that we are not sending a Content-Length header; even if we know the content length
                        // of the uncompressed file, we cannot predict the length of the compressed output yet
                        sendHeaders(status, headers);
                        if (originalRequest.Method == HttpMethod.Head)
                            return useKeepAlive;
                        var str = new GZipOutputStream(new DoNotCloseStream(_stream));
                        str.SetLevel(1);
                        output = str;
                    }
                    else if (useGzip)
                    {
                        // In this case, combine Gzip with chunked Transfer-Encoding. No Content-Length header
                        headers.TransferEncoding = HttpTransferEncoding.Chunked;
                        sendHeaders(status, headers);
                        if (originalRequest.Method == HttpMethod.Head)
                            return useKeepAlive;
                        var str = new GZipOutputStream(new ChunkedEncodingStream(_stream, leaveInnerOpen: true));
                        str.SetLevel(1);
                        output = str;
                    }
                    else if (useKeepAlive && !contentLengthKnown)
                    {
                        // Use chunked encoding without Gzip
                        headers.TransferEncoding = HttpTransferEncoding.Chunked;
                        sendHeaders(status, headers);
                        if (originalRequest.Method == HttpMethod.Head)
                            return useKeepAlive;
                        output = new ChunkedEncodingStream(_stream, leaveInnerOpen: true);
                    }
                    else
                    {
                        // No Gzip, no chunked, but if we know the content length, supply it
                        // (if we don't, then we're not using keep-alive here)
                        if (contentLengthKnown)
                            headers.ContentLength = contentLength;

                        sendHeaders(status, headers);

                        if (originalRequest.Method == HttpMethod.Head)
                            return useKeepAlive;

                        // We need DoNotCloseStream here because the later code needs to be able to
                        // close ‘output’ in case it’s a Gzip and/or Chunked stream; however, we don’t
                        // want to close the socket because it might be a keep-alive connection.
                        output = new DoNotCloseStream(_stream);
                    }

                    // Finally output the actual content
                    byte[] buffer = new byte[65536];
                    int bufferSize = buffer.Length;
                    int bytesRead;
                    while (true)
                    {
                        // There are no “valid” exceptions that may originate from the content stream, so the “Error500” setting
                        // actually propagates everything.
                        if (_server.PropagateExceptions)
                            bytesRead = contentStream.Read(buffer, 0, bufferSize);
                        else
                            try { bytesRead = contentStream.Read(buffer, 0, bufferSize); }
                            catch (Exception e)
                            {
                                if (!(e is SocketException) && _server.Options.OutputExceptionInformation)
                                    output.Write((headers.ContentType.StartsWith("text/html") ? exceptionToHtml(e) : exceptionToPlaintext(e)).ToUtf8());
                                var handler = _server.ResponseExceptionHandler;
                                if (handler != null)
                                    handler(originalRequest, e, response);
                                output.Close();
                                return false;
                            }

                        if (bytesRead == 0)
                            break;

                        // Performance optimisation: If we’re at the end of a body of known length, cause
                        // the last bit to be sent to the socket without the Nagle delay
                        try
                        {
                            if (contentStream.CanSeek && contentStream.Position == contentStream.Length)
                                Socket.NoDelay = true;
                        }
                        catch { }

                        output.Write(buffer, 0, bytesRead);
                    }

                    // Important: If we are using Gzip and/or Chunked encoding, this causes the relevant
                    // streams to output the last bytes.
                    output.Close();

                    // Now re-enable the Nagle algorithm in case this is a keep-alive connection.
                    Socket.NoDelay = false;

                    return useKeepAlive;
                }
                finally
                {
                    try
                    {
                        if (originalRequest.FileUploads != null)
                            foreach (var fileUpload in originalRequest.FileUploads.Values.Where(fu => fu.LocalFilename != null && !fu.LocalFileMoved))
                                File.Delete(fileUpload.LocalFilename);
                    }
                    catch (Exception) { }
                }
            }
Beispiel #9
0
 /// <summary>
 ///     Returns a response to the client consisting of an empty body.</summary>
 /// <param name="status">
 ///     HTTP status code to use in the response.</param>
 /// <param name="headers">
 ///     Headers to use in the response, or null to use default values.</param>
 public static HttpResponseContent Empty(HttpStatusCode status = HttpStatusCode._200_OK, HttpResponseHeaders headers = null)
 {
     return new HttpResponseContent(status, headers ?? new HttpResponseHeaders());
 }
Beispiel #10
0
            private void serveSingleRange(HttpResponseHeaders headers, Stream contentStream, HttpRequest originalRequest, long rangeFrom, long rangeTo, long totalFileSize)
            {
                // Note: this is the length of just the range, not the complete file (that's totalFileSize)
                headers.ContentLength = rangeTo - rangeFrom + 1;
                headers.ContentRange = new HttpContentRange { From = rangeFrom, To = rangeTo, Total = totalFileSize };
                sendHeaders(HttpStatusCode._206_PartialContent, headers);
                if (originalRequest.Method == HttpMethod.Head)
                    return;
                byte[] buffer = new byte[65536];

                contentStream.Seek(rangeFrom, SeekOrigin.Begin);
                long bytesMissing = rangeTo - rangeFrom + 1;
                int bytesRead = contentStream.Read(buffer, 0, (int) Math.Min(65536, bytesMissing));
                while (bytesRead > 0)
                {
                    _stream.Write(buffer, 0, bytesRead);
                    bytesMissing -= bytesRead;
                    bytesRead = (bytesMissing > 0) ? contentStream.Read(buffer, 0, (int) Math.Min(65536, bytesMissing)) : 0;
                }
            }
Beispiel #11
0
            private void serveRanges(HttpResponseHeaders headers, Stream contentStream, HttpRequest originalRequest, SortedList<long, long> ranges, long totalFileSize)
            {
                // Generate a random boundary token
                byte[] boundary = new byte[64];

                for (int i = 0; i < 64; i++)
                {
                    int r = Rnd.Next(16);
                    boundary[i] = r < 10 ? ((byte) (r + '0')) : ((byte) (r + 'A' - 10));
                }

                // Calculate the total content length
                long cLength = 0;
                foreach (var r in ranges)
                {
                    cLength += 68;                  // "--{boundary}\r\n"
                    cLength += 27 +                 // "Content-range: bytes {f}-{l}/{filesize}\r\n\r\n"
                        r.Key.ToString().Length + r.Value.ToString().Length + totalFileSize.ToString().Length;
                    cLength += r.Key - r.Value + 1; // content
                    cLength += 2;                   // "\r\n"
                }
                cLength += 70;                      // "--{boundary}--\r\n"

                headers.ContentLength = cLength;
                headers.ContentType = "multipart/byteranges; boundary=" + Encoding.UTF8.GetString(boundary);
                sendHeaders(HttpStatusCode._206_PartialContent, headers);
                if (originalRequest.Method == HttpMethod.Head)
                    return;

                byte[] buffer = new byte[65536];
                foreach (var r in ranges)
                {
                    _stream.Write(new byte[] { (byte) '-', (byte) '-' });
                    _stream.Write(boundary);
                    _stream.Write(("\r\nContent-Range: bytes " + r.Key.ToString() + "-" + r.Value.ToString() + "/" + totalFileSize.ToString() + "\r\n\r\n").ToUtf8());

                    contentStream.Seek(r.Key, SeekOrigin.Begin);
                    long bytesMissing = r.Value - r.Key + 1;
                    int bytesRead = contentStream.Read(buffer, 0, (int) Math.Min(65536, bytesMissing));
                    while (bytesRead > 0)
                    {
                        _stream.Write(buffer, 0, bytesRead);
                        bytesMissing -= bytesRead;
                        bytesRead = (bytesMissing > 0) ? contentStream.Read(buffer, 0, (int) Math.Min(65536, bytesMissing)) : 0;
                    }
                    _stream.Write(new byte[] { 13, 10 });
                }
                _stream.Write(new byte[] { (byte) '-', (byte) '-' });
                _stream.Write(boundary);
                _stream.Write(new byte[] { (byte) '-', (byte) '-', 13, 10 });
            }
Beispiel #12
0
 private void sendHeaders(HttpStatusCode status, HttpResponseHeaders headers)
 {
     string headersStr = "HTTP/1.1 " + ((int) status) + " " + status.ToText() + "\r\n" +
         headers.ToString() + "\r\n";
     _stream.Write(Encoding.UTF8.GetBytes(headersStr));
 }
 /// <summary>
 ///     Initializes an HTTP response.</summary>
 /// <param name="status">
 ///     The HTTP status code to return.</param>
 /// <param name="headers">
 ///     HTTP response headers to include in the response.</param>
 /// <param name="contentStreamDelegate">
 ///     A delegate that generates or returns a Stream, which in turn provides the content to return as part of this
 ///     response. Can be <c>null</c> for empty responses.</param>
 public HttpResponseContent(HttpStatusCode status, HttpResponseHeaders headers, Func<Stream> contentStreamDelegate = null)
     : base(headers)
 {
     _status = status;
     _contentStreamDelegate = contentStreamDelegate;
 }
 /// <summary>
 ///     Initializes an HTTP response.</summary>
 /// <param name="status">
 ///     The HTTP status code to return.</param>
 /// <param name="headers">
 ///     HTTP response headers to include in the response.</param>
 /// <param name="contentStreamDelegate">
 ///     A delegate that generates or returns a Stream, which in turn provides the content to return as part of this
 ///     response. Can be <c>null</c> for empty responses.</param>
 public HttpResponseContent(HttpStatusCode status, HttpResponseHeaders headers, Func <Stream> contentStreamDelegate = null)
     : base(headers)
 {
     _status = status;
     _contentStreamDelegate = contentStreamDelegate;
 }
Beispiel #15
0
        /// <summary>
        ///     Returns the specified content to the client with the specified MIME type.</summary>
        /// <param name="content">
        ///     Content to return to the client.</param>
        /// <param name="contentType">
        ///     MIME type to use. This overrides any MIME type specified in <paramref name="headers"/> (if any).</param>
        /// <param name="status">
        ///     HTTP status code to use in the response.</param>
        /// <param name="headers">
        ///     Headers to use in the response, or null to use default values.</param>
        public static HttpResponseContent Create(string content, string contentType, HttpStatusCode status = HttpStatusCode._200_OK, HttpResponseHeaders headers = null)
        {
            var utf8 = content.ToUtf8();

            return(create(() => new MemoryStream(utf8), contentType, status, headers));
        }
Beispiel #16
0
 /// <summary>
 ///     Returns the specified tag content to the client.</summary>
 /// <param name="content">
 ///     Content to return to the client.</param>
 /// <param name="status">
 ///     HTTP status code to use in the response.</param>
 /// <param name="headers">
 ///     Headers to use in the response, or null to use default values.</param>
 /// <param name="buffered">
 ///     If true (default), the output is buffered for performance; otherwise, all text is transmitted as soon as
 ///     possible.</param>
 public static HttpResponseContent Html(Tag content, HttpStatusCode status = HttpStatusCode._200_OK, HttpResponseHeaders headers = null, bool buffered = true)
 {
     return create(() => new DynamicContentStream(content.ToEnumerable(), buffered), "text/html; charset=utf-8", status, headers);
 }
Beispiel #17
0
 /// <summary>
 ///     Returns the contents of the specified byte array to the client with the specified MIME type.</summary>
 /// <param name="content">
 ///     Content to return to the client.</param>
 /// <param name="contentType">
 ///     MIME type to use. This overrides any MIME type specified in <paramref name="headers"/> (if any).</param>
 /// <param name="status">
 ///     HTTP status code to use in the response.</param>
 /// <param name="headers">
 ///     Headers to use in the response, or null to use default values.</param>
 public static HttpResponseContent Create(byte[] content, string contentType, HttpStatusCode status = HttpStatusCode._200_OK, HttpResponseHeaders headers = null)
 {
     return(create(() => new MemoryStream(content), contentType, status, headers));
 }
Beispiel #18
0
 /// <summary>Constructor.</summary>
 protected HttpResponse(HttpResponseHeaders headers) { _headers = headers; }
 /// <summary>
 ///     Constructor.</summary>
 /// <param name="websocket">
 ///     The <see cref="WebSocket"/> implementation to use for the remainder of the connection.</param>
 /// <param name="subprotocol">
 ///     The server’s selection of a subprotocol, if the client specified any subprotocols in the request.</param>
 /// <param name="headers">
 ///     Optional HTTP response headers.</param>
 public HttpResponseWebSocket(WebSocket websocket, string subprotocol = null, HttpResponseHeaders headers = null)
     : base(headers ?? new HttpResponseHeaders())
 {
     Subprotocol = subprotocol;
     Websocket   = websocket;
 }
Beispiel #20
0
 /// <summary>
 ///     Returns the specified content to the client with the MIME type “text/plain; charset=utf-8”.</summary>
 /// <param name="content">
 ///     Content to return to the client.</param>
 /// <param name="status">
 ///     HTTP status code to use in the response.</param>
 /// <param name="headers">
 ///     Headers to use in the response, or null to use default values.</param>
 public static HttpResponseContent PlainText(string content, HttpStatusCode status = HttpStatusCode._200_OK, HttpResponseHeaders headers = null)
 {
     return Create(content, "text/plain; charset=utf-8", status, headers);
 }
Beispiel #21
0
        private static HttpResponseContent create(Func<Stream> getContentStream, string contentType, HttpStatusCode status, HttpResponseHeaders headers)
        {
            if (!status.MayHaveBody() && getContentStream != null)
                throw new InvalidOperationException("A response with the {0} status cannot have a body.".Fmt(status));
            if (!status.MayHaveBody() && (contentType != null || (headers != null && headers.ContentType != null)))
                throw new InvalidOperationException("A response with the {0} status cannot have a Content-Type header.".Fmt(status));

            headers = headers ?? new HttpResponseHeaders();
            headers.ContentType = contentType ?? headers.ContentType;
            return new HttpResponseContent(status, headers, getContentStream);
        }
Beispiel #22
0
 /// <summary>
 ///     Returns the specified content to the client with the MIME type “text/javascript; charset=utf-8”.</summary>
 /// <param name="content">
 ///     Content to return to the client.</param>
 /// <param name="status">
 ///     HTTP status code to use in the response.</param>
 /// <param name="headers">
 ///     Headers to use in the response, or null to use default values.</param>
 public static HttpResponseContent JavaScript(string content, HttpStatusCode status = HttpStatusCode._200_OK, HttpResponseHeaders headers = null)
 {
     return Create(content, "text/javascript; charset=utf-8", status, headers);
 }
Beispiel #23
0
 /// <summary>
 ///     Returns a response to the client consisting of an empty body.</summary>
 /// <param name="status">
 ///     HTTP status code to use in the response.</param>
 /// <param name="headers">
 ///     Headers to use in the response, or null to use default values.</param>
 public static HttpResponseContent Empty(HttpStatusCode status = HttpStatusCode._200_OK, HttpResponseHeaders headers = null)
 {
     return(new HttpResponseContent(status, headers ?? new HttpResponseHeaders()));
 }
Beispiel #24
0
 /// <summary>
 ///     Returns the specified content to the client with the MIME type “application/json; charset=utf-8”.</summary>
 /// <param name="content">
 ///     Content to return to the client.</param>
 /// <param name="status">
 ///     HTTP status code to use in the response.</param>
 /// <param name="headers">
 ///     Headers to use in the response, or null to use default values.</param>
 public static HttpResponseContent Json(JsonValue content, HttpStatusCode status = HttpStatusCode._200_OK, HttpResponseHeaders headers = null)
 {
     return Create(JsonValue.ToEnumerable(content), "application/json; charset=utf-8", status, headers);
 }
Beispiel #25
0
 /// <summary>Constructor.</summary>
 protected HttpResponse(HttpResponseHeaders headers)
 {
     _headers = headers;
 }
Beispiel #26
0
 /// <summary>
 ///     Returns the specified content to the client as a single concatenated piece of text with the MIME type
 ///     “text/css; charset=utf-8”.</summary>
 /// <param name="content">
 ///     Content to return to the client.</param>
 /// <param name="status">
 ///     HTTP status code to use in the response.</param>
 /// <param name="headers">
 ///     Headers to use in the response, or null to use default values.</param>
 /// <param name="buffered">
 ///     If true (default), the output is buffered for performance; otherwise, all text is transmitted as soon as
 ///     possible.</param>
 public static HttpResponseContent Css(IEnumerable<string> content, HttpStatusCode status = HttpStatusCode._200_OK, HttpResponseHeaders headers = null, bool buffered = true)
 {
     return create(() => new DynamicContentStream(content, buffered), "text/css; charset=utf-8", status, headers);
 }
Beispiel #27
0
 /// <summary>
 ///     Returns the specified content to the client with the MIME type “text/javascript; charset=utf-8”.</summary>
 /// <param name="content">
 ///     Content to return to the client.</param>
 /// <param name="status">
 ///     HTTP status code to use in the response.</param>
 /// <param name="headers">
 ///     Headers to use in the response, or null to use default values.</param>
 public static HttpResponseContent JavaScript(string content, HttpStatusCode status = HttpStatusCode._200_OK, HttpResponseHeaders headers = null)
 {
     return(Create(content, "text/javascript; charset=utf-8", status, headers));
 }
Beispiel #28
0
 /// <summary>
 ///     Returns the contents of the specified byte array to the client.</summary>
 /// <param name="content">
 ///     Content to return to the client.</param>
 /// <param name="status">
 ///     HTTP status code to use in the response.</param>
 /// <param name="headers">
 ///     Headers to use in the response, or null to use default values.</param>
 public static HttpResponseContent Css(byte[] content, HttpStatusCode status = HttpStatusCode._200_OK, HttpResponseHeaders headers = null)
 {
     return create(() => new MemoryStream(content), "text/css; charset=utf-8", status, headers);
 }
Beispiel #29
0
 /// <summary>
 ///     Returns the specified content to the client as a single concatenated piece of text with the MIME type
 ///     “text/css; charset=utf-8”.</summary>
 /// <param name="content">
 ///     Content to return to the client.</param>
 /// <param name="status">
 ///     HTTP status code to use in the response.</param>
 /// <param name="headers">
 ///     Headers to use in the response, or null to use default values.</param>
 /// <param name="buffered">
 ///     If true (default), the output is buffered for performance; otherwise, all text is transmitted as soon as
 ///     possible.</param>
 public static HttpResponseContent Css(IEnumerable <string> content, HttpStatusCode status = HttpStatusCode._200_OK, HttpResponseHeaders headers = null, bool buffered = true)
 {
     return(create(() => new DynamicContentStream(content, buffered), "text/css; charset=utf-8", status, headers));
 }
Beispiel #30
0
 /// <summary>
 ///     Returns the contents of the specified stream to the client.</summary>
 /// <param name="content">
 ///     Content to return to the client.</param>
 /// <param name="status">
 ///     HTTP status code to use in the response.</param>
 /// <param name="headers">
 ///     Headers to use in the response, or null to use default values.</param>
 public static HttpResponseContent Css(Stream content, HttpStatusCode status = HttpStatusCode._200_OK, HttpResponseHeaders headers = null)
 {
     return Create(content, "text/css; charset=utf-8", status, headers);
 }
Beispiel #31
0
 /// <summary>
 ///     Returns the contents of the specified stream to the client.</summary>
 /// <param name="content">
 ///     Content to return to the client.</param>
 /// <param name="status">
 ///     HTTP status code to use in the response.</param>
 /// <param name="headers">
 ///     Headers to use in the response, or null to use default values.</param>
 public static HttpResponseContent Css(Stream content, HttpStatusCode status = HttpStatusCode._200_OK, HttpResponseHeaders headers = null)
 {
     return(Create(content, "text/css; charset=utf-8", status, headers));
 }
Beispiel #32
0
 /// <summary>
 ///     Returns the specified content to the client with the specified MIME type.</summary>
 /// <param name="content">
 ///     Content to return to the client.</param>
 /// <param name="contentType">
 ///     MIME type to use. This overrides any MIME type specified in <paramref name="headers"/> (if any).</param>
 /// <param name="status">
 ///     HTTP status code to use in the response.</param>
 /// <param name="headers">
 ///     Headers to use in the response, or null to use default values.</param>
 public static HttpResponseContent Create(string content, string contentType, HttpStatusCode status = HttpStatusCode._200_OK, HttpResponseHeaders headers = null)
 {
     var utf8 = content.ToUtf8();
     return create(() => new MemoryStream(utf8), contentType, status, headers);
 }
Beispiel #33
0
 /// <summary>
 ///     Returns the specified content to the client as a single concatenated piece of text with the specified MIME
 ///     type.</summary>
 /// <param name="content">
 ///     Content to return to the client.</param>
 /// <param name="contentType">
 ///     MIME type to use. This overrides any MIME type specified in <paramref name="headers"/> (if any).</param>
 /// <param name="status">
 ///     HTTP status code to use in the response.</param>
 /// <param name="headers">
 ///     Headers to use in the response, or null to use default values.</param>
 /// <param name="buffered">
 ///     If true (default), the output is buffered for performance; otherwise, all text is transmitted as soon as
 ///     possible.</param>
 public static HttpResponseContent Create(IEnumerable <string> content, string contentType, HttpStatusCode status = HttpStatusCode._200_OK, HttpResponseHeaders headers = null, bool buffered = true)
 {
     return(create(() => new DynamicContentStream(content, buffered), contentType, status, headers));
 }
Beispiel #34
0
 /// <summary>
 ///     Returns the specified content to the client as a single concatenated piece of text with the specified MIME
 ///     type.</summary>
 /// <param name="content">
 ///     Content to return to the client.</param>
 /// <param name="contentType">
 ///     MIME type to use. This overrides any MIME type specified in <paramref name="headers"/> (if any).</param>
 /// <param name="status">
 ///     HTTP status code to use in the response.</param>
 /// <param name="headers">
 ///     Headers to use in the response, or null to use default values.</param>
 /// <param name="buffered">
 ///     If true (default), the output is buffered for performance; otherwise, all text is transmitted as soon as
 ///     possible.</param>
 public static HttpResponseContent Create(IEnumerable<string> content, string contentType, HttpStatusCode status = HttpStatusCode._200_OK, HttpResponseHeaders headers = null, bool buffered = true)
 {
     return create(() => new DynamicContentStream(content, buffered), contentType, status, headers);
 }
Beispiel #35
0
        /// <summary>
        ///     Returns the contents of the specified stream to the client with the specified MIME type.</summary>
        /// <param name="content">
        ///     Content to return to the client.</param>
        /// <param name="contentType">
        ///     MIME type to use. This overrides any MIME type specified in <paramref name="headers"/> (if any).</param>
        /// <param name="status">
        ///     HTTP status code to use in the response.</param>
        /// <param name="headers">
        ///     Headers to use in the response, or null to use default values.</param>
        public static HttpResponseContent Create(Stream content, string contentType, HttpStatusCode status = HttpStatusCode._200_OK, HttpResponseHeaders headers = null)
        {
            var used = false;

            return(create(content == null ? null : new Func <Stream>(() =>
            {
                if (used)
                {
                    throw new InvalidOperationException("You cannot re-use an HttpResponse instance constructed from a Stream for multiple separate HTTP requests. Instead, construct a new Stream and HttpResponse from within the request handler.");
                }
                used = true;
                return content;
            }), contentType, status, headers));
        }
Beispiel #36
0
 /// <summary>
 ///     Returns the contents of the specified byte array to the client with the specified MIME type.</summary>
 /// <param name="content">
 ///     Content to return to the client.</param>
 /// <param name="contentType">
 ///     MIME type to use. This overrides any MIME type specified in <paramref name="headers"/> (if any).</param>
 /// <param name="status">
 ///     HTTP status code to use in the response.</param>
 /// <param name="headers">
 ///     Headers to use in the response, or null to use default values.</param>
 public static HttpResponseContent Create(byte[] content, string contentType, HttpStatusCode status = HttpStatusCode._200_OK, HttpResponseHeaders headers = null)
 {
     return create(() => new MemoryStream(content), contentType, status, headers);
 }
Beispiel #37
0
 /// <summary>
 ///     Returns an <see cref="HttpResponseWebSocket"/> which indicates to the client that the HTTP connection should
 ///     switch to the WebSocket protocol.</summary>
 /// <param name="websocket">
 ///     The <see cref="WebSocket"/> implementation to use for the remainder of the connection.</param>
 /// <param name="subprotocol">
 ///     The server’s selection of a subprotocol, if the client specified any subprotocols in the request.</param>
 /// <param name="headers">
 ///     Optional HTTP response headers.</param>
 public static HttpResponseWebSocket WebSocket(WebSocket websocket, string subprotocol = null, HttpResponseHeaders headers = null)
 {
     if (websocket == null)
     {
         throw new ArgumentNullException("websocket");
     }
     return(new HttpResponseWebSocket(websocket, subprotocol, headers));
 }
 /// <summary>
 ///     Constructor.</summary>
 /// <param name="websocket">
 ///     The <see cref="WebSocket"/> implementation to use for the remainder of the connection.</param>
 /// <param name="subprotocol">
 ///     The server’s selection of a subprotocol, if the client specified any subprotocols in the request.</param>
 /// <param name="headers">
 ///     Optional HTTP response headers.</param>
 public HttpResponseWebSocket(WebSocket websocket, string subprotocol = null, HttpResponseHeaders headers = null)
     : base(headers ?? new HttpResponseHeaders())
 {
     Subprotocol = subprotocol;
     Websocket = websocket;
 }