correct routes for API + backoffice
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
|
||||
namespace zero.Api;
|
||||
|
||||
public class ApiApplicationResolverHandler : IBackofficeApplicationResolverHandler
|
||||
{
|
||||
public bool TryResolve(HttpContext context, IEnumerable<Application> applications, ZeroUser user, out Application resolved)
|
||||
{
|
||||
var routeValues = context.Features.Get<IRouteValuesFeature>().RouteValues;
|
||||
|
||||
if (routeValues.ContainsKey("zero_app_key"))
|
||||
{
|
||||
string appKey = routeValues["zero_app_key"] as string;
|
||||
resolved = applications.FirstOrDefault(x => x.Alias == appKey);
|
||||
return resolved != null;
|
||||
}
|
||||
|
||||
resolved = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace zero.Api.Endpoints.NotFound;
|
||||
|
||||
public class NotFoundZeroApiController : Controller
|
||||
{
|
||||
public virtual ActionResult Index()
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@ public class ZeroApiPlugin : ZeroPlugin
|
||||
{
|
||||
services.AddOptions<ApiOptions>().Bind(configuration.GetSection("Zero:Api")).Configure<IWebHostEnvironment>(ConfigureOptions);
|
||||
services.TryAddEnumerable(ServiceDescriptor.Transient<IConfigureOptions<MvcOptions>, ZeroApiMvcOptions>());
|
||||
services.AddTransient<IBackofficeApplicationResolverHandler, ApiApplicationResolverHandler>();
|
||||
|
||||
ZeroModuleCollection modules = new();
|
||||
|
||||
|
||||
@@ -57,7 +57,9 @@ public class ZeroApiControllerModelConvention : IControllerModelConvention
|
||||
|
||||
if (appAware)
|
||||
{
|
||||
path.Append("{zero_app_slug}/");
|
||||
path.Append("{zero_app_key}/");
|
||||
// TODO add route constraint which only allows registered app-ids
|
||||
// see https://nemi-chand.github.io/creating-custom-routing-constraint-in-aspnet-core-mvc/
|
||||
}
|
||||
|
||||
path.Append("[controller]");
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
|
||||
namespace zero.Backoffice;
|
||||
|
||||
public static class ZeroEndpointRouteBuilderExtensions
|
||||
{
|
||||
public static void MapZeroApi(this IZeroEndpointRouteBuilder endpoints, string path = "/zero/api")
|
||||
{
|
||||
endpoints.MapFallbackToController(path.EnsureEndsWith('/') + "{**path}", "Index", "NotFoundZeroApi");
|
||||
//app.UseWhen(ctx => ctx.Request.Path.StartsWithSegments(path + "/api"), app1 =>
|
||||
//{
|
||||
// app1.UseEndpoints(endpoints =>
|
||||
// {
|
||||
// //IZeroOptions options = app.ApplicationServices.GetService<IZeroOptions>(); // TODO oO
|
||||
// // see https://our.umbraco.com/documentation/reference/routing/custom-routes#where-to-put-your-routing-logic
|
||||
// //string path = options.BackofficePath.EnsureStartsWith('/').TrimEnd('/');
|
||||
// //endpoints.MapFallbackToController(path + "/{**path}", "Index", "ZeroIndex");
|
||||
|
||||
// //endpoints.MapControllers();
|
||||
// });
|
||||
//});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
|
||||
namespace zero.Backoffice;
|
||||
|
||||
public static class ZeroEndpointRouteBuilderExtensions
|
||||
{
|
||||
public static void MapZeroBackoffice(this IZeroEndpointRouteBuilder endpoints, string path = "/zero")
|
||||
{
|
||||
endpoints.MapFallbackToController(path.EnsureEndsWith('/') + "{**path}", "Index", "ZeroIndex");
|
||||
endpoints.MapFallbackToController(path.EnsureEndsWith('/') + "backoffice/{**path}", "Index", "NotFoundZeroApi");
|
||||
//app.UseWhen(ctx => ctx.Request.Path.StartsWithSegments(path + "/api"), app1 =>
|
||||
//{
|
||||
// app1.UseEndpoints(endpoints =>
|
||||
// {
|
||||
// //IZeroOptions options = app.ApplicationServices.GetService<IZeroOptions>(); // TODO oO
|
||||
// // see https://our.umbraco.com/documentation/reference/routing/custom-routes#where-to-put-your-routing-logic
|
||||
// //string path = options.BackofficePath.EnsureStartsWith('/').TrimEnd('/');
|
||||
// //endpoints.MapFallbackToController(path + "/{**path}", "Index", "ZeroIndex");
|
||||
|
||||
// //endpoints.MapControllers();
|
||||
// });
|
||||
//});
|
||||
}
|
||||
}
|
||||
@@ -39,29 +39,65 @@ public class ApplicationResolver : IApplicationResolver
|
||||
return null;
|
||||
}
|
||||
|
||||
Application app;
|
||||
Application app = null;
|
||||
|
||||
//if (context.IsBackofficeRequest(Options.ZeroPath))
|
||||
//{
|
||||
// app = await ResolveFromUser(user);
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// app = await ResolveFromRequest(context);
|
||||
//}
|
||||
app = await ResolveFromRequest(context);
|
||||
if (context.IsBackofficeRequest(Options.ZeroPath))
|
||||
{
|
||||
ZeroUser userEntity = await GetBackofficeUser(user);
|
||||
app = await ResolveFromBackofficeHandlers(context, userEntity) ?? await ResolveFromUser(userEntity);
|
||||
}
|
||||
|
||||
if (app == null)
|
||||
{
|
||||
//Logger.LogWarning("Could not resolve application for host {host}", context.Request.Host);
|
||||
IList<Application> apps = await GetApplications();
|
||||
app = apps.FirstOrDefault();
|
||||
app = await ResolveFromHandlers(context) ?? await ResolveFromRequest(context);
|
||||
}
|
||||
|
||||
if (app == null)
|
||||
{
|
||||
Logger.LogWarning("Could not resolve application for host {host}", context.Request.Host);
|
||||
return null;
|
||||
}
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<Application> ResolveFromHandlers(HttpContext context)
|
||||
{
|
||||
IList<Application> apps = await GetApplications();
|
||||
IEnumerable<IApplicationResolverHandler> handlers = Handler.GetAll<IApplicationResolverHandler>();
|
||||
|
||||
foreach (IApplicationResolverHandler handler in handlers)
|
||||
{
|
||||
if (handler.TryResolve(context, apps, out Application resolved))
|
||||
{
|
||||
return resolved;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<Application> ResolveFromBackofficeHandlers(HttpContext context, ZeroUser user)
|
||||
{
|
||||
IList<Application> apps = await GetApplications();
|
||||
IEnumerable<IBackofficeApplicationResolverHandler> handlers = Handler.GetAll<IBackofficeApplicationResolverHandler>();
|
||||
|
||||
foreach (IBackofficeApplicationResolverHandler handler in handlers)
|
||||
{
|
||||
if (handler.TryResolve(context, apps, user, out Application resolved))
|
||||
{
|
||||
return resolved;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<Application> ResolveFromUser(ClaimsPrincipal user)
|
||||
{
|
||||
@@ -108,37 +144,15 @@ public class ApplicationResolver : IApplicationResolver
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<Application> ResolveFromRequest(HttpContext context)
|
||||
{
|
||||
//if (Options.Applications.Count < 2)
|
||||
//{
|
||||
// return (await GetApplications()).FirstOrDefault();
|
||||
//}
|
||||
|
||||
IApplicationResolverHandler handler = Handler.Get<IApplicationResolverHandler>();
|
||||
Application app = handler?.Resolve(context.Request, await GetApplications());
|
||||
|
||||
if (app == null)
|
||||
{
|
||||
app = await ResolveFromUri(context.Request.GetEncodedUrl());
|
||||
}
|
||||
|
||||
return app;
|
||||
}
|
||||
public Task<Application> ResolveFromRequest(HttpContext context) => ResolveFromUri(context.Request.GetEncodedUrl());
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<Application> ResolveFromUri(string uriString)
|
||||
{
|
||||
return ResolveFromUriInternal(new Uri(uriString, UriKind.Absolute), await GetApplications());
|
||||
}
|
||||
public async Task<Application> ResolveFromUri(string uriString) => ResolveFromUriInternal(new Uri(uriString, UriKind.Absolute), await GetApplications());
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<Application> ResolveFromUri(Uri uri)
|
||||
{
|
||||
return ResolveFromUriInternal(uri, await GetApplications());
|
||||
}
|
||||
public async Task<Application> ResolveFromUri(Uri uri) => ResolveFromUriInternal(uri, await GetApplications());
|
||||
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -4,5 +4,5 @@ namespace zero.Applications;
|
||||
|
||||
public interface IApplicationResolverHandler : IHandler
|
||||
{
|
||||
Application Resolve(HttpRequest request, IEnumerable<Application> applications);
|
||||
bool TryResolve(HttpContext context, IEnumerable<Application> applications, out Application resolved);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace zero.Applications;
|
||||
|
||||
public interface IBackofficeApplicationResolverHandler : IHandler
|
||||
{
|
||||
bool TryResolve(HttpContext context, IEnumerable<Application> applications, ZeroUser user, out Application resolved);
|
||||
}
|
||||
@@ -110,7 +110,7 @@ public class ZeroContext : IZeroContext
|
||||
Application = await AppResolver.Resolve(context, BackofficeUser);
|
||||
AppId = Application.Id;
|
||||
|
||||
Logger.LogDebug("Resolved {appId} for request {uri}", AppId, context.Request.Host.ToString() + context.Request.Path.Value.EnsureStartsWith('/'));
|
||||
Logger.LogInformation("Resolved {appId} ({uri})", AppId, context.Request.Host.ToString() + context.Request.Path.Value.EnsureStartsWith('/'));
|
||||
|
||||
// set default database for document store
|
||||
Store.ResolvedDatabase = Application.Database;
|
||||
|
||||
@@ -14,8 +14,8 @@ public class ZeroApplicationBuilder : IZeroApplicationBuilder
|
||||
App = app;
|
||||
App.UseStaticFiles();
|
||||
//App.UseExceptionHandler("/zero/api/error");
|
||||
App.UseMiddleware<ZeroContextMiddleware>();
|
||||
App.UseRouting();
|
||||
App.UseMiddleware<ZeroContextMiddleware>();
|
||||
App.UseAuthentication();
|
||||
App.UseAuthorization();
|
||||
|
||||
|
||||
@@ -20,22 +20,27 @@ public class DevApplicationResolverHandler : IApplicationResolverHandler
|
||||
}
|
||||
|
||||
|
||||
public Application Resolve(HttpRequest request, IEnumerable<Application> applications)
|
||||
public bool TryResolve(HttpContext context, IEnumerable<Application> applications, out Application resolved)
|
||||
{
|
||||
resolved = null;
|
||||
|
||||
//if (!Env.IsDevelopment())
|
||||
//{
|
||||
// return null;
|
||||
// return false;
|
||||
//}
|
||||
if (request.Host.Host.Contains("ngrok.io"))
|
||||
|
||||
if (context.Request.Host.Host.Contains("ngrok.io"))
|
||||
{
|
||||
return applications.First(x => x.Id == "app.hofbauer");
|
||||
resolved = applications.First(x => x.Id == "app.hofbauer");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (request.Host.Port.HasValue && PortMap.TryGetValue(request.Host.Port.Value, out string appId))
|
||||
if (context.Request.Host.Port.HasValue && PortMap.TryGetValue(context.Request.Host.Port.Value, out string appId))
|
||||
{
|
||||
return applications.FirstOrDefault(x => x.Id == appId);
|
||||
resolved = applications.FirstOrDefault(x => x.Id == appId);
|
||||
return true;
|
||||
}
|
||||
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,11 @@
|
||||
@page
|
||||
@model IndexModel
|
||||
@inject zero.Context.IZeroContext context
|
||||
@{
|
||||
ViewData["Title"] = "Home page";
|
||||
}
|
||||
|
||||
<div class="text-center">
|
||||
<h1 class="display-4">Welcome</h1>
|
||||
<h1 class="display-4">Welcome to <u>@context.AppId</u></h1>
|
||||
<p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
|
||||
</div>
|
||||
|
||||
@@ -41,6 +41,8 @@ app.UseZero().WithEndpoints(x =>
|
||||
//x.MapControllerRoute("default", "api/{controller}/{action=Index}/{id?}");
|
||||
x.MapControllers();
|
||||
x.MapRazorPages();
|
||||
x.MapZeroApi();
|
||||
x.MapZeroBackoffice();
|
||||
x.MapZeroRoutes();
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user