From c035f2baa1f3537d298a6559d15bd7ca40188e5d Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 12 Nov 2016 01:58:50 -0500 Subject: update responses --- ServiceStack/Host/ContentTypes.cs | 20 ++---- ServiceStack/Host/HttpResponseStreamWrapper.cs | 95 -------------------------- ServiceStack/Host/ServiceController.cs | 3 - 3 files changed, 7 insertions(+), 111 deletions(-) delete mode 100644 ServiceStack/Host/HttpResponseStreamWrapper.cs (limited to 'ServiceStack/Host') diff --git a/ServiceStack/Host/ContentTypes.cs b/ServiceStack/Host/ContentTypes.cs index 22fdc3e50..58ba29801 100644 --- a/ServiceStack/Host/ContentTypes.cs +++ b/ServiceStack/Host/ContentTypes.cs @@ -13,37 +13,31 @@ namespace ServiceStack.Host public void SerializeToStream(IRequest req, object response, Stream responseStream) { var contentType = req.ResponseContentType; - var serializer = GetResponseSerializer(contentType); - if (serializer == null) - throw new NotSupportedException("ContentType not supported: " + contentType); + var serializer = GetStreamSerializer(contentType); - var httpRes = new HttpResponseStreamWrapper(responseStream, req) - { - Dto = req.Response.Dto - }; - serializer(req, response, httpRes); + serializer(response, responseStream); } - public Action GetResponseSerializer(string contentType) + public Action GetResponseSerializer(string contentType) { var serializer = GetStreamSerializer(contentType); if (serializer == null) return null; - return (httpReq, dto, httpRes) => serializer(httpReq, dto, httpRes.OutputStream); + return (dto, httpRes) => serializer(dto, httpRes.OutputStream); } - public Action GetStreamSerializer(string contentType) + public Action GetStreamSerializer(string contentType) { switch (GetRealContentType(contentType)) { case "application/xml": case "text/xml": case "text/xml; charset=utf-8": //"text/xml; charset=utf-8" also matches xml - return (r, o, s) => ServiceStackHost.Instance.SerializeToXml(o, s); + return (o, s) => ServiceStackHost.Instance.SerializeToXml(o, s); case "application/json": case "text/json": - return (r, o, s) => ServiceStackHost.Instance.SerializeToJson(o, s); + return (o, s) => ServiceStackHost.Instance.SerializeToJson(o, s); } return null; diff --git a/ServiceStack/Host/HttpResponseStreamWrapper.cs b/ServiceStack/Host/HttpResponseStreamWrapper.cs deleted file mode 100644 index 33038da72..000000000 --- a/ServiceStack/Host/HttpResponseStreamWrapper.cs +++ /dev/null @@ -1,95 +0,0 @@ -using System.Collections.Generic; -using System.IO; -using System.Net; -using System.Text; -using MediaBrowser.Model.Services; - -namespace ServiceStack.Host -{ - public class HttpResponseStreamWrapper : IHttpResponse - { - private static readonly UTF8Encoding UTF8EncodingWithoutBom = new UTF8Encoding(false); - - public HttpResponseStreamWrapper(Stream stream, IRequest request) - { - this.OutputStream = stream; - this.Request = request; - this.Headers = new Dictionary(); - this.Items = new Dictionary(); - } - - public Dictionary Headers { get; set; } - - public object OriginalResponse - { - get { return null; } - } - - public IRequest Request { get; private set; } - - public int StatusCode { set; get; } - public string StatusDescription { set; get; } - public string ContentType { get; set; } - - public void AddHeader(string name, string value) - { - this.Headers[name] = value; - } - - public string GetHeader(string name) - { - return this.Headers[name]; - } - - public void Redirect(string url) - { - this.Headers["Location"] = url; - } - - public Stream OutputStream { get; private set; } - - public object Dto { get; set; } - - public void Write(string text) - { - var bytes = UTF8EncodingWithoutBom.GetBytes(text); - OutputStream.Write(bytes, 0, bytes.Length); - } - - public bool UseBufferedStream { get; set; } - - public void Close() - { - if (IsClosed) return; - - OutputStream.Dispose(); - IsClosed = true; - } - - public void End() - { - Close(); - } - - public void Flush() - { - OutputStream.Flush(); - } - - public bool IsClosed { get; private set; } - - public void SetContentLength(long contentLength) {} - - public bool KeepAlive { get; set; } - - public Dictionary Items { get; private set; } - - public void SetCookie(Cookie cookie) - { - } - - public void ClearCookies() - { - } - } -} \ No newline at end of file diff --git a/ServiceStack/Host/ServiceController.cs b/ServiceStack/Host/ServiceController.cs index 703f06365..7eb1253b3 100644 --- a/ServiceStack/Host/ServiceController.cs +++ b/ServiceStack/Host/ServiceController.cs @@ -210,9 +210,6 @@ namespace ServiceStack.Host //Executes the service and returns the result var response = await ServiceExecGeneral.Execute(serviceType, req, service, requestDto, requestType.GetOperationName()).ConfigureAwait(false); - if (req.Response.Dto == null) - req.Response.Dto = response; - return response; } } -- cgit v1.2.3 From a855864207fe3ed0ac9b4d648617bb1cb39df3f3 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 12 Nov 2016 02:14:04 -0500 Subject: limit access to response stream --- .../HttpServer/HttpListenerHost.cs | 22 +++++++++++++++------- .../SocketSharp/WebSocketSharpResponse.cs | 21 ++++----------------- MediaBrowser.Model/Services/IRequest.cs | 13 ------------- ServiceStack/Host/ContentTypes.cs | 10 +--------- ServiceStack/HttpResponseExtensionsInternal.cs | 22 ++++++++++++---------- 5 files changed, 32 insertions(+), 56 deletions(-) (limited to 'ServiceStack/Host') diff --git a/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs b/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs index 49c664eec..41b7a4622 100644 --- a/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs +++ b/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs @@ -9,6 +9,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; +using System.Text; using System.Threading.Tasks; using Emby.Server.Implementations.HttpServer; using Emby.Server.Implementations.HttpServer.SocketSharp; @@ -248,9 +249,7 @@ namespace Emby.Server.Implementations.HttpServer httpRes.StatusCode = statusCode; httpRes.ContentType = "text/html"; - httpRes.Write(ex.Message); - - httpRes.Close(); + Write(httpRes, ex.Message); } catch { @@ -404,7 +403,7 @@ namespace Emby.Server.Implementations.HttpServer { httpRes.StatusCode = 400; httpRes.ContentType = "text/plain"; - httpRes.Write("Invalid host"); + Write(httpRes, "Invalid host"); return; } @@ -458,7 +457,7 @@ namespace Emby.Server.Implementations.HttpServer if (!string.Equals(newUrl, urlString, StringComparison.OrdinalIgnoreCase)) { - httpRes.Write( + Write(httpRes, "EmbyPlease update your Emby bookmark to " + newUrl + ""); return; @@ -475,7 +474,7 @@ namespace Emby.Server.Implementations.HttpServer if (!string.Equals(newUrl, urlString, StringComparison.OrdinalIgnoreCase)) { - httpRes.Write( + Write(httpRes, "EmbyPlease update your Emby bookmark to " + newUrl + ""); return; @@ -513,7 +512,7 @@ namespace Emby.Server.Implementations.HttpServer { httpRes.StatusCode = 503; httpRes.ContentType = "text/html"; - httpRes.Write(GlobalResponse); + Write(httpRes, GlobalResponse); return; } @@ -547,6 +546,15 @@ namespace Emby.Server.Implementations.HttpServer } } + private void Write(IResponse response, string text) + { + var bOutput = Encoding.UTF8.GetBytes(text); + response.SetContentLength(bOutput.Length); + + var outputStream = response.OutputStream; + outputStream.Write(bOutput, 0, bOutput.Length); + } + public static void RedirectToUrl(IResponse httpRes, string url) { httpRes.StatusCode = 302; diff --git a/Emby.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpResponse.cs b/Emby.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpResponse.cs index 9de86e9cc..a8b115056 100644 --- a/Emby.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpResponse.cs +++ b/Emby.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpResponse.cs @@ -77,16 +77,6 @@ namespace Emby.Server.Implementations.HttpServer.SocketSharp get { return _response.OutputStream; } } - public void Write(string text) - { - var bOutput = System.Text.Encoding.UTF8.GetBytes(text); - _response.ContentLength64 = bOutput.Length; - - var outputStream = _response.OutputStream; - outputStream.Write(bOutput, 0, bOutput.Length); - Close(); - } - public void Close() { if (!this.IsClosed) @@ -108,8 +98,10 @@ namespace Emby.Server.Implementations.HttpServer.SocketSharp { try { - response.OutputStream.Flush(); - response.OutputStream.Dispose(); + var outputStream = response.OutputStream; + + outputStream.Flush(); + outputStream.Dispose(); response.Close(); } catch (Exception ex) @@ -118,11 +110,6 @@ namespace Emby.Server.Implementations.HttpServer.SocketSharp } } - public void Flush() - { - _response.OutputStream.Flush(); - } - public bool IsClosed { get; diff --git a/MediaBrowser.Model/Services/IRequest.cs b/MediaBrowser.Model/Services/IRequest.cs index 455a69d37..e9a9f1c5b 100644 --- a/MediaBrowser.Model/Services/IRequest.cs +++ b/MediaBrowser.Model/Services/IRequest.cs @@ -136,23 +136,12 @@ namespace MediaBrowser.Model.Services Stream OutputStream { get; } - /// - /// Write once to the Response Stream then close it. - /// - /// - void Write(string text); - /// /// Signal that this response has been handled and no more processing should be done. /// When used in a request or response filter, no more filters or processing is done on this request. /// void Close(); - /// - /// Response.Flush() and OutputStream.Flush() seem to have different behaviour in ASP.NET - /// - void Flush(); - /// /// Gets a value indicating whether this instance is closed. /// @@ -160,8 +149,6 @@ namespace MediaBrowser.Model.Services void SetContentLength(long contentLength); - bool KeepAlive { get; set; } - //Add Metadata to Response Dictionary Items { get; } } diff --git a/ServiceStack/Host/ContentTypes.cs b/ServiceStack/Host/ContentTypes.cs index 58ba29801..8840e7c8b 100644 --- a/ServiceStack/Host/ContentTypes.cs +++ b/ServiceStack/Host/ContentTypes.cs @@ -18,15 +18,7 @@ namespace ServiceStack.Host serializer(response, responseStream); } - public Action GetResponseSerializer(string contentType) - { - var serializer = GetStreamSerializer(contentType); - if (serializer == null) return null; - - return (dto, httpRes) => serializer(dto, httpRes.OutputStream); - } - - public Action GetStreamSerializer(string contentType) + private Action GetStreamSerializer(string contentType) { switch (GetRealContentType(contentType)) { diff --git a/ServiceStack/HttpResponseExtensionsInternal.cs b/ServiceStack/HttpResponseExtensionsInternal.cs index 88b82bdf6..44b790f5f 100644 --- a/ServiceStack/HttpResponseExtensionsInternal.cs +++ b/ServiceStack/HttpResponseExtensionsInternal.cs @@ -6,6 +6,7 @@ using System.IO; using System.Net; using System.Threading.Tasks; using System.Collections.Generic; +using System.Text; using System.Threading; using MediaBrowser.Model.Services; using ServiceStack.Host; @@ -14,19 +15,19 @@ namespace ServiceStack { public static class HttpResponseExtensionsInternal { - public static async Task WriteToOutputStream(IResponse response, object result) + public static async Task WriteToOutputStream(IResponse response, Stream outputStream, object result) { var asyncStreamWriter = result as IAsyncStreamWriter; if (asyncStreamWriter != null) { - await asyncStreamWriter.WriteToAsync(response.OutputStream, CancellationToken.None).ConfigureAwait(false); + await asyncStreamWriter.WriteToAsync(outputStream, CancellationToken.None).ConfigureAwait(false); return true; } var streamWriter = result as IStreamWriter; if (streamWriter != null) { - streamWriter.WriteTo(response.OutputStream); + streamWriter.WriteTo(outputStream); return true; } @@ -35,7 +36,7 @@ namespace ServiceStack { using (stream) { - await stream.CopyToAsync(response.OutputStream).ConfigureAwait(false); + await stream.CopyToAsync(outputStream).ConfigureAwait(false); return true; } } @@ -46,7 +47,7 @@ namespace ServiceStack response.ContentType = "application/octet-stream"; response.SetContentLength(bytes.Length); - await response.OutputStream.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false); + await outputStream.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false); return true; } @@ -151,10 +152,11 @@ namespace ServiceStack response.ContentType += "; charset=utf-8"; } - var writeToOutputStreamResult = await WriteToOutputStream(response, result).ConfigureAwait(false); + var outputStream = response.OutputStream; + + var writeToOutputStreamResult = await WriteToOutputStream(response, outputStream, result).ConfigureAwait(false); if (writeToOutputStreamResult) { - response.Flush(); //required for Compression return; } @@ -164,12 +166,12 @@ namespace ServiceStack if (response.ContentType == null || response.ContentType == "text/html") response.ContentType = defaultContentType; - response.Write(responseText); + var bytes = Encoding.UTF8.GetBytes(responseText); + await outputStream.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false); return; } - var serializer = ContentTypes.Instance.GetResponseSerializer(defaultContentType); - serializer(result, response); + ContentTypes.Instance.SerializeToStream(request, result, outputStream); } } } -- cgit v1.2.3 From 6865bb53530abbf703b590dd39cfa27274b03107 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 12 Nov 2016 02:45:06 -0500 Subject: update responses --- ServiceStack/Host/ContentTypes.cs | 2 +- ServiceStack/HttpResponseExtensionsInternal.cs | 35 ++++++++++++++++++-------- ServiceStack/HttpResult.cs | 2 +- 3 files changed, 27 insertions(+), 12 deletions(-) (limited to 'ServiceStack/Host') diff --git a/ServiceStack/Host/ContentTypes.cs b/ServiceStack/Host/ContentTypes.cs index 8840e7c8b..f7734a36b 100644 --- a/ServiceStack/Host/ContentTypes.cs +++ b/ServiceStack/Host/ContentTypes.cs @@ -18,7 +18,7 @@ namespace ServiceStack.Host serializer(response, responseStream); } - private Action GetStreamSerializer(string contentType) + public static Action GetStreamSerializer(string contentType) { switch (GetRealContentType(contentType)) { diff --git a/ServiceStack/HttpResponseExtensionsInternal.cs b/ServiceStack/HttpResponseExtensionsInternal.cs index 44b790f5f..318d62429 100644 --- a/ServiceStack/HttpResponseExtensionsInternal.cs +++ b/ServiceStack/HttpResponseExtensionsInternal.cs @@ -15,19 +15,19 @@ namespace ServiceStack { public static class HttpResponseExtensionsInternal { - public static async Task WriteToOutputStream(IResponse response, Stream outputStream, object result) + public static async Task WriteToOutputStream(IResponse response, object result) { var asyncStreamWriter = result as IAsyncStreamWriter; if (asyncStreamWriter != null) { - await asyncStreamWriter.WriteToAsync(outputStream, CancellationToken.None).ConfigureAwait(false); + await asyncStreamWriter.WriteToAsync(response.OutputStream, CancellationToken.None).ConfigureAwait(false); return true; } var streamWriter = result as IStreamWriter; if (streamWriter != null) { - streamWriter.WriteTo(outputStream); + streamWriter.WriteTo(response.OutputStream); return true; } @@ -36,7 +36,7 @@ namespace ServiceStack { using (stream) { - await stream.CopyToAsync(outputStream).ConfigureAwait(false); + await stream.CopyToAsync(response.OutputStream).ConfigureAwait(false); return true; } } @@ -47,7 +47,7 @@ namespace ServiceStack response.ContentType = "application/octet-stream"; response.SetContentLength(bytes.Length); - await outputStream.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false); + await response.OutputStream.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false); return true; } @@ -152,9 +152,7 @@ namespace ServiceStack response.ContentType += "; charset=utf-8"; } - var outputStream = response.OutputStream; - - var writeToOutputStreamResult = await WriteToOutputStream(response, outputStream, result).ConfigureAwait(false); + var writeToOutputStreamResult = await WriteToOutputStream(response, result).ConfigureAwait(false); if (writeToOutputStreamResult) { return; @@ -167,11 +165,28 @@ namespace ServiceStack response.ContentType = defaultContentType; var bytes = Encoding.UTF8.GetBytes(responseText); - await outputStream.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false); + await response.OutputStream.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false); return; } - ContentTypes.Instance.SerializeToStream(request, result, outputStream); + await WriteObject(request, result, response).ConfigureAwait(false); + } + + public static async Task WriteObject(IRequest request, object result, IResponse response) + { + var contentType = request.ResponseContentType; + var serializer = ContentTypes.GetStreamSerializer(contentType); + + using (var ms = new MemoryStream()) + { + serializer(result, ms); + + ms.Position = 0; + response.SetContentLength(ms.Length); + await ms.CopyToAsync(response.OutputStream).ConfigureAwait(false); + } + + //serializer(result, outputStream); } } } diff --git a/ServiceStack/HttpResult.cs b/ServiceStack/HttpResult.cs index e25002b3e..3f86ffdf7 100644 --- a/ServiceStack/HttpResult.cs +++ b/ServiceStack/HttpResult.cs @@ -55,7 +55,7 @@ namespace ServiceStack return; } - ContentTypes.Instance.SerializeToStream(this.RequestContext, this.Response, responseStream); + await HttpResponseExtensionsInternal.WriteObject(this.RequestContext, this.Response, response).ConfigureAwait(false); } } } -- cgit v1.2.3