refactor
This commit is contained in:
parent
c302da3713
commit
2a62fb2c7b
7 changed files with 77 additions and 77 deletions
|
@ -11,7 +11,7 @@ public class CORS : IRouter
|
|||
{
|
||||
}
|
||||
|
||||
public Task<HttpResponse?> Handle(HttpRequest client, ArraySegment<string> path, ParameterCollection? baseParameters)
|
||||
public Task<HttpResponse?> Handle(HttpRequest client, ArraySegment<string> path, VariableCollection? baseParameters)
|
||||
{
|
||||
if (client.Method != HttpMethod.OPTIONS)
|
||||
return Task.FromResult<HttpResponse?>(null);
|
||||
|
|
|
@ -6,14 +6,14 @@ namespace MiniHTTP.Routing;
|
|||
/// An asynchronous endpoint handler.
|
||||
/// </summary>
|
||||
/// <param name="request">The request being served.</param>
|
||||
/// <param name="parameters">Parameters in the path.</param>
|
||||
/// <param name="variables">Variables provided in the path.</param>
|
||||
/// <returns>Returns a HTTP response if the request successfully hit. Returns null if the request misses the handler.</returns>
|
||||
public delegate Task<HttpResponse?> EndpointHandlerAsync(HttpRequest request, ParameterCollection parameters);
|
||||
public delegate Task<HttpResponse?> EndpointHandlerAsync(HttpRequest request, VariableCollection variables);
|
||||
|
||||
/// <summary>
|
||||
/// An synchronous endpoint handler.
|
||||
/// </summary>
|
||||
/// <param name="request">The request being served.</param>
|
||||
/// <param name="parameters">Parameters in the path.</param>
|
||||
/// <param name="variables">Variables provided in the path.</param>
|
||||
/// <returns>Returns a HTTP response if the request successfully hit. Returns null if the request misses the handler.</returns>
|
||||
public delegate HttpResponse? EndpointHandler(HttpRequest request, ParameterCollection parameters);
|
||||
public delegate HttpResponse? EndpointHandler(HttpRequest request, VariableCollection variables);
|
|
@ -7,5 +7,5 @@ namespace MiniHTTP.Routing;
|
|||
/// </summary>
|
||||
public interface IRouter
|
||||
{
|
||||
Task<HttpResponse?> Handle(HttpRequest client, ArraySegment<string> path, ParameterCollection? baseParameters);
|
||||
Task<HttpResponse?> Handle(HttpRequest client, ArraySegment<string> path, VariableCollection? baseParameters);
|
||||
}
|
||||
|
|
|
@ -1,58 +0,0 @@
|
|||
namespace MiniHTTP.Routing;
|
||||
|
||||
/// <summary>
|
||||
/// A map of arguments passed as parameters in a HTTP path.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// Routes may contain parameters, denoted by a colon at the beginning. When a request is made, whatever is provided in that space becomes available in the parameter collection as an argument.
|
||||
/// If you have a route such as <c>/far/:example/bar</c>, and a client requests the path <c>/foo/quux/bar</c>, then the argument passed to the "example" parameter will be "quux".
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Arguments can be obtained from the collection like a <see cref="Dictionary{TKey, TValue}"/>. For example:
|
||||
/// <code>
|
||||
/// string id = parameters["id"];
|
||||
/// </code>
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public class ParameterCollection
|
||||
{
|
||||
public static readonly ParameterCollection Empty = new ParameterCollection();
|
||||
|
||||
/// <summary>
|
||||
/// A parameter collection to read from if this instance fails to fulfill a lookup.
|
||||
/// </summary>
|
||||
public readonly ParameterCollection? Fallback;
|
||||
|
||||
readonly Dictionary<string, string> Parameters = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
public string? this[string key]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Parameters.TryGetValue(key, out var value))
|
||||
return value;
|
||||
else if (Fallback == null)
|
||||
return null;
|
||||
else
|
||||
return Fallback[key];
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value == null)
|
||||
Parameters.Remove(key);
|
||||
else
|
||||
Parameters[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
public ParameterCollection(ParameterCollection? fallback = null)
|
||||
{
|
||||
Fallback = fallback;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
Parameters.Clear();
|
||||
}
|
||||
}
|
|
@ -9,13 +9,13 @@ public class Router : IRouter
|
|||
{
|
||||
struct Route
|
||||
{
|
||||
public string[] Paths;
|
||||
public string[] Path;
|
||||
|
||||
public IRouter Router;
|
||||
|
||||
public Route(string[] paths, IRouter router)
|
||||
{
|
||||
Paths = paths;
|
||||
Path = paths;
|
||||
Router = router;
|
||||
}
|
||||
}
|
||||
|
@ -42,22 +42,22 @@ public class Router : IRouter
|
|||
Endpoint = (client, parameters) => Task.FromResult(endpoint(client, parameters));
|
||||
}
|
||||
|
||||
internal async Task<HttpResponse?> Handle(HttpRequest client, ArraySegment<string> path, ParameterCollection? baseParameters)
|
||||
internal async Task<HttpResponse?> Handle(HttpRequest client, ArraySegment<string> path, VariableCollection? baseParameters)
|
||||
{
|
||||
if (Method != HttpMethod.Any && client.Method != Method)
|
||||
return null;
|
||||
|
||||
ParameterCollection parameters = new ParameterCollection(baseParameters);
|
||||
VariableCollection parameters = new VariableCollection(baseParameters);
|
||||
foreach (var route in Routes)
|
||||
{
|
||||
if (route.Paths.Length != 1 || route.Paths[0] != "*")
|
||||
if (route.Path.Length != 1 || route.Path[0] != "*")
|
||||
{
|
||||
if (route.Paths.Length > path.Count)
|
||||
if (route.Path.Length > path.Count)
|
||||
continue;
|
||||
|
||||
for (int i = 0; i < route.Paths.Length; i++)
|
||||
for (int i = 0; i < route.Path.Length; i++)
|
||||
{
|
||||
string key = route.Paths[i];
|
||||
string key = route.Path[i];
|
||||
if (key.Length == 0)
|
||||
{
|
||||
if (path[i].Length == 0)
|
||||
|
@ -68,7 +68,7 @@ public class Router : IRouter
|
|||
|
||||
if (key[0] == ':')
|
||||
{
|
||||
parameters[route.Paths[i][1..]] = path[i];
|
||||
parameters[route.Path[i][1..]] = path[i];
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -77,7 +77,7 @@ public class Router : IRouter
|
|||
}
|
||||
}
|
||||
|
||||
HttpResponse? resp = await route.Router.Handle(client, path.Slice(route.Paths.Length), parameters);
|
||||
HttpResponse? resp = await route.Router.Handle(client, path.Slice(route.Path.Length), parameters);
|
||||
if (resp != null)
|
||||
return resp;
|
||||
|
||||
|
@ -88,10 +88,10 @@ public class Router : IRouter
|
|||
if (Endpoint == null)
|
||||
return null;
|
||||
else
|
||||
return await Endpoint(client, baseParameters ?? ParameterCollection.Empty);
|
||||
return await Endpoint(client, baseParameters ?? VariableCollection.Empty);
|
||||
}
|
||||
|
||||
Task<HttpResponse?> IRouter.Handle(HttpRequest client, ArraySegment<string> path, ParameterCollection? baseParameters)
|
||||
Task<HttpResponse?> IRouter.Handle(HttpRequest client, ArraySegment<string> path, VariableCollection? baseParameters)
|
||||
=> Handle(client, path, baseParameters);
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -70,7 +70,7 @@ public partial class Static : IRouter
|
|||
AssetParameter = assetParameter;
|
||||
}
|
||||
|
||||
async Task<HttpResponse?> IRouter.Handle(HttpRequest client, ArraySegment<string> path, ParameterCollection? baseParameters)
|
||||
async Task<HttpResponse?> IRouter.Handle(HttpRequest client, ArraySegment<string> path, VariableCollection? baseParameters)
|
||||
{
|
||||
if (baseParameters == null)
|
||||
return null;
|
||||
|
|
58
MiniHTTP/Routing/VariableCollection.cs
Normal file
58
MiniHTTP/Routing/VariableCollection.cs
Normal file
|
@ -0,0 +1,58 @@
|
|||
namespace MiniHTTP.Routing;
|
||||
|
||||
/// <summary>
|
||||
/// A map of arguments passed as variables in a HTTP path.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// Routes may contain variables, denoted by a colon at the beginning. When a request is made, whatever is provided in that space becomes available in the variable collection as an argument.
|
||||
/// If you have a route such as <c>/far/:example/bar</c>, and a client requests the path <c>/foo/quux/bar</c>, then the argument passed to the "example" variable will be "quux".
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Arguments can be obtained from the collection like a <see cref="Dictionary{TKey, TValue}"/>. For example:
|
||||
/// <code>
|
||||
/// string id = variables["id"];
|
||||
/// </code>
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public class VariableCollection
|
||||
{
|
||||
public static readonly VariableCollection Empty = new VariableCollection();
|
||||
|
||||
/// <summary>
|
||||
/// A variable collection to read from if this instance fails to fulfill a lookup.
|
||||
/// </summary>
|
||||
public readonly VariableCollection? Fallback;
|
||||
|
||||
readonly Dictionary<string, string> Values = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
public string? this[string key]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Values.TryGetValue(key, out var value))
|
||||
return value;
|
||||
else if (Fallback == null)
|
||||
return null;
|
||||
else
|
||||
return Fallback[key];
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value == null)
|
||||
Values.Remove(key);
|
||||
else
|
||||
Values[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
public VariableCollection(VariableCollection? fallback = null)
|
||||
{
|
||||
Fallback = fallback;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
Values.Clear();
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue