Skip to content

Commit

Permalink
Router with delegate
Browse files Browse the repository at this point in the history
  • Loading branch information
HeHang0 committed Nov 7, 2023
1 parent 74d0e69 commit 23fce74
Show file tree
Hide file tree
Showing 7 changed files with 143 additions and 102 deletions.
23 changes: 10 additions & 13 deletions windows/Audio/AudioTag.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,19 +44,16 @@ public static AudioTag ReadTag(string audioFile, bool picture=false)
AudioTag audioTag = new AudioTag(audioFile);
try
{
#if DEBUG
#else
//TagLib.File tagFile = TagLib.File.Create(audioFile);
//audioTag.Name = tagFile.Tag.Title;
//audioTag.Singer = tagFile.Tag.JoinedAlbumArtists;
//audioTag.Album = tagFile.Tag.Album;
//audioTag.Length = (int)Math.Floor(tagFile.Properties.Duration.TotalMilliseconds);
//audioTag.Duration = tagFile.Properties.Duration.ToString("mm\\:ss");
//if (picture && tagFile.Tag.Pictures.Length > 0)
//{
// audioTag.SetPicture(tagFile.Tag.Pictures[0].Data.Data, tagFile.Tag.Pictures[0].MimeType);
//}
#endif
TagLib.File tagFile = TagLib.File.Create(audioFile);
audioTag.Name = tagFile.Tag.Title;
audioTag.Singer = tagFile.Tag.JoinedAlbumArtists;
audioTag.Album = tagFile.Tag.Album;
audioTag.Length = (int)Math.Floor(tagFile.Properties.Duration.TotalMilliseconds);
audioTag.Duration = tagFile.Properties.Duration.ToString("mm\\:ss");
if (picture && tagFile.Tag.Pictures.Length > 0)
{
audioTag.SetPicture(tagFile.Tag.Pictures[0].Data.Data, tagFile.Tag.Pictures[0].MimeType);
}
}
catch (Exception ex)
{
Expand Down
46 changes: 28 additions & 18 deletions windows/Server/HttpHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
Expand All @@ -13,17 +12,19 @@ namespace Musiche.Server
{
public class HttpHandler : Handler, IHandler
{
private readonly Dictionary<string, MethodInfo> routers = new Dictionary<string, MethodInfo>();
private readonly HashSet<string> installChineseFonts = new HashSet<string>();
private readonly Dictionary<string, Func<HttpListenerContext, Task>> routers;
private static readonly string installChineseFontsJson = string.Empty;
private readonly FileHandler fileHandler = new FileHandler();
public HttpHandler(MainWindow window, AudioPlay audioPlay) : base(window, audioPlay)
{
InitFonts();
routers = Utils.ReadRouter(this);
routers = Router.ReadHttpRouter(this);
}

private void InitFonts()
static HttpHandler()
{
ServicePointManager.ServerCertificateValidationCallback +=
(sender, certificate, chain, sslPolicyErrors) => true;
HashSet<string> installChineseFonts = new HashSet<string>();
foreach (var family in System.Windows.Media.Fonts.SystemFontFamilies)
{
foreach (var keyPair in family.FamilyNames)
Expand All @@ -35,12 +36,7 @@ private void InitFonts()
}
}
}
}

static HttpHandler()
{
ServicePointManager.ServerCertificateValidationCallback +=
(sender, certificate, chain, sslPolicyErrors) => true;
installChineseFontsJson = JsonConvert.SerializeObject(installChineseFonts);
}

[Router("*")]
Expand All @@ -61,6 +57,13 @@ public async Task ClipboardIndex(HttpListenerContext ctx)
}
}

[Router("/version")]
public async Task GetVersion(HttpListenerContext ctx)
{
byte[] data = fileHandler.GetFile("version");
await SendString(ctx, data != null ? Encoding.UTF8.GetString(data) : Utils.App.Version);
}

[Router("/title")]
public async Task SetTitle(HttpListenerContext ctx)
{
Expand Down Expand Up @@ -235,7 +238,7 @@ public async Task SetHide(HttpListenerContext ctx)
[Router("/fonts")]
public async Task InstalledFonts(HttpListenerContext ctx)
{
await SendString(ctx, JsonConvert.SerializeObject(installChineseFonts), "text/json");
await SendString(ctx, installChineseFontsJson, "text/json");
}

[Router("/image")]
Expand Down Expand Up @@ -466,20 +469,27 @@ public async Task Handle(HttpListenerContext context)
return;
}
string router = context.Request.Url?.LocalPath.TrimEnd('/') ?? "*";
routers.TryGetValue(router.ToUpper(), out MethodInfo methodInfo);
if (methodInfo == null)
routers.TryGetValue(router.ToUpper(), out Func<HttpListenerContext, Task> func);
if (func == null)
{
methodInfo = routers["*"];
func = routers["*"];
}
try
{
if (methodInfo?.Invoke(this, new object[] { context }) is Task task) await task;
context.Response.Close();
if (func == null)
{
context.Response.StatusCode = (int)HttpStatusCode.NotFound;
}
else
{
await func(context);
}
}
catch (Exception ex)
{
Logger.Logger.Error("Handle Http Error: ", ex);
}
finally { context.Response.Close(); }
}
}
}
28 changes: 0 additions & 28 deletions windows/Server/HttpProxy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,34 +52,6 @@ public static async Task<ProxyResponseData> Request(ProxyRequestData data)
response.ContentEncoding ?? string.Empty,
response.CharacterSet ?? string.Empty,
resHeaders);
//using (Stream responseStream = response.GetResponseStream())
//{

// if (response.ContentEncoding?.ToLower() == "gzip")
// {
// using (Stream gzipStream = new GZipStream(responseStream, CompressionMode.Decompress))
// {
// return new ProxyResponseData(
// Utils.StreamToBytes(gzipStream),
// (int)response.StatusCode,
// response.ContentType,
// response.ContentEncoding,
// response.CharacterSet ?? string.Empty,
// resHeaders);
// }
// }
// else
// {
// return new ProxyResponseData(
// responseStream,
// response.ContentLength,
// (int)response.StatusCode,
// response.ContentType,
// response.ContentEncoding ?? string.Empty,
// response.CharacterSet ?? string.Empty,
// resHeaders);
// }
//}
}
catch (Exception ex)
{
Expand Down
89 changes: 89 additions & 0 deletions windows/Server/Router.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.WebSockets;
using System.Reflection;
using System.Threading.Tasks;

namespace Musiche.Server
{
public class Router
{
public static Dictionary<string, Func<HttpListenerContext, Task>> ReadHttpRouter(object obj)
{
Dictionary<string, Func<HttpListenerContext, Task>> routers = new Dictionary<string, Func<HttpListenerContext, Task>>();
if(obj == null) return routers;
Type type = obj.GetType();
MethodInfo[] methods = type.GetMethods();
foreach (MethodInfo method in methods)
{
if(!IsParameterRoute(method, typeof(HttpListenerContext))) continue;
RouterAttribute[] attributes = (RouterAttribute[])method.GetCustomAttributes(typeof(RouterAttribute), false);
var func = method.IsStatic ?
(Func<HttpListenerContext, Task>)Delegate.CreateDelegate(typeof(Func<HttpListenerContext, Task>), method) :
(Func<HttpListenerContext, Task>)Delegate.CreateDelegate(typeof(Func<HttpListenerContext, Task>), obj, method);
foreach (RouterAttribute attribute in attributes)
{
routers.Add(attribute.Router.ToUpper(), func);
}
}
return routers;
}
public static Dictionary<string, Func<WebSocket, Task>> ReadWebSocketRouter(object obj)
{
Dictionary<string, Func<WebSocket, Task>> routers = new Dictionary<string, Func<WebSocket, Task>>();
if (obj == null) return routers;
Type type = obj.GetType();
MethodInfo[] methods = type.GetMethods();
foreach (MethodInfo method in methods)
{
if (!IsParameterRoute(method, typeof(WebSocket))) continue;
RouterAttribute[] attributes = (RouterAttribute[])method.GetCustomAttributes(typeof(RouterAttribute), false);
var func = method.IsStatic ?
(Func<WebSocket, Task>)Delegate.CreateDelegate(typeof(Func<WebSocket, Task>), method) :
(Func<WebSocket, Task>)Delegate.CreateDelegate(typeof(Func<WebSocket, Task>), obj, method);
foreach (RouterAttribute attribute in attributes)
{
routers.Add(attribute.Router.ToUpper(), func);
}
}
return routers;
}

private static Func<HttpListenerContext, Task> ToHttpRouteMethod(MethodInfo method)
{
if (method.IsStatic)
{
return (Func<HttpListenerContext, Task>)Delegate.CreateDelegate(typeof(Func<HttpListenerContext, Task>), method);
}
else
{
object instance = Activator.CreateInstance(method.DeclaringType);
return (Func<HttpListenerContext, Task>)Delegate.CreateDelegate(typeof(Func<HttpListenerContext, Task>), instance, method);
}
}

private static Func<WebSocket, Task> ToWebSocketRouteMethod(MethodInfo method)
{
if (method.IsStatic)
{
return (Func<WebSocket, Task>)Delegate.CreateDelegate(typeof(Func<WebSocket, Task>), method);
}
else
{
object instance = Activator.CreateInstance(method.DeclaringType);
return (Func<WebSocket, Task>)Delegate.CreateDelegate(typeof(Func<WebSocket, Task>), instance, method);
}
}

private static bool IsParameterRoute(MethodInfo method, Type parameterType)
{
return method.GetCustomAttributes().OfType<RouterAttribute>().Any()
&& method.DeclaringType != null
&& method.ReturnType == typeof(Task)
&& method.GetParameters().Length == 1
&& method.GetParameters().First().ParameterType == parameterType;
}
}
}
36 changes: 0 additions & 36 deletions windows/Server/Utils.cs

This file was deleted.

12 changes: 5 additions & 7 deletions windows/Server/WebSocketHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ namespace Musiche.Server
{
public class WebSocketHandler : Handler, IHandler
{
private readonly Dictionary<string, MethodInfo> routers;
private readonly Dictionary<string, Func<WebSocket, Task>> routers;
private readonly HashSet<WebSocket> webSockets = new HashSet<WebSocket>();
public WebSocketHandler(MainWindow window, AudioPlay audioPlay) : base(window, audioPlay)
{
routers = Utils.ReadRouter(this);
routers = Router.ReadWebSocketRouter(this);
}

[Router("/status")]
public async Task WSStatus(WebSocket webSocket, string[] commands)
public async Task WSStatus(WebSocket webSocket)
{
var status = await GetStatus();
status.Add("type", "status");
Expand Down Expand Up @@ -70,11 +70,9 @@ public async Task Handle(HttpListenerContext context)
foreach (var message in messageList)
{
var commands = message.Split(',');
routers.TryGetValue(commands[0].ToUpper(), out MethodInfo methodInfo);
if (methodInfo != null)
if (routers.TryGetValue(commands[0].ToUpper(), out Func<WebSocket, Task> func))
{
var task = methodInfo.Invoke(this, new object[] { webSocket, commands }) as Task;
if (task != null) await task;
await func(webSocket);
}
}
}
Expand Down
11 changes: 11 additions & 0 deletions windows/Utils/App.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace Musiche.Utils
{
public class App
{
public static readonly string Version;
static App()
{
Version = System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetEntryAssembly().Location)?.ProductVersion ?? string.Empty;
}
}
}

0 comments on commit 23fce74

Please sign in to comment.