mirror of
				https://github.com/jellyfin/jellyfin.git
				synced 2025-10-31 00:01:12 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			201 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			201 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using System;
 | |
| using System.Collections.Generic;
 | |
| using System.Runtime.Serialization;
 | |
| using System.Threading.Tasks;
 | |
| using MediaBrowser.Model.Services;
 | |
| 
 | |
| namespace ServiceStack.Host
 | |
| {
 | |
|     public class RestHandler
 | |
|     {
 | |
|         public string RequestName { get; set; }
 | |
| 
 | |
|         public async Task<object> HandleResponseAsync(object response)
 | |
|         {
 | |
|             var taskResponse = response as Task;
 | |
| 
 | |
|             if (taskResponse == null)
 | |
|             {
 | |
|                 return response;
 | |
|             }
 | |
| 
 | |
|             await taskResponse.ConfigureAwait(false);
 | |
| 
 | |
|             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)
 | |
|             {
 | |
|                 return new object[] { };
 | |
|             }
 | |
| 
 | |
|             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;
 | |
|         }
 | |
| 
 | |
|         protected static object CreateContentTypeRequest(IRequest httpReq, Type requestType, string contentType)
 | |
|         {
 | |
|             if (!string.IsNullOrEmpty(contentType) && httpReq.ContentLength > 0)
 | |
|             {
 | |
|                 var deserializer = ContentTypes.Instance.GetStreamDeserializer(contentType);
 | |
|                 if (deserializer != null)
 | |
|                 {
 | |
|                     return deserializer(requestType, httpReq.InputStream);
 | |
|                 }
 | |
|             }
 | |
|             return ServiceStackHost.Instance.CreateInstance(requestType); //Return an empty DTO, even for empty request bodies
 | |
|         }
 | |
| 
 | |
|         protected static object GetCustomRequestFromBinder(IRequest httpReq, Type requestType)
 | |
|         {
 | |
|             Func<IRequest, object> requestFactoryFn;
 | |
|             ServiceStackHost.Instance.ServiceController.RequestTypeFactoryMap.TryGetValue(
 | |
|                 requestType, out requestFactoryFn);
 | |
| 
 | |
|             return requestFactoryFn != null ? requestFactoryFn(httpReq) : null;
 | |
|         }
 | |
| 
 | |
|         public static RestPath FindMatchingRestPath(string httpMethod, string pathInfo, out string contentType)
 | |
|         {
 | |
|             pathInfo = GetSanitizedPathInfo(pathInfo, out contentType);
 | |
| 
 | |
|             return ServiceStackHost.Instance.ServiceController.GetRestPathForRequest(httpMethod, pathInfo);
 | |
|         }
 | |
| 
 | |
|         public static string GetSanitizedPathInfo(string pathInfo, out string contentType)
 | |
|         {
 | |
|             contentType = null;
 | |
|             var pos = pathInfo.LastIndexOf('.');
 | |
|             if (pos >= 0)
 | |
|             {
 | |
|                 var format = pathInfo.Substring(pos + 1);
 | |
|                 contentType = GetFormatContentType(format);
 | |
|                 if (contentType != null)
 | |
|                 {
 | |
|                     pathInfo = pathInfo.Substring(0, pos);
 | |
|                 }
 | |
|             }
 | |
|             return pathInfo;
 | |
|         }
 | |
| 
 | |
|         private static string GetFormatContentType(string format)
 | |
|         {
 | |
|             //built-in formats
 | |
|             if (format == "json")
 | |
|                 return "application/json";
 | |
|             if (format == "xml")
 | |
|                 return "application/xml";
 | |
| 
 | |
|             return null;
 | |
|         }
 | |
| 
 | |
|         public RestPath GetRestPath(string httpMethod, string pathInfo)
 | |
|         {
 | |
|             if (this.RestPath == null)
 | |
|             {
 | |
|                 string contentType;
 | |
|                 this.RestPath = FindMatchingRestPath(httpMethod, pathInfo, out contentType);
 | |
| 
 | |
|                 if (contentType != null)
 | |
|                     ResponseContentType = contentType;
 | |
|             }
 | |
|             return this.RestPath;
 | |
|         }
 | |
| 
 | |
|         public RestPath RestPath { get; set; }
 | |
| 
 | |
|         // Set from SSHHF.GetHandlerForPathInfo()
 | |
|         public string ResponseContentType { get; set; }
 | |
| 
 | |
|         public async Task ProcessRequestAsync(IRequest httpReq, IResponse httpRes, string operationName)
 | |
|         {
 | |
|             var appHost = ServiceStackHost.Instance;
 | |
| 
 | |
|             var restPath = GetRestPath(httpReq.Verb, httpReq.PathInfo);
 | |
|             if (restPath == null)
 | |
|             {
 | |
|                 throw new NotSupportedException("No RestPath found for: " + httpReq.Verb + " " + httpReq.PathInfo);
 | |
|             }
 | |
|             httpReq.SetRoute(restPath);
 | |
| 
 | |
|             if (ResponseContentType != null)
 | |
|                 httpReq.ResponseContentType = ResponseContentType;
 | |
| 
 | |
|             var request = httpReq.Dto = CreateRequest(httpReq, restPath);
 | |
| 
 | |
|             if (appHost.ApplyRequestFilters(httpReq, httpRes, request))
 | |
|                 return;
 | |
| 
 | |
|             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;
 | |
| 
 | |
|             await httpRes.WriteToResponse(httpReq, response).ConfigureAwait(false);
 | |
|         }
 | |
| 
 | |
|         public static object CreateRequest(IRequest httpReq, RestPath restPath)
 | |
|         {
 | |
|             var dtoFromBinder = GetCustomRequestFromBinder(httpReq, restPath.RequestType);
 | |
|             if (dtoFromBinder != null)
 | |
|                 return dtoFromBinder;
 | |
| 
 | |
|             var requestParams = httpReq.GetFlattenedRequestParams();
 | |
|             return CreateRequest(httpReq, restPath, requestParams);
 | |
|         }
 | |
| 
 | |
|         public static object CreateRequest(IRequest httpReq, RestPath restPath, Dictionary<string, string> requestParams)
 | |
|         {
 | |
|             var requestDto = CreateContentTypeRequest(httpReq, restPath.RequestType, httpReq.ContentType);
 | |
| 
 | |
|             return CreateRequest(httpReq, restPath, requestParams, requestDto);
 | |
|         }
 | |
| 
 | |
|         public static object CreateRequest(IRequest httpReq, RestPath restPath, Dictionary<string, string> requestParams, object requestDto)
 | |
|         {
 | |
|             string contentType;
 | |
|             var pathInfo = !restPath.IsWildCardPath
 | |
|                 ? GetSanitizedPathInfo(httpReq.PathInfo, out contentType)
 | |
|                 : httpReq.PathInfo;
 | |
| 
 | |
|             return restPath.CreateRequest(pathInfo, requestParams, requestDto);
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Used in Unit tests
 | |
|         /// </summary>
 | |
|         /// <returns></returns>
 | |
|         public object CreateRequest(IRequest httpReq, string operationName)
 | |
|         {
 | |
|             if (this.RestPath == null)
 | |
|                 throw new ArgumentNullException("No RestPath found");
 | |
| 
 | |
|             return CreateRequest(httpReq, this.RestPath);
 | |
|         }
 | |
|     }
 | |
| 
 | |
| }
 |