/// <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)); }
/// <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)); }
/// <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)); }
/// <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> /// 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)); }
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)); }
/// <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); }
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) { } } }
/// <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()); }
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; } }
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 }); }
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; }
/// <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)); }
/// <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); }
/// <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)); }
/// <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; }
/// <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); }
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); }
/// <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); }
/// <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())); }
/// <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); }
/// <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); }
/// <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)); }
/// <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); }
/// <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)); }
/// <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); }
/// <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)); }
/// <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); }
/// <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)); }
/// <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); }
/// <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)); }
/// <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); }
/// <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)); }