From 406e6cb8132c1b8ade2872d44d7183267dd51ca8 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 11 Nov 2016 14:55:12 -0500 Subject: update portable projects --- .../Net/HttpListenerRequest.cs | 654 +++++++++++++++++++++ 1 file changed, 654 insertions(+) create mode 100644 SocketHttpListener.Portable/Net/HttpListenerRequest.cs (limited to 'SocketHttpListener.Portable/Net/HttpListenerRequest.cs') diff --git a/SocketHttpListener.Portable/Net/HttpListenerRequest.cs b/SocketHttpListener.Portable/Net/HttpListenerRequest.cs new file mode 100644 index 000000000..63d5e510d --- /dev/null +++ b/SocketHttpListener.Portable/Net/HttpListenerRequest.cs @@ -0,0 +1,654 @@ +using System; +using System.Collections.Specialized; +using System.Globalization; +using System.IO; +using System.Net; +using System.Text; +using System.Threading.Tasks; +using MediaBrowser.Model.Net; +using MediaBrowser.Model.Services; +using MediaBrowser.Model.Text; +using SocketHttpListener.Primitives; + +namespace SocketHttpListener.Net +{ + public sealed class HttpListenerRequest + { + string[] accept_types; + Encoding content_encoding; + long content_length; + bool cl_set; + CookieCollection cookies; + WebHeaderCollection headers; + string method; + Stream input_stream; + Version version; + QueryParamCollection query_string; // check if null is ok, check if read-only, check case-sensitiveness + string raw_url; + Uri url; + Uri referrer; + string[] user_languages; + HttpListenerContext context; + bool is_chunked; + bool ka_set; + bool keep_alive; + + private readonly ITextEncoding _textEncoding; + + internal HttpListenerRequest(HttpListenerContext context, ITextEncoding textEncoding) + { + this.context = context; + _textEncoding = textEncoding; + headers = new WebHeaderCollection(); + version = HttpVersion.Version10; + } + + static char[] separators = new char[] { ' ' }; + + internal void SetRequestLine(string req) + { + string[] parts = req.Split(separators, 3); + if (parts.Length != 3) + { + context.ErrorMessage = "Invalid request line (parts)."; + return; + } + + method = parts[0]; + foreach (char c in method) + { + int ic = (int)c; + + if ((ic >= 'A' && ic <= 'Z') || + (ic > 32 && c < 127 && c != '(' && c != ')' && c != '<' && + c != '<' && c != '>' && c != '@' && c != ',' && c != ';' && + c != ':' && c != '\\' && c != '"' && c != '/' && c != '[' && + c != ']' && c != '?' && c != '=' && c != '{' && c != '}')) + continue; + + context.ErrorMessage = "(Invalid verb)"; + return; + } + + raw_url = parts[1]; + if (parts[2].Length != 8 || !parts[2].StartsWith("HTTP/")) + { + context.ErrorMessage = "Invalid request line (version)."; + return; + } + + try + { + version = new Version(parts[2].Substring(5)); + if (version.Major < 1) + throw new Exception(); + } + catch + { + context.ErrorMessage = "Invalid request line (version)."; + return; + } + } + + void CreateQueryString(string query) + { + if (query == null || query.Length == 0) + { + query_string = new QueryParamCollection(); + return; + } + + query_string = new QueryParamCollection(); + if (query[0] == '?') + query = query.Substring(1); + string[] components = query.Split('&'); + foreach (string kv in components) + { + int pos = kv.IndexOf('='); + if (pos == -1) + { + query_string.Add(null, WebUtility.UrlDecode(kv)); + } + else + { + string key = WebUtility.UrlDecode(kv.Substring(0, pos)); + string val = WebUtility.UrlDecode(kv.Substring(pos + 1)); + + query_string.Add(key, val); + } + } + } + + internal void FinishInitialization() + { + string host = UserHostName; + if (version > HttpVersion.Version10 && (host == null || host.Length == 0)) + { + context.ErrorMessage = "Invalid host name"; + return; + } + + string path; + Uri raw_uri = null; + if (MaybeUri(raw_url.ToLowerInvariant()) && Uri.TryCreate(raw_url, UriKind.Absolute, out raw_uri)) + path = raw_uri.PathAndQuery; + else + path = raw_url; + + if ((host == null || host.Length == 0)) + host = UserHostAddress; + + if (raw_uri != null) + host = raw_uri.Host; + + int colon = host.LastIndexOf(':'); + if (colon >= 0) + host = host.Substring(0, colon); + + string base_uri = String.Format("{0}://{1}:{2}", + (IsSecureConnection) ? (IsWebSocketRequest ? "wss" : "https") : (IsWebSocketRequest ? "ws" : "http"), + host, LocalEndPoint.Port); + + if (!Uri.TryCreate(base_uri + path, UriKind.Absolute, out url)) + { + context.ErrorMessage = WebUtility.HtmlEncode("Invalid url: " + base_uri + path); + return; return; + } + + CreateQueryString(url.Query); + + if (version >= HttpVersion.Version11) + { + string t_encoding = Headers["Transfer-Encoding"]; + is_chunked = (t_encoding != null && String.Compare(t_encoding, "chunked", StringComparison.OrdinalIgnoreCase) == 0); + // 'identity' is not valid! + if (t_encoding != null && !is_chunked) + { + context.Connection.SendError(null, 501); + return; + } + } + + if (!is_chunked && !cl_set) + { + if (String.Compare(method, "POST", StringComparison.OrdinalIgnoreCase) == 0 || + String.Compare(method, "PUT", StringComparison.OrdinalIgnoreCase) == 0) + { + context.Connection.SendError(null, 411); + return; + } + } + + if (String.Compare(Headers["Expect"], "100-continue", StringComparison.OrdinalIgnoreCase) == 0) + { + ResponseStream output = context.Connection.GetResponseStream(); + + var _100continue = _textEncoding.GetASCIIEncoding().GetBytes("HTTP/1.1 100 Continue\r\n\r\n"); + + output.InternalWrite(_100continue, 0, _100continue.Length); + } + } + + static bool MaybeUri(string s) + { + int p = s.IndexOf(':'); + if (p == -1) + return false; + + if (p >= 10) + return false; + + return IsPredefinedScheme(s.Substring(0, p)); + } + + // + // Using a simple block of if's is twice as slow as the compiler generated + // switch statement. But using this tuned code is faster than the + // compiler generated code, with a million loops on x86-64: + // + // With "http": .10 vs .51 (first check) + // with "https": .16 vs .51 (second check) + // with "foo": .22 vs .31 (never found) + // with "mailto": .12 vs .51 (last check) + // + // + static bool IsPredefinedScheme(string scheme) + { + if (scheme == null || scheme.Length < 3) + return false; + + char c = scheme[0]; + if (c == 'h') + return (scheme == "http" || scheme == "https"); + if (c == 'f') + return (scheme == "file" || scheme == "ftp"); + + if (c == 'n') + { + c = scheme[1]; + if (c == 'e') + return (scheme == "news" || scheme == "net.pipe" || scheme == "net.tcp"); + if (scheme == "nntp") + return true; + return false; + } + if ((c == 'g' && scheme == "gopher") || (c == 'm' && scheme == "mailto")) + return true; + + return false; + } + + internal static string Unquote(String str) + { + int start = str.IndexOf('\"'); + int end = str.LastIndexOf('\"'); + if (start >= 0 && end >= 0) + str = str.Substring(start + 1, end - 1); + return str.Trim(); + } + + internal void AddHeader(string header) + { + int colon = header.IndexOf(':'); + if (colon == -1 || colon == 0) + { + context.ErrorMessage = "Bad Request"; + context.ErrorStatus = 400; + return; + } + + string name = header.Substring(0, colon).Trim(); + string val = header.Substring(colon + 1).Trim(); + string lower = name.ToLowerInvariant(); + headers.SetInternal(name, val); + switch (lower) + { + case "accept-language": + user_languages = val.Split(','); // yes, only split with a ',' + break; + case "accept": + accept_types = val.Split(','); // yes, only split with a ',' + break; + case "content-length": + try + { + //TODO: max. content_length? + content_length = Int64.Parse(val.Trim()); + if (content_length < 0) + context.ErrorMessage = "Invalid Content-Length."; + cl_set = true; + } + catch + { + context.ErrorMessage = "Invalid Content-Length."; + } + + break; + case "content-type": + { + var contents = val.Split(';'); + foreach (var content in contents) + { + var tmp = content.Trim(); + if (tmp.StartsWith("charset")) + { + var charset = tmp.GetValue("="); + if (charset != null && charset.Length > 0) + { + try + { + + // Support upnp/dlna devices - CONTENT-TYPE: text/xml ; charset="utf-8"\r\n + charset = charset.Trim('"'); + var index = charset.IndexOf('"'); + if (index != -1) charset = charset.Substring(0, index); + + content_encoding = Encoding.GetEncoding(charset); + } + catch + { + context.ErrorMessage = "Invalid Content-Type header: " + charset; + } + } + + break; + } + } + } + break; + case "referer": + try + { + referrer = new Uri(val); + } + catch + { + referrer = new Uri("http://someone.is.screwing.with.the.headers.com/"); + } + break; + case "cookie": + if (cookies == null) + cookies = new CookieCollection(); + + string[] cookieStrings = val.Split(new char[] { ',', ';' }); + Cookie current = null; + int version = 0; + foreach (string cookieString in cookieStrings) + { + string str = cookieString.Trim(); + if (str.Length == 0) + continue; + if (str.StartsWith("$Version")) + { + version = Int32.Parse(Unquote(str.Substring(str.IndexOf('=') + 1))); + } + else if (str.StartsWith("$Path")) + { + if (current != null) + current.Path = str.Substring(str.IndexOf('=') + 1).Trim(); + } + else if (str.StartsWith("$Domain")) + { + if (current != null) + current.Domain = str.Substring(str.IndexOf('=') + 1).Trim(); + } + else if (str.StartsWith("$Port")) + { + if (current != null) + current.Port = str.Substring(str.IndexOf('=') + 1).Trim(); + } + else + { + if (current != null) + { + cookies.Add(current); + } + current = new Cookie(); + int idx = str.IndexOf('='); + if (idx > 0) + { + current.Name = str.Substring(0, idx).Trim(); + current.Value = str.Substring(idx + 1).Trim(); + } + else + { + current.Name = str.Trim(); + current.Value = String.Empty; + } + current.Version = version; + } + } + if (current != null) + { + cookies.Add(current); + } + break; + } + } + + // returns true is the stream could be reused. + internal bool FlushInput() + { + if (!HasEntityBody) + return true; + + int length = 2048; + if (content_length > 0) + length = (int)Math.Min(content_length, (long)length); + + byte[] bytes = new byte[length]; + while (true) + { + // TODO: test if MS has a timeout when doing this + try + { + var task = InputStream.ReadAsync(bytes, 0, length); + var result = Task.WaitAll(new [] { task }, 1000); + if (!result) + { + return false; + } + if (task.Result <= 0) + { + return true; + } + } + catch (ObjectDisposedException e) + { + input_stream = null; + return true; + } + catch + { + return false; + } + } + } + + public string[] AcceptTypes + { + get { return accept_types; } + } + + public int ClientCertificateError + { + get + { + HttpConnection cnc = context.Connection; + //if (cnc.ClientCertificate == null) + // throw new InvalidOperationException("No client certificate"); + //int[] errors = cnc.ClientCertificateErrors; + //if (errors != null && errors.Length > 0) + // return errors[0]; + return 0; + } + } + + public Encoding ContentEncoding + { + get + { + if (content_encoding == null) + content_encoding = _textEncoding.GetDefaultEncoding(); + return content_encoding; + } + } + + public long ContentLength64 + { + get { return content_length; } + } + + public string ContentType + { + get { return headers["content-type"]; } + } + + public CookieCollection Cookies + { + get + { + // TODO: check if the collection is read-only + if (cookies == null) + cookies = new CookieCollection(); + return cookies; + } + } + + public bool HasEntityBody + { + get { return (content_length > 0 || is_chunked); } + } + + public QueryParamCollection Headers + { + get { return headers; } + } + + public string HttpMethod + { + get { return method; } + } + + public Stream InputStream + { + get + { + if (input_stream == null) + { + if (is_chunked || content_length > 0) + input_stream = context.Connection.GetRequestStream(is_chunked, content_length); + else + input_stream = Stream.Null; + } + + return input_stream; + } + } + + public bool IsAuthenticated + { + get { return false; } + } + + public bool IsLocal + { + get { return RemoteEndPoint.IpAddress.Equals(IpAddressInfo.Loopback) || RemoteEndPoint.IpAddress.Equals(IpAddressInfo.IPv6Loopback) || LocalEndPoint.IpAddress.Equals(RemoteEndPoint.IpAddress); } + } + + public bool IsSecureConnection + { + get { return context.Connection.IsSecure; } + } + + public bool KeepAlive + { + get + { + if (ka_set) + return keep_alive; + + ka_set = true; + // 1. Connection header + // 2. Protocol (1.1 == keep-alive by default) + // 3. Keep-Alive header + string cnc = headers["Connection"]; + if (!String.IsNullOrEmpty(cnc)) + { + keep_alive = (0 == String.Compare(cnc, "keep-alive", StringComparison.OrdinalIgnoreCase)); + } + else if (version == HttpVersion.Version11) + { + keep_alive = true; + } + else + { + cnc = headers["keep-alive"]; + if (!String.IsNullOrEmpty(cnc)) + keep_alive = (0 != String.Compare(cnc, "closed", StringComparison.OrdinalIgnoreCase)); + } + return keep_alive; + } + } + + public IpEndPointInfo LocalEndPoint + { + get { return context.Connection.LocalEndPoint; } + } + + public Version ProtocolVersion + { + get { return version; } + } + + public QueryParamCollection QueryString + { + get { return query_string; } + } + + public string RawUrl + { + get { return raw_url; } + } + + public IpEndPointInfo RemoteEndPoint + { + get { return context.Connection.RemoteEndPoint; } + } + + public Guid RequestTraceIdentifier + { + get { return Guid.Empty; } + } + + public Uri Url + { + get { return url; } + } + + public Uri UrlReferrer + { + get { return referrer; } + } + + public string UserAgent + { + get { return headers["user-agent"]; } + } + + public string UserHostAddress + { + get { return LocalEndPoint.ToString(); } + } + + public string UserHostName + { + get { return headers["host"]; } + } + + public string[] UserLanguages + { + get { return user_languages; } + } + + public string ServiceName + { + get + { + return null; + } + } + + private bool _websocketRequestWasSet; + private bool _websocketRequest; + + /// + /// Gets a value indicating whether the request is a WebSocket connection request. + /// + /// + /// true if the request is a WebSocket connection request; otherwise, false. + /// + public bool IsWebSocketRequest + { + get + { + if (!_websocketRequestWasSet) + { + _websocketRequest = method == "GET" && + version > HttpVersion.Version10 && + headers.Contains("Upgrade", "websocket") && + headers.Contains("Connection", "Upgrade"); + + _websocketRequestWasSet = true; + } + + return _websocketRequest; + } + } + + public Task GetClientCertificateAsync() + { + return Task.FromResult(null); + } + } +} -- cgit v1.2.3 From 1714cb8764f2311fd255945d5a03d6b298f62071 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 12 Nov 2016 03:02:46 -0500 Subject: update response stream handling --- Emby.Server.Core/ApplicationHost.cs | 3 --- .../HttpServer/SocketSharp/WebSocketSharpResponse.cs | 7 ++++++- MediaBrowser.ServerApplication/MainStartup.cs | 4 ++++ SocketHttpListener.Portable/Net/HttpConnection.cs | 17 ++++++++++++++--- SocketHttpListener.Portable/Net/HttpListenerRequest.cs | 4 ++-- SocketHttpListener.Portable/Net/HttpListenerResponse.cs | 2 +- SocketHttpListener.Portable/Net/ResponseStream.cs | 10 +++++----- 7 files changed, 32 insertions(+), 15 deletions(-) (limited to 'SocketHttpListener.Portable/Net/HttpListenerRequest.cs') diff --git a/Emby.Server.Core/ApplicationHost.cs b/Emby.Server.Core/ApplicationHost.cs index 0c0ef894e..5c8aea7ed 100644 --- a/Emby.Server.Core/ApplicationHost.cs +++ b/Emby.Server.Core/ApplicationHost.cs @@ -1136,9 +1136,6 @@ namespace Emby.Server.Core { get { -#if DEBUG - return false; -#endif #pragma warning disable 162 return NativeApp.CanSelfUpdate; #pragma warning restore 162 diff --git a/Emby.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpResponse.cs b/Emby.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpResponse.cs index a8b115056..dc049cbde 100644 --- a/Emby.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpResponse.cs +++ b/Emby.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpResponse.cs @@ -100,7 +100,12 @@ namespace Emby.Server.Implementations.HttpServer.SocketSharp { var outputStream = response.OutputStream; - outputStream.Flush(); + // This is needed with compression + //if (!string.IsNullOrWhiteSpace(GetHeader("Content-Encoding"))) + { + outputStream.Flush(); + } + outputStream.Dispose(); response.Close(); } diff --git a/MediaBrowser.ServerApplication/MainStartup.cs b/MediaBrowser.ServerApplication/MainStartup.cs index 09c948a4a..fa8cccf34 100644 --- a/MediaBrowser.ServerApplication/MainStartup.cs +++ b/MediaBrowser.ServerApplication/MainStartup.cs @@ -291,6 +291,10 @@ namespace MediaBrowser.ServerApplication { get { +#if DEBUG + return false; +#endif + if (_isRunningAsService) { return _canRestartService; diff --git a/SocketHttpListener.Portable/Net/HttpConnection.cs b/SocketHttpListener.Portable/Net/HttpConnection.cs index db34c4218..8e472117e 100644 --- a/SocketHttpListener.Portable/Net/HttpConnection.cs +++ b/SocketHttpListener.Portable/Net/HttpConnection.cs @@ -23,7 +23,7 @@ namespace SocketHttpListener.Net StringBuilder current_line; ListenerPrefix prefix; RequestStream i_stream; - ResponseStream o_stream; + Stream o_stream; bool chunked; int reuses; bool context_bound; @@ -204,12 +204,23 @@ namespace SocketHttpListener.Net return i_stream; } - public ResponseStream GetResponseStream() + public Stream GetResponseStream() { // TODO: can we get this stream before reading the input? if (o_stream == null) { - o_stream = new ResponseStream(stream, context.Response, _memoryStreamFactory, _textEncoding); + if (context.Response.SendChunked) + { + o_stream = new ResponseStream(stream, context.Response, _memoryStreamFactory, _textEncoding); + } + else + { + o_stream = stream; + using (var headerStream = ResponseStream.GetHeaders(context.Response, _memoryStreamFactory, false)) + { + headerStream.CopyTo(o_stream); + } + } } return o_stream; } diff --git a/SocketHttpListener.Portable/Net/HttpListenerRequest.cs b/SocketHttpListener.Portable/Net/HttpListenerRequest.cs index 63d5e510d..5631fc0a1 100644 --- a/SocketHttpListener.Portable/Net/HttpListenerRequest.cs +++ b/SocketHttpListener.Portable/Net/HttpListenerRequest.cs @@ -181,11 +181,11 @@ namespace SocketHttpListener.Net if (String.Compare(Headers["Expect"], "100-continue", StringComparison.OrdinalIgnoreCase) == 0) { - ResponseStream output = context.Connection.GetResponseStream(); + var output = context.Connection.GetResponseStream(); var _100continue = _textEncoding.GetASCIIEncoding().GetBytes("HTTP/1.1 100 Continue\r\n\r\n"); - output.InternalWrite(_100continue, 0, _100continue.Length); + //output.InternalWrite(_100continue, 0, _100continue.Length); } } diff --git a/SocketHttpListener.Portable/Net/HttpListenerResponse.cs b/SocketHttpListener.Portable/Net/HttpListenerResponse.cs index 0bc827b5a..93358cae4 100644 --- a/SocketHttpListener.Portable/Net/HttpListenerResponse.cs +++ b/SocketHttpListener.Portable/Net/HttpListenerResponse.cs @@ -19,7 +19,7 @@ namespace SocketHttpListener.Net CookieCollection cookies; WebHeaderCollection headers = new WebHeaderCollection(); bool keep_alive = true; - ResponseStream output_stream; + Stream output_stream; Version version = HttpVersion.Version11; string location; int status_code = 200; diff --git a/SocketHttpListener.Portable/Net/ResponseStream.cs b/SocketHttpListener.Portable/Net/ResponseStream.cs index 07788ea41..7a6425dea 100644 --- a/SocketHttpListener.Portable/Net/ResponseStream.cs +++ b/SocketHttpListener.Portable/Net/ResponseStream.cs @@ -64,7 +64,7 @@ namespace SocketHttpListener.Net { disposed = true; byte[] bytes = null; - MemoryStream ms = GetHeaders(true); + MemoryStream ms = GetHeaders(response, _memoryStreamFactory, false); bool chunked = response.SendChunked; if (stream.CanWrite) { @@ -102,14 +102,14 @@ namespace SocketHttpListener.Net base.Dispose(disposing); } - MemoryStream GetHeaders(bool closing) + internal static MemoryStream GetHeaders(HttpListenerResponse response, IMemoryStreamFactory memoryStreamFactory, bool closing) { // SendHeaders works on shared headers lock (response.headers_lock) { if (response.HeadersSent) return null; - MemoryStream ms = _memoryStreamFactory.CreateNew(); + MemoryStream ms = memoryStreamFactory.CreateNew(); response.SendHeaders(closing, ms); return ms; } @@ -137,7 +137,7 @@ namespace SocketHttpListener.Net throw new ObjectDisposedException(GetType().ToString()); byte[] bytes = null; - MemoryStream ms = GetHeaders(false); + MemoryStream ms = GetHeaders(response, _memoryStreamFactory, false); bool chunked = response.SendChunked; if (ms != null) { @@ -177,7 +177,7 @@ namespace SocketHttpListener.Net throw new ObjectDisposedException(GetType().ToString()); byte[] bytes = null; - MemoryStream ms = GetHeaders(false); + MemoryStream ms = GetHeaders(response, _memoryStreamFactory, false); bool chunked = response.SendChunked; if (ms != null) { -- cgit v1.2.3 From 102bbe2beb76fa76b21f4ed3f7c584a58d787204 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 12 Nov 2016 17:46:38 -0500 Subject: fix mono project --- .../MediaBrowser.Server.Mono.csproj | 44 ++++++++++++++++++++++ ServiceStack/Host/RestHandler.cs | 36 +++--------------- ServiceStack/ServiceStackHost.Runtime.cs | 21 +---------- SocketHttpListener.Portable/Net/HttpConnection.cs | 6 +-- .../Net/HttpListenerRequest.cs | 13 +++++-- .../Net/HttpListenerResponse.cs | 4 +- 6 files changed, 66 insertions(+), 58 deletions(-) (limited to 'SocketHttpListener.Portable/Net/HttpListenerRequest.cs') diff --git a/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj b/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj index 090e8ea9a..ca830b2f4 100644 --- a/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj +++ b/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj @@ -115,6 +115,34 @@ + + {88ae38df-19d7-406f-a6a9-09527719a21e} + BDInfo + + + {713f42b5-878e-499d-a878-e4c652b1d5e8} + DvdLib + + + {805844ab-e92f-45e6-9d99-4f6d48d129a5} + Emby.Dlna + + + {6cfee013-6e7c-432b-ac37-cabf0880c69a} + Emby.Drawing.ImageMagick + + + {c97a239e-a96c-4d64-a844-ccf8cc30aecb} + Emby.Drawing.Net + + + {08fff49b-f175-4807-a2b5-73b0ebd9f716} + Emby.Drawing + + + {89ab4548-770d-41fd-a891-8daff44f452c} + Emby.Photos + {e383961b-9356-4d5d-8233-9a1079d03055} Emby.Server.Implementations @@ -163,6 +191,22 @@ {23499896-B135-4527-8574-C26E926EA99E} MediaBrowser.XbmcMetadata + + {4a4402d4-e910-443b-b8fc-2c18286a2ca0} + OpenSubtitlesHandler + + + {21002819-c39a-4d3e-be83-2a276a77fb1f} + RSSDP + + + {680a1709-25eb-4d52-a87f-ee03ffd94baa} + ServiceStack + + + {4f26d5d8-a7b0-42b3-ba42-7cb7d245934e} + SocketHttpListener.Portable + diff --git a/ServiceStack/Host/RestHandler.cs b/ServiceStack/Host/RestHandler.cs index 5c360d150..1eae6be38 100644 --- a/ServiceStack/Host/RestHandler.cs +++ b/ServiceStack/Host/RestHandler.cs @@ -23,32 +23,13 @@ namespace ServiceStack.Host var taskResult = ServiceStackHost.Instance.GetTaskResult(taskResponse, RequestName); - var taskResults = taskResult as Task[]; - - if (taskResults == null) - { - var subTask = taskResult as Task; - if (subTask != null) - taskResult = ServiceStackHost.Instance.GetTaskResult(subTask, RequestName); - - return taskResult; - } - - if (taskResults.Length == 0) + var subTask = taskResult as Task; + if (subTask != null) { - return new object[] { }; + taskResult = ServiceStackHost.Instance.GetTaskResult(subTask, RequestName); } - var firstResponse = ServiceStackHost.Instance.GetTaskResult(taskResults[0], RequestName); - var batchedResponses = firstResponse != null - ? (object[])Array.CreateInstance(firstResponse.GetType(), taskResults.Length) - : new object[taskResults.Length]; - batchedResponses[0] = firstResponse; - for (var i = 1; i < taskResults.Length; i++) - { - batchedResponses[i] = ServiceStackHost.Instance.GetTaskResult(taskResults[i], RequestName); - } - return batchedResponses; + return taskResult; } protected static object CreateContentTypeRequest(IRequest httpReq, Type requestType, string contentType) @@ -141,18 +122,13 @@ namespace ServiceStack.Host var request = httpReq.Dto = CreateRequest(httpReq, restPath); - if (appHost.ApplyRequestFilters(httpReq, httpRes, request)) - return; + appHost.ApplyRequestFilters(httpReq, httpRes, request); var rawResponse = await ServiceStackHost.Instance.ServiceController.Execute(request, httpReq).ConfigureAwait(false); - if (httpRes.IsClosed) - return; - var response = await HandleResponseAsync(rawResponse).ConfigureAwait(false); - if (appHost.ApplyResponseFilters(httpReq, httpRes, response)) - return; + appHost.ApplyResponseFilters(httpReq, httpRes, response); await httpRes.WriteToResponse(httpReq, response).ConfigureAwait(false); } diff --git a/ServiceStack/ServiceStackHost.Runtime.cs b/ServiceStack/ServiceStackHost.Runtime.cs index 1a1656a0e..aaa50633b 100644 --- a/ServiceStack/ServiceStackHost.Runtime.cs +++ b/ServiceStack/ServiceStackHost.Runtime.cs @@ -14,10 +14,8 @@ namespace ServiceStack /// and no more processing should be done. /// /// - public virtual bool ApplyRequestFilters(IRequest req, IResponse res, object requestDto) + public virtual void ApplyRequestFilters(IRequest req, IResponse res, object requestDto) { - if (res.IsClosed) return res.IsClosed; - //Exec all RequestFilter attributes with Priority < 0 var attributes = FilterAttributeCache.GetRequestFilterAttributes(requestDto.GetType()); var i = 0; @@ -25,16 +23,12 @@ namespace ServiceStack { var attribute = attributes[i]; attribute.RequestFilter(req, res, requestDto); - if (res.IsClosed) return res.IsClosed; } - if (res.IsClosed) return res.IsClosed; - //Exec global filters foreach (var requestFilter in GlobalRequestFilters) { requestFilter(req, res, requestDto); - if (res.IsClosed) return res.IsClosed; } //Exec remaining RequestFilter attributes with Priority >= 0 @@ -42,10 +36,7 @@ namespace ServiceStack { var attribute = attributes[i]; attribute.RequestFilter(req, res, requestDto); - if (res.IsClosed) return res.IsClosed; } - - return res.IsClosed; } /// @@ -53,21 +44,13 @@ namespace ServiceStack /// and no more processing should be done. /// /// - public virtual bool ApplyResponseFilters(IRequest req, IResponse res, object response) + public virtual void ApplyResponseFilters(IRequest req, IResponse res, object response) { - if (response != null) - { - if (res.IsClosed) return res.IsClosed; - } - //Exec global filters foreach (var responseFilter in GlobalResponseFilters) { responseFilter(req, res, response); - if (res.IsClosed) return res.IsClosed; } - - return res.IsClosed; } } diff --git a/SocketHttpListener.Portable/Net/HttpConnection.cs b/SocketHttpListener.Portable/Net/HttpConnection.cs index 8e472117e..67dd5c958 100644 --- a/SocketHttpListener.Portable/Net/HttpConnection.cs +++ b/SocketHttpListener.Portable/Net/HttpConnection.cs @@ -204,12 +204,12 @@ namespace SocketHttpListener.Net return i_stream; } - public Stream GetResponseStream() + public Stream GetResponseStream(HttpListenerRequest request) { // TODO: can we get this stream before reading the input? if (o_stream == null) { - if (context.Response.SendChunked) + if (context.Response.SendChunked || request == null || request.HasExpect100Continue) { o_stream = new ResponseStream(stream, context.Response, _memoryStreamFactory, _textEncoding); } @@ -490,7 +490,7 @@ namespace SocketHttpListener.Net { if (!context.Request.IsWebSocketRequest || force_close) { - Stream st = GetResponseStream(); + Stream st = GetResponseStream(context.Request); if (st != null) st.Dispose(); diff --git a/SocketHttpListener.Portable/Net/HttpListenerRequest.cs b/SocketHttpListener.Portable/Net/HttpListenerRequest.cs index 5631fc0a1..767f1c542 100644 --- a/SocketHttpListener.Portable/Net/HttpListenerRequest.cs +++ b/SocketHttpListener.Portable/Net/HttpListenerRequest.cs @@ -179,16 +179,21 @@ namespace SocketHttpListener.Net } } - if (String.Compare(Headers["Expect"], "100-continue", StringComparison.OrdinalIgnoreCase) == 0) + if (HasExpect100Continue) { - var output = context.Connection.GetResponseStream(); - + var output = (ResponseStream)context.Connection.GetResponseStream(this); + var _100continue = _textEncoding.GetASCIIEncoding().GetBytes("HTTP/1.1 100 Continue\r\n\r\n"); - //output.InternalWrite(_100continue, 0, _100continue.Length); + output.InternalWrite(_100continue, 0, _100continue.Length); } } + public bool HasExpect100Continue + { + get { return String.Compare(Headers["Expect"], "100-continue", StringComparison.OrdinalIgnoreCase) == 0; } + } + static bool MaybeUri(string s) { int p = s.IndexOf(':'); diff --git a/SocketHttpListener.Portable/Net/HttpListenerResponse.cs b/SocketHttpListener.Portable/Net/HttpListenerResponse.cs index 93358cae4..8c610d725 100644 --- a/SocketHttpListener.Portable/Net/HttpListenerResponse.cs +++ b/SocketHttpListener.Portable/Net/HttpListenerResponse.cs @@ -149,7 +149,7 @@ namespace SocketHttpListener.Net get { if (output_stream == null) - output_stream = context.Connection.GetResponseStream(); + output_stream = context.Connection.GetResponseStream(context.Request); return output_stream; } } @@ -489,7 +489,7 @@ namespace SocketHttpListener.Net int preamble = encoding.GetPreamble().Length; if (output_stream == null) - output_stream = context.Connection.GetResponseStream(); + output_stream = context.Connection.GetResponseStream(context.Request); /* Assumes that the ms was at position 0 */ ms.Position = preamble; -- cgit v1.2.3 From 38c216a61a3dc389d1ddab2a37b4b032a6de13d0 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 12 Nov 2016 19:30:03 -0500 Subject: update response streams --- SocketHttpListener.Portable/Net/HttpConnection.cs | 6 +++--- SocketHttpListener.Portable/Net/HttpListenerRequest.cs | 9 ++------- SocketHttpListener.Portable/Net/HttpListenerResponse.cs | 4 ++-- 3 files changed, 7 insertions(+), 12 deletions(-) (limited to 'SocketHttpListener.Portable/Net/HttpListenerRequest.cs') diff --git a/SocketHttpListener.Portable/Net/HttpConnection.cs b/SocketHttpListener.Portable/Net/HttpConnection.cs index 67dd5c958..d9fd97ed2 100644 --- a/SocketHttpListener.Portable/Net/HttpConnection.cs +++ b/SocketHttpListener.Portable/Net/HttpConnection.cs @@ -204,12 +204,12 @@ namespace SocketHttpListener.Net return i_stream; } - public Stream GetResponseStream(HttpListenerRequest request) + public Stream GetResponseStream(bool isExpect100Continue = false) { // TODO: can we get this stream before reading the input? if (o_stream == null) { - if (context.Response.SendChunked || request == null || request.HasExpect100Continue) + if (context.Response.SendChunked || isExpect100Continue) { o_stream = new ResponseStream(stream, context.Response, _memoryStreamFactory, _textEncoding); } @@ -490,7 +490,7 @@ namespace SocketHttpListener.Net { if (!context.Request.IsWebSocketRequest || force_close) { - Stream st = GetResponseStream(context.Request); + Stream st = GetResponseStream(); if (st != null) st.Dispose(); diff --git a/SocketHttpListener.Portable/Net/HttpListenerRequest.cs b/SocketHttpListener.Portable/Net/HttpListenerRequest.cs index 767f1c542..811cc6ddb 100644 --- a/SocketHttpListener.Portable/Net/HttpListenerRequest.cs +++ b/SocketHttpListener.Portable/Net/HttpListenerRequest.cs @@ -179,9 +179,9 @@ namespace SocketHttpListener.Net } } - if (HasExpect100Continue) + if (String.Compare(Headers["Expect"], "100-continue", StringComparison.OrdinalIgnoreCase) == 0) { - var output = (ResponseStream)context.Connection.GetResponseStream(this); + var output = (ResponseStream)context.Connection.GetResponseStream(true); var _100continue = _textEncoding.GetASCIIEncoding().GetBytes("HTTP/1.1 100 Continue\r\n\r\n"); @@ -189,11 +189,6 @@ namespace SocketHttpListener.Net } } - public bool HasExpect100Continue - { - get { return String.Compare(Headers["Expect"], "100-continue", StringComparison.OrdinalIgnoreCase) == 0; } - } - static bool MaybeUri(string s) { int p = s.IndexOf(':'); diff --git a/SocketHttpListener.Portable/Net/HttpListenerResponse.cs b/SocketHttpListener.Portable/Net/HttpListenerResponse.cs index 8c610d725..93358cae4 100644 --- a/SocketHttpListener.Portable/Net/HttpListenerResponse.cs +++ b/SocketHttpListener.Portable/Net/HttpListenerResponse.cs @@ -149,7 +149,7 @@ namespace SocketHttpListener.Net get { if (output_stream == null) - output_stream = context.Connection.GetResponseStream(context.Request); + output_stream = context.Connection.GetResponseStream(); return output_stream; } } @@ -489,7 +489,7 @@ namespace SocketHttpListener.Net int preamble = encoding.GetPreamble().Length; if (output_stream == null) - output_stream = context.Connection.GetResponseStream(context.Request); + output_stream = context.Connection.GetResponseStream(); /* Assumes that the ms was at position 0 */ ms.Position = preamble; -- cgit v1.2.3