You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
199 lines
7.5 KiB
199 lines
7.5 KiB
using Apewer.Network;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Reflection;
|
|
using System.Text;
|
|
|
|
namespace Apewer.AspNetBridge
|
|
{
|
|
|
|
[Serializable]
|
|
internal class RouteItem : IToJson
|
|
{
|
|
|
|
public string Path;
|
|
|
|
public string Lower;
|
|
|
|
public Type Controller;
|
|
|
|
public MethodInfo Method;
|
|
|
|
public string MethodName;
|
|
|
|
public bool Connect;
|
|
public bool Delete;
|
|
public bool Get;
|
|
public bool Head;
|
|
public bool Options;
|
|
public bool Patch;
|
|
public bool Post;
|
|
public bool Put;
|
|
public bool Trace;
|
|
|
|
public ParameterInfo[] Parameters;
|
|
|
|
public Type Return;
|
|
|
|
public Json ToJson()
|
|
{
|
|
var ps = Json.NewObject();
|
|
foreach (var parameter in Parameters) ps.SetProperty(parameter.Name, parameter.ParameterType.FullName);
|
|
|
|
var methods = Json.NewArray();
|
|
if (Connect) methods.AddItem("connect");
|
|
if (Delete) methods.AddItem("delete");
|
|
if (Get) methods.AddItem("get");
|
|
if (Head) methods.AddItem("head");
|
|
if (Options) methods.AddItem("options");
|
|
if (Patch) methods.AddItem("patch");
|
|
if (Post) methods.AddItem("post");
|
|
if (Put) methods.AddItem("put");
|
|
if (Trace) methods.AddItem("trace");
|
|
|
|
var json = Json.NewObject();
|
|
json.SetProperty("path", Path);
|
|
json.SetProperty("controller", Controller.FullName);
|
|
json.SetProperty("function", Method.Name);
|
|
json.SetProperty("return", Return.FullName);
|
|
json.SetProperty("parameters", ps);
|
|
json.SetProperty("methods", methods);
|
|
|
|
return json;
|
|
}
|
|
|
|
#region Enumerate
|
|
|
|
internal static RouteItem[] Parse(IEnumerable<Assembly> assemblies, bool withVoid)
|
|
{
|
|
if (assemblies.IsEmpty()) assemblies = AppDomain.CurrentDomain.GetAssemblies();
|
|
var baseType = typeof(ApiController);
|
|
var items = new ArrayBuilder<RouteItem>();
|
|
foreach (var assembly in assemblies)
|
|
{
|
|
var types = assembly.GetExportedTypes();
|
|
foreach (var type in types)
|
|
{
|
|
if (type.IsNotPublic) continue;
|
|
if (!type.IsClass) continue;
|
|
if (!RuntimeUtility.IsInherits(type, baseType)) continue;
|
|
|
|
if (type.Name == "AccountController")
|
|
{
|
|
}
|
|
|
|
var pa = RuntimeUtility.GetAttribute<RoutePrefixAttribute>(type, false);
|
|
var prefix = (pa == null || pa.Path.IsEmpty()) ? null : pa.Path.Split('/');
|
|
|
|
var methods = type.GetMethods(BindingFlags.Public | BindingFlags.Instance);
|
|
foreach (var method in methods)
|
|
{
|
|
if (method.IsConstructor) continue;
|
|
if (method.IsGenericMethod) continue;
|
|
if (!withVoid)
|
|
{
|
|
var returnType = method.ReturnType;
|
|
if (returnType == null || returnType.Equals(typeof(void))) continue;
|
|
}
|
|
|
|
var route = RuntimeUtility.GetAttribute<RouteAttribute>(method);
|
|
if (route == null) continue;
|
|
|
|
var path = route.Path;
|
|
if (path.IsEmpty()) path = method.Name;
|
|
if (path.IsEmpty()) continue;
|
|
path = Concat(prefix, path.Split('/'));
|
|
|
|
var item = new RouteItem();
|
|
item.Controller = type;
|
|
item.Method = method;
|
|
item.MethodName = method.Name;
|
|
item.Parameters = method.GetParameters();
|
|
item.Return = method.ReturnType;
|
|
item.Path = path;
|
|
item.Lower = path.Lower();
|
|
|
|
item.Get = RuntimeUtility.Contains<HttpGetAttribute>(method);
|
|
item.Post = RuntimeUtility.Contains<HttpPostAttribute>(method);
|
|
|
|
item.Connect = RuntimeUtility.Contains<HttpConnectAttribute>(method);
|
|
item.Delete = RuntimeUtility.Contains<HttpDeleteAttribute>(method);
|
|
item.Head = RuntimeUtility.Contains<HttpHeadAttribute>(method);
|
|
item.Options = RuntimeUtility.Contains<HttpOptionsAttribute>(method);
|
|
item.Patch = RuntimeUtility.Contains<HttpPatchAttribute>(method);
|
|
item.Put = RuntimeUtility.Contains<HttpPutAttribute>(method);
|
|
item.Trace = RuntimeUtility.Contains<HttpTraceAttribute>(method);
|
|
|
|
items.Add(item);
|
|
}
|
|
}
|
|
}
|
|
return items.Export();
|
|
}
|
|
|
|
internal static RouteItem Match(RouteItem[] routes, string path, HttpMethod method)
|
|
{
|
|
if (routes == null) return null;
|
|
if (path.IsEmpty()) path = "/";
|
|
|
|
var length = routes.Length;
|
|
for (var i = 0; i < length; i++)
|
|
{
|
|
var route = routes[i];
|
|
if (route == null) continue;
|
|
if (route.Path != path) continue;
|
|
|
|
if (method == HttpMethod.GET && route.Get) return route;
|
|
if (method == HttpMethod.POST && route.Post) return route;
|
|
if (method == HttpMethod.CONNECT && route.Connect) return route;
|
|
if (method == HttpMethod.DELETE && route.Delete) return route;
|
|
if (method == HttpMethod.HEAD && route.Head) return route;
|
|
if (method == HttpMethod.OPTIONS && route.Options) return route;
|
|
if (method == HttpMethod.PATCH && route.Patch) return route;
|
|
if (method == HttpMethod.PUT && route.Put) return route;
|
|
if (method == HttpMethod.TRACE && route.Trace) return route;
|
|
}
|
|
|
|
var lower = path.Lower();
|
|
for (var i = 0; i < length; i++)
|
|
{
|
|
var route = routes[i];
|
|
if (route == null) continue;
|
|
if (route.Lower != lower) continue;
|
|
|
|
if (method == HttpMethod.GET && route.Get) return route;
|
|
if (method == HttpMethod.POST && route.Post) return route;
|
|
if (method == HttpMethod.CONNECT && route.Connect) return route;
|
|
if (method == HttpMethod.DELETE && route.Delete) return route;
|
|
if (method == HttpMethod.HEAD && route.Head) return route;
|
|
if (method == HttpMethod.OPTIONS && route.Options) return route;
|
|
if (method == HttpMethod.PATCH && route.Patch) return route;
|
|
if (method == HttpMethod.PUT && route.Put) return route;
|
|
if (method == HttpMethod.TRACE && route.Trace) return route;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
static string Concat(string[] prefix, string[] path)
|
|
{
|
|
var all = new List<string>(16);
|
|
|
|
if (prefix != null) all.AddRange(prefix);
|
|
if (path != null) all.AddRange(path);
|
|
|
|
var segs = new List<string>(all.Count);
|
|
foreach (var seg in all)
|
|
{
|
|
if (seg.IsEmpty()) continue;
|
|
segs.Add(seg);
|
|
}
|
|
if (segs.Count < 1) return "/";
|
|
return "/" + TextUtility.Join("/", segs.ToArray());
|
|
}
|
|
|
|
#endregion
|
|
|
|
}
|
|
|
|
}
|
|
|