aboutsummaryrefslogtreecommitdiff
path: root/Emby.Server.Implementations/Services
diff options
context:
space:
mode:
Diffstat (limited to 'Emby.Server.Implementations/Services')
-rw-r--r--Emby.Server.Implementations/Services/ServiceController.cs19
-rw-r--r--Emby.Server.Implementations/Services/ServiceExec.cs9
-rw-r--r--Emby.Server.Implementations/Services/ServiceHandler.cs26
-rw-r--r--Emby.Server.Implementations/Services/ServicePath.cs8
-rw-r--r--Emby.Server.Implementations/Services/SwaggerService.cs287
5 files changed, 43 insertions, 306 deletions
diff --git a/Emby.Server.Implementations/Services/ServiceController.cs b/Emby.Server.Implementations/Services/ServiceController.cs
index 857df591a..47e7261e8 100644
--- a/Emby.Server.Implementations/Services/ServiceController.cs
+++ b/Emby.Server.Implementations/Services/ServiceController.cs
@@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
+using System.Globalization;
using System.Threading.Tasks;
using Emby.Server.Implementations.HttpServer;
using MediaBrowser.Model.Services;
@@ -91,12 +92,22 @@ namespace Emby.Server.Implementations.Services
{
if (restPath.Path[0] != '/')
{
- throw new ArgumentException(string.Format("Route '{0}' on '{1}' must start with a '/'", restPath.Path, restPath.RequestType.GetMethodName()));
+ throw new ArgumentException(
+ string.Format(
+ CultureInfo.InvariantCulture,
+ "Route '{0}' on '{1}' must start with a '/'",
+ restPath.Path,
+ restPath.RequestType.GetMethodName()));
}
if (restPath.Path.IndexOfAny(InvalidRouteChars) != -1)
{
- throw new ArgumentException(string.Format("Route '{0}' on '{1}' contains invalid chars. ", restPath.Path, restPath.RequestType.GetMethodName()));
+ throw new ArgumentException(
+ string.Format(
+ CultureInfo.InvariantCulture,
+ "Route '{0}' on '{1}' contains invalid chars. ",
+ restPath.Path,
+ restPath.RequestType.GetMethodName()));
}
if (RestPathMap.TryGetValue(restPath.FirstMatchHashKey, out List<RestPath> pathsAtFirstMatch))
@@ -179,8 +190,7 @@ namespace Emby.Server.Implementations.Services
var service = httpHost.CreateInstance(serviceType);
- var serviceRequiresContext = service as IRequiresRequest;
- if (serviceRequiresContext != null)
+ if (service is IRequiresRequest serviceRequiresContext)
{
serviceRequiresContext.Request = req;
}
@@ -189,5 +199,4 @@ namespace Emby.Server.Implementations.Services
return ServiceExecGeneral.Execute(serviceType, req, service, requestDto, requestType.GetMethodName());
}
}
-
}
diff --git a/Emby.Server.Implementations/Services/ServiceExec.cs b/Emby.Server.Implementations/Services/ServiceExec.cs
index cbc4b754d..7b970627e 100644
--- a/Emby.Server.Implementations/Services/ServiceExec.cs
+++ b/Emby.Server.Implementations/Services/ServiceExec.cs
@@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
+using System.Globalization;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
@@ -105,7 +106,13 @@ namespace Emby.Server.Implementations.Services
}
var expectedMethodName = actionName.Substring(0, 1) + actionName.Substring(1).ToLowerInvariant();
- throw new NotImplementedException(string.Format("Could not find method named {1}({0}) or Any({0}) on Service {2}", requestDto.GetType().GetMethodName(), expectedMethodName, serviceType.GetMethodName()));
+ throw new NotImplementedException(
+ string.Format(
+ CultureInfo.InvariantCulture,
+ "Could not find method named {1}({0}) or Any({0}) on Service {2}",
+ requestDto.GetType().GetMethodName(),
+ expectedMethodName,
+ serviceType.GetMethodName()));
}
private static async Task<object> GetTaskResult(Task task)
diff --git a/Emby.Server.Implementations/Services/ServiceHandler.cs b/Emby.Server.Implementations/Services/ServiceHandler.cs
index a42f88ea0..b4166f771 100644
--- a/Emby.Server.Implementations/Services/ServiceHandler.cs
+++ b/Emby.Server.Implementations/Services/ServiceHandler.cs
@@ -2,10 +2,12 @@
using System;
using System.Collections.Generic;
+using System.Net.Mime;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using Emby.Server.Implementations.HttpServer;
+using MediaBrowser.Common.Extensions;
using MediaBrowser.Model.Services;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
@@ -44,7 +46,7 @@ namespace Emby.Server.Implementations.Services
var pos = pathInfo.LastIndexOf('.');
if (pos != -1)
{
- var format = pathInfo.Substring(pos + 1);
+ var format = pathInfo.AsSpan().Slice(pos + 1);
contentType = GetFormatContentType(format);
if (contentType != null)
{
@@ -55,18 +57,21 @@ namespace Emby.Server.Implementations.Services
return pathInfo;
}
- private static string GetFormatContentType(string format)
+ private static string GetFormatContentType(ReadOnlySpan<char> format)
{
- // built-in formats
- switch (format)
+ if (format.Equals("json", StringComparison.Ordinal))
{
- case "json": return "application/json";
- case "xml": return "application/xml";
- default: return null;
+ return MediaTypeNames.Application.Json;
}
+ else if (format.Equals("xml", StringComparison.Ordinal))
+ {
+ return MediaTypeNames.Application.Xml;
+ }
+
+ return null;
}
- public async Task ProcessRequestAsync(HttpListenerHost httpHost, IRequest httpReq, HttpResponse httpRes, ILogger logger, CancellationToken cancellationToken)
+ public async Task ProcessRequestAsync(HttpListenerHost httpHost, IRequest httpReq, HttpResponse httpRes, CancellationToken cancellationToken)
{
httpReq.Items["__route"] = _restPath;
@@ -75,10 +80,11 @@ namespace Emby.Server.Implementations.Services
httpReq.ResponseContentType = _responseContentType;
}
- var request = await CreateRequest(httpHost, httpReq, _restPath, logger).ConfigureAwait(false);
+ var request = await CreateRequest(httpHost, httpReq, _restPath).ConfigureAwait(false);
httpHost.ApplyRequestFilters(httpReq, httpRes, request);
+ httpRes.HttpContext.SetServiceStackRequest(httpReq);
var response = await httpHost.ServiceController.Execute(httpHost, request, httpReq).ConfigureAwait(false);
// Apply response filters
@@ -90,7 +96,7 @@ namespace Emby.Server.Implementations.Services
await ResponseHelper.WriteToResponse(httpRes, httpReq, response, cancellationToken).ConfigureAwait(false);
}
- public static async Task<object> CreateRequest(HttpListenerHost host, IRequest httpReq, RestPath restPath, ILogger logger)
+ public static async Task<object> CreateRequest(HttpListenerHost host, IRequest httpReq, RestPath restPath)
{
var requestType = restPath.RequestType;
diff --git a/Emby.Server.Implementations/Services/ServicePath.cs b/Emby.Server.Implementations/Services/ServicePath.cs
index 89538ae72..442b2ab1c 100644
--- a/Emby.Server.Implementations/Services/ServicePath.cs
+++ b/Emby.Server.Implementations/Services/ServicePath.cs
@@ -156,7 +156,7 @@ namespace Emby.Server.Implementations.Services
{
var component = components[i];
- if (component.StartsWith(VariablePrefix))
+ if (component.StartsWith(VariablePrefix, StringComparison.Ordinal))
{
var variableName = component.Substring(1, component.Length - 2);
if (variableName[variableName.Length - 1] == WildCardChar)
@@ -488,7 +488,8 @@ namespace Emby.Server.Implementations.Services
sb.Append(value);
for (var j = pathIx + 1; j < requestComponents.Length; j++)
{
- sb.Append(PathSeperatorChar + requestComponents[j]);
+ sb.Append(PathSeperatorChar)
+ .Append(requestComponents[j]);
}
value = sb.ToString();
@@ -505,7 +506,8 @@ namespace Emby.Server.Implementations.Services
pathIx++;
while (!string.Equals(requestComponents[pathIx], stopLiteral, StringComparison.OrdinalIgnoreCase))
{
- sb.Append(PathSeperatorChar + requestComponents[pathIx++]);
+ sb.Append(PathSeperatorChar)
+ .Append(requestComponents[pathIx++]);
}
value = sb.ToString();
diff --git a/Emby.Server.Implementations/Services/SwaggerService.cs b/Emby.Server.Implementations/Services/SwaggerService.cs
deleted file mode 100644
index 4f011a678..000000000
--- a/Emby.Server.Implementations/Services/SwaggerService.cs
+++ /dev/null
@@ -1,287 +0,0 @@
-#pragma warning disable CS1591
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using Emby.Server.Implementations.HttpServer;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Model.Services;
-
-namespace Emby.Server.Implementations.Services
-{
- [Route("/swagger", "GET", Summary = "Gets the swagger specifications")]
- [Route("/swagger.json", "GET", Summary = "Gets the swagger specifications")]
- public class GetSwaggerSpec : IReturn<SwaggerSpec>
- {
- }
-
- public class SwaggerSpec
- {
- public string swagger { get; set; }
-
- public string[] schemes { get; set; }
-
- public SwaggerInfo info { get; set; }
-
- public string host { get; set; }
-
- public string basePath { get; set; }
-
- public SwaggerTag[] tags { get; set; }
-
- public IDictionary<string, Dictionary<string, SwaggerMethod>> paths { get; set; }
-
- public Dictionary<string, SwaggerDefinition> definitions { get; set; }
-
- public SwaggerComponents components { get; set; }
- }
-
- public class SwaggerComponents
- {
- public Dictionary<string, SwaggerSecurityScheme> securitySchemes { get; set; }
- }
-
- public class SwaggerSecurityScheme
- {
- public string name { get; set; }
-
- public string type { get; set; }
-
- public string @in { get; set; }
- }
-
- public class SwaggerInfo
- {
- public string description { get; set; }
-
- public string version { get; set; }
-
- public string title { get; set; }
-
- public string termsOfService { get; set; }
-
- public SwaggerConcactInfo contact { get; set; }
- }
-
- public class SwaggerConcactInfo
- {
- public string email { get; set; }
-
- public string name { get; set; }
-
- public string url { get; set; }
- }
-
- public class SwaggerTag
- {
- public string description { get; set; }
-
- public string name { get; set; }
- }
-
- public class SwaggerMethod
- {
- public string summary { get; set; }
-
- public string description { get; set; }
-
- public string[] tags { get; set; }
-
- public string operationId { get; set; }
-
- public string[] consumes { get; set; }
-
- public string[] produces { get; set; }
-
- public SwaggerParam[] parameters { get; set; }
-
- public Dictionary<string, SwaggerResponse> responses { get; set; }
-
- public Dictionary<string, string[]>[] security { get; set; }
- }
-
- public class SwaggerParam
- {
- public string @in { get; set; }
-
- public string name { get; set; }
-
- public string description { get; set; }
-
- public bool required { get; set; }
-
- public string type { get; set; }
-
- public string collectionFormat { get; set; }
- }
-
- public class SwaggerResponse
- {
- public string description { get; set; }
-
- // ex. "$ref":"#/definitions/Pet"
- public Dictionary<string, string> schema { get; set; }
- }
-
- public class SwaggerDefinition
- {
- public string type { get; set; }
-
- public Dictionary<string, SwaggerProperty> properties { get; set; }
- }
-
- public class SwaggerProperty
- {
- public string type { get; set; }
-
- public string format { get; set; }
-
- public string description { get; set; }
-
- public string[] @enum { get; set; }
-
- public string @default { get; set; }
- }
-
- public class SwaggerService : IService, IRequiresRequest
- {
- private readonly IHttpServer _httpServer;
- private SwaggerSpec _spec;
-
- public IRequest Request { get; set; }
-
- public SwaggerService(IHttpServer httpServer)
- {
- _httpServer = httpServer;
- }
-
- public object Get(GetSwaggerSpec request)
- {
- return _spec ?? (_spec = GetSpec());
- }
-
- private SwaggerSpec GetSpec()
- {
- string host = null;
- Uri uri;
- if (Uri.TryCreate(Request.RawUrl, UriKind.Absolute, out uri))
- {
- host = uri.Host;
- }
-
- var securitySchemes = new Dictionary<string, SwaggerSecurityScheme>();
-
- securitySchemes["api_key"] = new SwaggerSecurityScheme
- {
- name = "api_key",
- type = "apiKey",
- @in = "query"
- };
-
- var spec = new SwaggerSpec
- {
- schemes = new[] { "http" },
- tags = GetTags(),
- swagger = "2.0",
- info = new SwaggerInfo
- {
- title = "Jellyfin Server API",
- version = "1.0.0",
- description = "Explore the Jellyfin Server API",
- contact = new SwaggerConcactInfo
- {
- name = "Jellyfin Community",
- url = "https://jellyfin.readthedocs.io/en/latest/user-docs/getting-help/"
- }
- },
- paths = GetPaths(),
- definitions = GetDefinitions(),
- basePath = "/jellyfin",
- host = host,
-
- components = new SwaggerComponents
- {
- securitySchemes = securitySchemes
- }
- };
-
- return spec;
- }
-
-
- private SwaggerTag[] GetTags()
- {
- return Array.Empty<SwaggerTag>();
- }
-
- private Dictionary<string, SwaggerDefinition> GetDefinitions()
- {
- return new Dictionary<string, SwaggerDefinition>();
- }
-
- private IDictionary<string, Dictionary<string, SwaggerMethod>> GetPaths()
- {
- var paths = new SortedDictionary<string, Dictionary<string, SwaggerMethod>>();
-
- // REVIEW: this can be done better
- var all = ((HttpListenerHost)_httpServer).ServiceController.RestPathMap.OrderBy(i => i.Key, StringComparer.OrdinalIgnoreCase).ToList();
-
- foreach (var current in all)
- {
- foreach (var info in current.Value)
- {
- if (info.IsHidden)
- {
- continue;
- }
-
- if (info.Path.StartsWith("/mediabrowser", StringComparison.OrdinalIgnoreCase)
- || info.Path.StartsWith("/jellyfin", StringComparison.OrdinalIgnoreCase))
- {
- continue;
- }
-
- paths[info.Path] = GetPathInfo(info);
- }
- }
-
- return paths;
- }
-
- private Dictionary<string, SwaggerMethod> GetPathInfo(RestPath info)
- {
- var result = new Dictionary<string, SwaggerMethod>();
-
- foreach (var verb in info.Verbs)
- {
- var responses = new Dictionary<string, SwaggerResponse>
- {
- { "200", new SwaggerResponse { description = "OK" } }
- };
-
- var apiKeySecurity = new Dictionary<string, string[]>
- {
- { "api_key", Array.Empty<string>() }
- };
-
- result[verb.ToLowerInvariant()] = new SwaggerMethod
- {
- summary = info.Summary,
- description = info.Description,
- produces = new[] { "application/json" },
- consumes = new[] { "application/json" },
- operationId = info.RequestType.Name,
- tags = Array.Empty<string>(),
-
- parameters = Array.Empty<SwaggerParam>(),
-
- responses = responses,
-
- security = new[] { apiKeySecurity }
- };
- }
-
- return result;
- }
- }
-}