2
0

ServiceController.cs 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Threading.Tasks;
  4. using Emby.Server.Implementations.HttpServer;
  5. using MediaBrowser.Model.Services;
  6. namespace Emby.Server.Implementations.Services
  7. {
  8. public delegate object ActionInvokerFn(object intance, object request);
  9. public delegate void VoidActionInvokerFn(object intance, object request);
  10. public class ServiceController
  11. {
  12. public void Init(HttpListenerHost appHost, IEnumerable<Type> serviceTypes)
  13. {
  14. foreach (var serviceType in serviceTypes)
  15. {
  16. RegisterService(appHost, serviceType);
  17. }
  18. }
  19. public void RegisterService(HttpListenerHost appHost, Type serviceType)
  20. {
  21. var processedReqs = new HashSet<Type>();
  22. var actions = ServiceExecGeneral.Reset(serviceType);
  23. foreach (var mi in serviceType.GetActions())
  24. {
  25. var requestType = mi.GetParameters()[0].ParameterType;
  26. if (processedReqs.Contains(requestType))
  27. {
  28. continue;
  29. }
  30. processedReqs.Add(requestType);
  31. ServiceExecGeneral.CreateServiceRunnersFor(requestType, actions);
  32. //var returnMarker = GetTypeWithGenericTypeDefinitionOf(requestType, typeof(IReturn<>));
  33. //var responseType = returnMarker != null ?
  34. // GetGenericArguments(returnMarker)[0]
  35. // : mi.ReturnType != typeof(object) && mi.ReturnType != typeof(void) ?
  36. // mi.ReturnType
  37. // : Type.GetType(requestType.FullName + "Response");
  38. RegisterRestPaths(appHost, requestType, serviceType);
  39. appHost.AddServiceInfo(serviceType, requestType);
  40. }
  41. }
  42. public readonly RestPath.RestPathMap RestPathMap = new RestPath.RestPathMap();
  43. public void RegisterRestPaths(HttpListenerHost appHost, Type requestType, Type serviceType)
  44. {
  45. var attrs = appHost.GetRouteAttributes(requestType);
  46. foreach (var attr in attrs)
  47. {
  48. var restPath = new RestPath(appHost.CreateInstance, appHost.GetParseFn, requestType, serviceType, attr.Path, attr.Verbs, attr.IsHidden, attr.Summary, attr.Description);
  49. RegisterRestPath(restPath);
  50. }
  51. }
  52. private static readonly char[] InvalidRouteChars = new[] { '?', '&' };
  53. public void RegisterRestPath(RestPath restPath)
  54. {
  55. if (restPath.Path[0] != '/')
  56. {
  57. throw new ArgumentException(string.Format("Route '{0}' on '{1}' must start with a '/'", restPath.Path, restPath.RequestType.GetMethodName()));
  58. }
  59. if (restPath.Path.IndexOfAny(InvalidRouteChars) != -1)
  60. {
  61. throw new ArgumentException(string.Format("Route '{0}' on '{1}' contains invalid chars. ", restPath.Path, restPath.RequestType.GetMethodName()));
  62. }
  63. if (RestPathMap.TryGetValue(restPath.FirstMatchHashKey, out List<RestPath> pathsAtFirstMatch))
  64. {
  65. pathsAtFirstMatch.Add(restPath);
  66. }
  67. else
  68. {
  69. RestPathMap[restPath.FirstMatchHashKey] = new List<RestPath>() { restPath };
  70. }
  71. }
  72. public RestPath GetRestPathForRequest(string httpMethod, string pathInfo)
  73. {
  74. var matchUsingPathParts = RestPath.GetPathPartsForMatching(pathInfo);
  75. List<RestPath> firstMatches;
  76. var yieldedHashMatches = RestPath.GetFirstMatchHashKeys(matchUsingPathParts);
  77. foreach (var potentialHashMatch in yieldedHashMatches)
  78. {
  79. if (!this.RestPathMap.TryGetValue(potentialHashMatch, out firstMatches))
  80. {
  81. continue;
  82. }
  83. var bestScore = -1;
  84. RestPath bestMatch = null;
  85. foreach (var restPath in firstMatches)
  86. {
  87. var score = restPath.MatchScore(httpMethod, matchUsingPathParts);
  88. if (score > bestScore)
  89. {
  90. bestScore = score;
  91. bestMatch = restPath;
  92. }
  93. }
  94. if (bestScore > 0 && bestMatch != null)
  95. {
  96. return bestMatch;
  97. }
  98. }
  99. var yieldedWildcardMatches = RestPath.GetFirstMatchWildCardHashKeys(matchUsingPathParts);
  100. foreach (var potentialHashMatch in yieldedWildcardMatches)
  101. {
  102. if (!this.RestPathMap.TryGetValue(potentialHashMatch, out firstMatches)) continue;
  103. var bestScore = -1;
  104. RestPath bestMatch = null;
  105. foreach (var restPath in firstMatches)
  106. {
  107. var score = restPath.MatchScore(httpMethod, matchUsingPathParts);
  108. if (score > bestScore)
  109. {
  110. bestScore = score;
  111. bestMatch = restPath;
  112. }
  113. }
  114. if (bestScore > 0 && bestMatch != null)
  115. {
  116. return bestMatch;
  117. }
  118. }
  119. return null;
  120. }
  121. public Task<object> Execute(HttpListenerHost httpHost, object requestDto, IRequest req)
  122. {
  123. var requestType = requestDto.GetType();
  124. req.OperationName = requestType.Name;
  125. var serviceType = httpHost.GetServiceTypeByRequest(requestType);
  126. var service = httpHost.CreateInstance(serviceType);
  127. var serviceRequiresContext = service as IRequiresRequest;
  128. if (serviceRequiresContext != null)
  129. {
  130. serviceRequiresContext.Request = req;
  131. }
  132. //Executes the service and returns the result
  133. return ServiceExecGeneral.Execute(serviceType, req, service, requestDto, requestType.GetMethodName());
  134. }
  135. }
  136. }