update service creation

This commit is contained in:
Luke Pulverenti 2017-09-03 03:28:58 -04:00
parent e0c1d740a3
commit 2084678266
10 changed files with 78 additions and 69 deletions

View File

@ -182,6 +182,8 @@ namespace Emby.Server.Implementations.HttpServer
private IHttpListener GetListener() private IHttpListener GetListener()
{ {
//return new KestrelHost.KestrelListener(_logger, _environment, _fileSystem);
return new WebSocketSharpListener(_logger, return new WebSocketSharpListener(_logger,
_certificate, _certificate,
_memoryStreamProvider, _memoryStreamProvider,
@ -306,7 +308,8 @@ namespace Emby.Server.Implementations.HttpServer
if (_listener != null) if (_listener != null)
{ {
_logger.Info("Stopping HttpListener..."); _logger.Info("Stopping HttpListener...");
_listener.Stop(); var task = _listener.Stop();
Task.WaitAll(task);
_logger.Info("HttpListener stopped"); _logger.Info("HttpListener stopped");
} }
} }
@ -392,7 +395,7 @@ namespace Emby.Server.Implementations.HttpServer
return address.Trim('/'); return address.Trim('/');
} }
private bool ValidateHost(Uri url) private bool ValidateHost(string host)
{ {
var hosts = _config var hosts = _config
.Configuration .Configuration
@ -405,7 +408,7 @@ namespace Emby.Server.Implementations.HttpServer
return true; return true;
} }
var host = url.Host ?? string.Empty; host = host ?? string.Empty;
_logger.Debug("Validating host {0}", host); _logger.Debug("Validating host {0}", host);
@ -423,7 +426,7 @@ namespace Emby.Server.Implementations.HttpServer
/// <summary> /// <summary>
/// Overridable method that can be used to implement a custom hnandler /// Overridable method that can be used to implement a custom hnandler
/// </summary> /// </summary>
protected async Task RequestHandler(IHttpRequest httpReq, Uri url, CancellationToken cancellationToken) protected async Task RequestHandler(IHttpRequest httpReq, string urlString, string host, string localPath, CancellationToken cancellationToken)
{ {
var date = DateTime.Now; var date = DateTime.Now;
var httpRes = httpReq.Response; var httpRes = httpReq.Response;
@ -442,7 +445,7 @@ namespace Emby.Server.Implementations.HttpServer
return; return;
} }
if (!ValidateHost(url)) if (!ValidateHost(host))
{ {
httpRes.StatusCode = 400; httpRes.StatusCode = 400;
httpRes.ContentType = "text/plain"; httpRes.ContentType = "text/plain";
@ -462,9 +465,7 @@ namespace Emby.Server.Implementations.HttpServer
} }
var operationName = httpReq.OperationName; var operationName = httpReq.OperationName;
var localPath = url.LocalPath;
var urlString = url.OriginalString;
enableLog = EnableLogging(urlString, localPath); enableLog = EnableLogging(urlString, localPath);
urlToLog = urlString; urlToLog = urlString;
logHeaders = enableLog && urlToLog.IndexOf("/videos/", StringComparison.OrdinalIgnoreCase) != -1; logHeaders = enableLog && urlToLog.IndexOf("/videos/", StringComparison.OrdinalIgnoreCase) != -1;

View File

@ -19,7 +19,7 @@ namespace Emby.Server.Implementations.HttpServer
/// Gets or sets the request handler. /// Gets or sets the request handler.
/// </summary> /// </summary>
/// <value>The request handler.</value> /// <value>The request handler.</value>
Func<IHttpRequest, Uri, CancellationToken, Task> RequestHandler { get; set; } Func<IHttpRequest, string, string, string, CancellationToken, Task> RequestHandler { get; set; }
/// <summary> /// <summary>
/// Gets or sets the web socket handler. /// Gets or sets the web socket handler.
@ -42,6 +42,6 @@ namespace Emby.Server.Implementations.HttpServer
/// <summary> /// <summary>
/// Stops this instance. /// Stops this instance.
/// </summary> /// </summary>
void Stop(); Task Stop();
} }
} }

View File

@ -53,7 +53,7 @@ namespace Emby.Server.Implementations.HttpServer.SocketSharp
} }
public Action<Exception, IRequest, bool> ErrorHandler { get; set; } public Action<Exception, IRequest, bool> ErrorHandler { get; set; }
public Func<IHttpRequest, Uri, CancellationToken, Task> RequestHandler { get; set; } public Func<IHttpRequest, string, string, string, CancellationToken, Task> RequestHandler { get; set; }
public Action<WebSocketConnectingEventArgs> WebSocketConnecting { get; set; } public Action<WebSocketConnectingEventArgs> WebSocketConnecting { get; set; }
@ -114,7 +114,9 @@ namespace Emby.Server.Implementations.HttpServer.SocketSharp
return Task.FromResult(true); return Task.FromResult(true);
} }
return RequestHandler(httpReq, request.Url, cancellationToken); var uri = request.Url;
return RequestHandler(httpReq, uri.OriginalString, uri.Host, uri.LocalPath, cancellationToken);
} }
private void ProcessWebSocketRequest(HttpListenerContext ctx) private void ProcessWebSocketRequest(HttpListenerContext ctx)
@ -177,7 +179,7 @@ namespace Emby.Server.Implementations.HttpServer.SocketSharp
return req; return req;
} }
public void Stop() public Task Stop()
{ {
_disposeCancellationTokenSource.Cancel(); _disposeCancellationTokenSource.Cancel();
@ -190,6 +192,8 @@ namespace Emby.Server.Implementations.HttpServer.SocketSharp
_listener.Close(); _listener.Close();
} }
return Task.FromResult(true);
} }
public void Dispose() public void Dispose()

View File

@ -246,13 +246,12 @@ namespace Emby.Server.Implementations.HttpServer.SocketSharp
set set
{ {
this.responseContentType = value; this.responseContentType = value;
HasExplicitResponseContentType = true;
} }
} }
public const string FormUrlEncoded = "application/x-www-form-urlencoded"; public const string FormUrlEncoded = "application/x-www-form-urlencoded";
public const string MultiPartFormData = "multipart/form-data"; public const string MultiPartFormData = "multipart/form-data";
private static string GetResponseContentType(IRequest httpReq) public static string GetResponseContentType(IRequest httpReq)
{ {
var specifiedContentType = GetQueryStringContentType(httpReq); var specifiedContentType = GetQueryStringContentType(httpReq);
if (!string.IsNullOrEmpty(specifiedContentType)) return specifiedContentType; if (!string.IsNullOrEmpty(specifiedContentType)) return specifiedContentType;
@ -360,8 +359,6 @@ namespace Emby.Server.Implementations.HttpServer.SocketSharp
: strVal.Substring(0, pos); : strVal.Substring(0, pos);
} }
public bool HasExplicitResponseContentType { get; private set; }
public static string HandlerFactoryPath; public static string HandlerFactoryPath;
private string pathInfo; private string pathInfo;
@ -504,13 +501,6 @@ namespace Emby.Server.Implementations.HttpServer.SocketSharp
get { return HttpMethod; } get { return HttpMethod; }
} }
public string Param(string name)
{
return Headers[name]
?? QueryString[name]
?? FormData[name];
}
public string ContentType public string ContentType
{ {
get { return request.ContentType; } get { return request.ContentType; }

View File

@ -29,7 +29,6 @@ namespace Emby.Server.Implementations.HttpServer.SocketSharp
} }
public IRequest Request { get; private set; } public IRequest Request { get; private set; }
public bool UseBufferedStream { get; set; }
public Dictionary<string, object> Items { get; private set; } public Dictionary<string, object> Items { get; private set; }
public object OriginalResponse public object OriginalResponse
{ {

View File

@ -45,10 +45,15 @@ namespace Emby.Server.Implementations.Services
var bytesResponse = this.Response as byte[]; var bytesResponse = this.Response as byte[];
if (bytesResponse != null) if (bytesResponse != null)
{ {
if (response != null) var contentLength = bytesResponse.Length;
response.SetContentLength(bytesResponse.Length);
await responseStream.WriteAsync(bytesResponse, 0, bytesResponse.Length).ConfigureAwait(false); if (response != null)
response.SetContentLength(contentLength);
if (contentLength > 0)
{
await responseStream.WriteAsync(bytesResponse, 0, contentLength).ConfigureAwait(false);
}
return; return;
} }

View File

@ -41,11 +41,11 @@ namespace Emby.Server.Implementations.Services
response.StatusCode = httpResult.Status; response.StatusCode = httpResult.Status;
response.StatusDescription = httpResult.StatusCode.ToString(); response.StatusDescription = httpResult.StatusCode.ToString();
if (string.IsNullOrEmpty(httpResult.ContentType)) //if (string.IsNullOrEmpty(httpResult.ContentType))
{ //{
httpResult.ContentType = defaultContentType; // httpResult.ContentType = defaultContentType;
} //}
response.ContentType = httpResult.ContentType; //response.ContentType = httpResult.ContentType;
if (httpResult.Cookies != null) if (httpResult.Cookies != null)
{ {
@ -124,7 +124,10 @@ namespace Emby.Server.Implementations.Services
response.ContentType = "application/octet-stream"; response.ContentType = "application/octet-stream";
response.SetContentLength(bytes.Length); response.SetContentLength(bytes.Length);
await response.OutputStream.WriteAsync(bytes, 0, bytes.Length, cancellationToken).ConfigureAwait(false); if (bytes.Length > 0)
{
await response.OutputStream.WriteAsync(bytes, 0, bytes.Length, cancellationToken).ConfigureAwait(false);
}
return; return;
} }
@ -133,7 +136,10 @@ namespace Emby.Server.Implementations.Services
{ {
bytes = Encoding.UTF8.GetBytes(responseText); bytes = Encoding.UTF8.GetBytes(responseText);
response.SetContentLength(bytes.Length); response.SetContentLength(bytes.Length);
await response.OutputStream.WriteAsync(bytes, 0, bytes.Length, cancellationToken).ConfigureAwait(false); if (bytes.Length > 0)
{
await response.OutputStream.WriteAsync(bytes, 0, bytes.Length, cancellationToken).ConfigureAwait(false);
}
return; return;
} }
@ -150,8 +156,15 @@ namespace Emby.Server.Implementations.Services
serializer(result, ms); serializer(result, ms);
ms.Position = 0; ms.Position = 0;
response.SetContentLength(ms.Length);
await ms.CopyToAsync(response.OutputStream).ConfigureAwait(false); var contentLength = ms.Length;
response.SetContentLength(contentLength);
if (contentLength > 0)
{
await ms.CopyToAsync(response.OutputStream).ConfigureAwait(false);
}
} }
//serializer(result, outputStream); //serializer(result, outputStream);

View File

@ -162,7 +162,11 @@ namespace Emby.Server.Implementations.Services
if (RequireqRequestStream(requestType)) if (RequireqRequestStream(requestType))
{ {
// Used by IRequiresRequestStream // Used by IRequiresRequestStream
return CreateRequiresRequestStreamRequest(host, httpReq, requestType); var request = ServiceHandler.CreateRequest(httpReq, restPath, GetRequestParams(httpReq), host.CreateInstance(requestType));
var rawReq = (IRequiresRequestStream)request;
rawReq.RequestStream = httpReq.InputStream;
return rawReq;
} }
var requestParams = GetFlattenedRequestParams(httpReq); var requestParams = GetFlattenedRequestParams(httpReq);
@ -176,16 +180,6 @@ namespace Emby.Server.Implementations.Services
return requiresRequestStreamTypeInfo.IsAssignableFrom(requestType.GetTypeInfo()); return requiresRequestStreamTypeInfo.IsAssignableFrom(requestType.GetTypeInfo());
} }
private static IRequiresRequestStream CreateRequiresRequestStreamRequest(HttpListenerHost host, IRequest req, Type requestType)
{
var restPath = GetRoute(req);
var request = ServiceHandler.CreateRequest(req, restPath, GetRequestParams(req), host.CreateInstance(requestType));
var rawReq = (IRequiresRequestStream)request;
rawReq.RequestStream = req.InputStream;
return rawReq;
}
public static object CreateRequest(HttpListenerHost host, IRequest httpReq, RestPath restPath, Dictionary<string, string> requestParams) public static object CreateRequest(HttpListenerHost host, IRequest httpReq, RestPath restPath, Dictionary<string, string> requestParams)
{ {
var requestDto = CreateContentTypeRequest(host, httpReq, restPath.RequestType, httpReq.ContentType); var requestDto = CreateContentTypeRequest(host, httpReq, restPath.RequestType, httpReq.ContentType);
@ -228,22 +222,26 @@ namespace Emby.Server.Implementations.Services
} }
} }
if ((IsMethod(request.Verb, "POST") || IsMethod(request.Verb, "PUT")) && request.FormData != null) if ((IsMethod(request.Verb, "POST") || IsMethod(request.Verb, "PUT")))
{ {
foreach (var name in request.FormData.Keys) var formData = request.FormData;
if (formData != null)
{ {
if (name == null) continue; //thank you ASP.NET foreach (var name in formData.Keys)
{
if (name == null) continue; //thank you ASP.NET
var values = request.FormData.GetValues(name); var values = formData.GetValues(name);
if (values.Count == 1) if (values.Count == 1)
{
map[name] = values[0];
}
else
{
for (var i = 0; i < values.Count; i++)
{ {
map[name + (i == 0 ? "" : "#" + i)] = values[i]; map[name] = values[0];
}
else
{
for (var i = 0; i < values.Count; i++)
{
map[name + (i == 0 ? "" : "#" + i)] = values[i];
}
} }
} }
} }
@ -270,12 +268,16 @@ namespace Emby.Server.Implementations.Services
map[name] = request.QueryString[name]; map[name] = request.QueryString[name];
} }
if ((IsMethod(request.Verb, "POST") || IsMethod(request.Verb, "PUT")) && request.FormData != null) if ((IsMethod(request.Verb, "POST") || IsMethod(request.Verb, "PUT")))
{ {
foreach (var name in request.FormData.Keys) var formData = request.FormData;
if (formData != null)
{ {
if (name == null) continue; //thank you ASP.NET foreach (var name in formData.Keys)
map[name] = request.FormData[name]; {
if (name == null) continue; //thank you ASP.NET
map[name] = formData[name];
}
} }
} }

View File

@ -48,11 +48,6 @@ namespace MediaBrowser.Model.Services
/// </summary> /// </summary>
string ResponseContentType { get; set; } string ResponseContentType { get; set; }
/// <summary>
/// Whether the ResponseContentType has been explicitly overrided or whether it was just the default
/// </summary>
bool HasExplicitResponseContentType { get; }
/// <summary> /// <summary>
/// Attach any data to this request that all filters and services can access. /// Attach any data to this request that all filters and services can access.
/// </summary> /// </summary>

View File

@ -1,3 +1,3 @@
using System.Reflection; using System.Reflection;
[assembly: AssemblyVersion("3.2.30.5")] [assembly: AssemblyVersion("3.2.30.6")]