|
|
using Apewer.Network; using Apewer.Source; using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection;
using static Apewer.Internals.ApiHelper;
namespace Apewer.Web {
internal class ApiProcessor {
internal ApiInvoker Invoker; internal ApiEntries Entries; internal ApiProvider Provider; ApiOptions Options;
Stopwatch Stopwatch;
Uri Url; HttpMethod Method; ApiRequest ApiRequest; ApiResponse ApiResponse;
internal ApiProcessor() { }
/// <summary>执行处理程序,返回错误信息。</summary>
public string Run() { if (Options == null) Options = new ApiOptions(); if (Options.WithDuration) { Stopwatch = new Stopwatch(); Stopwatch.Start(); } var error = Flow(); if (Stopwatch != null) { Stopwatch.Stop(); Stopwatch = null; } return error; }
string Flow() { try { // 传入字段。
if (Provider == null) return "服务程序无效。"; if (Invoker == null) return "调用器无效。"; if (Entries == null) return "入口无效。"; Options = Invoker.Options ?? new ApiOptions(); Provider.Options = Options;
// 检查执行的前提条件,获取 Method 和 URL。
var check = Check(); if (!string.IsNullOrEmpty(check)) return check;
// 准备请求和响应模型。
ApiRequest = GetRequest(Provider, Options, Method, Url); ApiResponse = new ApiResponse(); ApiResponse.Random = ApiRequest.Random; ApiResponse.Application = ApiRequest.Application; ApiResponse.Function = ApiRequest.Function;
// 调用 API。
var invoke = Invoke(); if (!string.IsNullOrEmpty(invoke)) return invoke;
// 输出。
if (Stopwatch != null) { Stopwatch.Stop(); ApiResponse.Duration = Stopwatch.ElapsedMilliseconds; Stopwatch = null; } Output(Provider, Options, ApiResponse, ApiRequest, Method); return null; } catch (Exception ex) { if (Stopwatch != null) { Stopwatch.Stop(); Stopwatch = null; } return ex.Message; } }
string Check() { // 服务程序检查。
var check = Provider.PreInvoke(); if (!string.IsNullOrEmpty(check)) return check;
// URL
Url = Provider.GetUrl(); if (Url == null) return "URL 无效。";
Method = Provider.GetMethod(); if (Method == HttpMethod.NULL) return "HTTP 方法无效。"; if (Method == HttpMethod.OPTIONS) return null;
// favicon.ico
var lowerPath = TextUtility.AssureStarts(TextUtility.Lower(Url.AbsolutePath), "/"); if (!Options.AllowFavIcon) { if (lowerPath.StartsWith("/favicon.ico")) { Output(Provider, Options, null, null); return "已取消对 favicon.ico 的请求。"; } }
// robots.txt
if (!Options.AllowRobots) { if (lowerPath.StartsWith("/robots.txt")) { const string text = "User-agent: *\nDisallow: / \n"; Output(Provider, Options, "text/plain", TextUtility.Bytes(text)); return "已取消对 robots.txt 的请求。"; } }
return null; }
// 寻找入口。
string Invoke() { var appName = ApiRequest.Application; var funcName = ApiRequest.Function; var random = ApiRequest.Random;
Invoke(Entries.Get(appName));
if (Stopwatch != null) ApiResponse.Duration = Stopwatch.ElapsedMilliseconds; ApiResponse.Application = appName; ApiResponse.Function = funcName; ApiResponse.Random = random;
return null; }
// 创建控制器。
void Invoke(ApiApplication application) { var request = ApiRequest; var response = ApiResponse; var function = null as ApiFunction; var controller = null as ApiController;
// Application 无效,尝试默认控制器和枚举。
if (application == null) { var @default = Options.Default; if (@default == null) { // 没有指定默认控制器,尝试枚举。
response.Error("Invalid Application"); if (Options.AllowEnumerate) response.Data = Enumerate(Entries.Enumerate(), Options); return; } else { // 创建默认控制器。
try { controller = CreateController(@default, request, response, Options); } catch (Exception ex) { ApiUtility.Exception(response, ex.InnerException); } } } else { // 创建控制器时候会填充 Controller.Request 属性,可能导致 Request.Function 被篡改,所以在创建之前获取 Function。
function = application.Get(request.Function); try { controller = CreateController(application.Type, request, response, Options); } catch (Exception ex) { ApiUtility.Exception(response, ex.InnerException); } } if (controller == null) response.Error("创建控制器实例失败。"); else Invoke(controller, application, function, Options, request, response); RuntimeUtility.Dispose(controller); }
// 调用 Function。
static void Invoke(ApiController controller, ApiApplication application, ApiFunction function, ApiOptions options, ApiRequest request, ApiResponse response) { // 没有 ApiApplication,使用了 Options 中指定的默认控制器。
if (application == null) { application = new ApiApplication(); application.Independent = true; application.Hidden = true; }
try { // 控制器初始化。
var initializer = ApiUtility.GetInitialier(controller); var match = initializer == null ? true : initializer.Invoke(controller); if (!match) return; if (application.Independent) return;
if (function != null) { var result = function.Method.Invoke(controller, ReadParameters(request, function)); if (result == null || function.Returnable == null) return; var returnable = function.Returnable;
// 已明确字符串类型,视为提示错误。
if (returnable.Equals(typeof(string))) { var error = result as string; if (!string.IsNullOrEmpty(error)) response.Error(error); return; }
// 已明确 Exception 类型,视为提示错误。
if (result is Exception) { ApiUtility.Exception(response, result as Exception); return; }
// 已明确 Json 类型。
if (result is Json) { response.Data = result as Json; return; }
// 已明确 Model 类型。
if (result is ApiModel) { response.Model = result as ApiModel; return; }
// 类型未知,尝试 ToJson 方法。
var tojson = result as IToJson; if (tojson != null) { response.Data = tojson.ToJson(); return; }
// 类型未知,尝试 Record 模型。
var record = result as IRecord; if (record != null) { response.Data = Json.From(record); return; }
// 未知类型,尝试 Json 类型。
var json = result as Json; if (json != null) { response.Data = json; return; }
// 未知返回类型,无法明确输出格式,忽略。
} else { // 未匹配到 Function,尝试 Default。
var @default = ApiUtility.GetDefault(controller); if (@default != null) { @default.Invoke(controller); return; }
// 没有执行任何 Function,尝试枚举。
if (application.Hidden) { response.Error("Invalid Application"); } else { response.Error("Invalid Function"); if (options.AllowEnumerate) response.Data = Enumerate(application.Items, options); } } } catch (Exception exception) { if (exception == null) response.Error("发生了未定义的异常。"); else ApiUtility.Exception(response, exception); } }
static ApiController CreateController(Type type, ApiRequest request, ApiResponse response, ApiOptions options) { var controller = (ApiController)Activator.CreateInstance(type); ApiUtility.SetProperties(controller, request, response, options); return controller; }
}
}
|