Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ Cel: potwierdzić, że podejście działa, zanim cokolwiek ruszymy w Way.
- `ShellOptions.Notice`: notka nad każdym Way (panel i strona Way), np. „publiczne demo”.
- `WayModule.IsHidden`: Way bez pozycji w menu panelu, otwierany pod `#/{id}/` (np. konto z linku pod nazwą użytkownika); panel przekierowuje na pierwszy widoczny Way.
- `UseWayShell("/")`: panel w korzeniu aplikacji. Konwencja na grupie zawęża trasę catch-all Reiho do samego `/` (pliki panelu i tak idą z `AssetsPath`); bez tego każdy nieznany adres dostawał 404 panelu albo przekierowanie na logowanie (klient API z kluczem: 302 zamiast 404). Inne endpointy hosta odpowiadają jak dotąd. `MapWay` w korzeniu dalej zabronione.
- 2.1.1: pod PathBase adres aplikacji bez końcowego ukośnika (`/app`) ma pustą ścieżkę, z której Reiho nie umiał wyciąć `/` trasy panelu w korzeniu (500 u zalogowanego na demie Polyglota). Konwencja ustawia wtedy `Path = "/"`; test z adresem bez ukośnika.
- Kontrakt modułu bez zmian (2). Testy: 53 × 3 TFM, npm 31; demo Shella (notka, ukryty Way „Account”) 40/40 × 4 przeglądarki.

### Faza 7: wydanie
Expand Down
7 changes: 7 additions & 0 deletions src/Way.Shell.Tests/ShellPageTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,13 @@ public async Task Panel_AtTheRoot_IsTheHomePage_NextToTheHostsEndpoints(string?
Assert.Equal($"{prefix}/config/api", ShellApp.SettingsOf(html).GetProperty("ways")[0].GetProperty("apiBase").GetString());
Assert.Equal("sign in", await (await app.GetAsync($"{prefix}/login")).Content.ReadAsStringAsync());
Assert.Equal("single", ShellApp.SettingsOf(await (await app.GetAsync($"{prefix}/config/")).Content.ReadAsStringAsync()).GetProperty("mode").GetString());
if (pathBase is not null)
{
// The app's own address without the trailing slash: under the path base the request path is empty.
var bare = await app.GetAsync(pathBase, user: "ada");
Assert.Equal(HttpStatusCode.OK, bare.StatusCode);
Assert.Contains($"""<base href="{baseHref}">""", await bare.Content.ReadAsStringAsync());
}
// Only the page: addresses the host does not map stay 404, not the panel's sign-in.
Assert.Equal(HttpStatusCode.Unauthorized, (await app.GetAsync($"{prefix}/")).StatusCode);
Assert.Equal(HttpStatusCode.NotFound, (await app.GetAsync($"{prefix}/nothing")).StatusCode);
Expand Down
10 changes: 9 additions & 1 deletion src/Way.Shell/ShellEndpoints.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,15 @@ public RouteGroupBuilder UseWayShell(string path = "/admin")
// answer every address the host does not map, with the panel's 404 or its sign-in instead of the host's.
((IEndpointConventionBuilder)group).Add(endpoint =>
{
if (endpoint is RouteEndpointBuilder route) route.RoutePattern = RoutePatternFactory.Parse("/");
if (endpoint is not RouteEndpointBuilder { RequestDelegate: { } inner } route) return;
route.RoutePattern = RoutePatternFactory.Parse("/");
// Under a path base the app's own address without the trailing slash (/app) has an empty path, which
// Reiho cannot cut the route's "/" from.
route.RequestDelegate = context =>
{
if (!context.Request.Path.HasValue) context.Request.Path = "/";
return inner(context);
};
});
return group;
}
Expand Down
Loading