added path variable
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
# Copy to .env (next to docker-compose.yml) and adjust. Docker Compose reads .env automatically.
|
||||
|
||||
# Full URL the browser uses to reach the game hub through the reverse proxy.
|
||||
# Empty = "<website origin>/hub".
|
||||
SERVER_URL=https://game.example.com/server/hub
|
||||
|
||||
# Prefix the game server should accept when the proxy forwards its sub-path without
|
||||
# stripping it (e.g. /server). Leave empty if the proxy strips the prefix.
|
||||
PATH_BASE=
|
||||
|
||||
# Comma separated origins allowed to connect to the hub. Empty = allow any origin.
|
||||
ALLOWED_ORIGINS=https://game.example.com
|
||||
|
||||
# Optional gameplay tuning, passed to the server as Game__<Setting> (see GameSettings.cs).
|
||||
# Add these under the server's "environment:" in docker-compose.yml to use them.
|
||||
# Game__ItemSpawnChance=0.1
|
||||
# Game__CountdownSeconds=3
|
||||
@@ -0,0 +1 @@
|
||||
.env
|
||||
@@ -37,6 +37,8 @@ docker network create actionBlocks_server
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
The website uses relative URLs. It works under a sub-path such as `/website/`, whether or not the proxy strips that prefix.
|
||||
|
||||
The reverse proxy (attached to both networks) should route:
|
||||
|
||||
- the site to `actionblocks-website:80`
|
||||
@@ -47,6 +49,7 @@ The reverse proxy (attached to both networks) should route:
|
||||
| `SERVER_URL` | website | Hub URL as seen by the browser. Empty means `<site origin>/hub`. Written into `config.js` at container start. |
|
||||
| `ALLOWED_ORIGINS` | server | Comma-separated CORS origins. Empty allows any origin. |
|
||||
| `HUB_PATH` | server | Hub endpoint path (default `/hub`). |
|
||||
| `PATH_BASE` | server | Prefix to accept when the proxy forwards a sub-path unstripped, e.g. `/server`. |
|
||||
| `Game__*` | server | Overrides any `GameSettings` value, e.g. `Game__ItemSpawnChance=0.2`. |
|
||||
|
||||
## Extending
|
||||
|
||||
@@ -10,6 +10,9 @@ var builder = WebApplication.CreateBuilder(args);
|
||||
var allowedOrigins = (builder.Configuration["ALLOWED_ORIGINS"] ?? "")
|
||||
.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
|
||||
var hubPath = builder.Configuration["HUB_PATH"] ?? "/hub";
|
||||
// Optional prefix when the reverse proxy forwards a sub-path without stripping it, e.g. "/server".
|
||||
// Requests without the prefix keep working.
|
||||
var pathBase = builder.Configuration["PATH_BASE"] ?? "";
|
||||
|
||||
builder.Services.AddCors(options => options.AddDefaultPolicy(policy =>
|
||||
{
|
||||
@@ -35,6 +38,11 @@ builder.Services.AddHostedService<MatchRunner>();
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(pathBase))
|
||||
{
|
||||
app.UsePathBase(pathBase);
|
||||
}
|
||||
|
||||
app.UseCors();
|
||||
app.MapGet("/health", () => Results.Ok(new { status = "ok" }));
|
||||
app.MapHub<GameHub>(hubPath);
|
||||
|
||||
@@ -28,8 +28,14 @@ server {
|
||||
add_header Cache-Control "no-cache";
|
||||
}
|
||||
|
||||
# Single page app fallback.
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
try_files $uri $uri/ @prefixed;
|
||||
}
|
||||
|
||||
# The reverse proxy may forward a sub-path without stripping it (e.g. /website/static/x.js).
|
||||
# Drop the leading path segment and try again; fall back to the app's index.html.
|
||||
location @prefixed {
|
||||
rewrite ^/[^/]+(/.*)$ $1 last;
|
||||
rewrite ^ /index.html last;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,14 +2,18 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<!-- Relative asset URLs need a trailing slash when served under a sub-path (/website -> /website/). -->
|
||||
<script>
|
||||
if (!/\/$|\.[a-z0-9]+$/i.test(location.pathname)) location.replace(location.pathname + '/' + location.search + location.hash);
|
||||
</script>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="icon" type="image/svg+xml" href="/assets/favicon.svg" />
|
||||
<link rel="icon" type="image/svg+xml" href="./assets/favicon.svg" />
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link href="https://fonts.googleapis.com/css2?family=Press+Start+2P&display=swap" rel="stylesheet" />
|
||||
<title>Action Blocks</title>
|
||||
<!-- Runtime configuration, rewritten by the container on startup. -->
|
||||
<script src="/config.js"></script>
|
||||
<script src="./config.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
* (or point these paths elsewhere) to change the look without touching components.
|
||||
*/
|
||||
|
||||
/** Resolves a file in /public relative to where the site is served (works under sub-paths). */
|
||||
const asset = (path: string) => `${import.meta.env.BASE_URL}${path}`;
|
||||
|
||||
export interface ItemVisual {
|
||||
/** Icon drawn on board cells, in inventories and item bars. */
|
||||
icon: string;
|
||||
@@ -17,31 +20,31 @@ export interface ItemVisual {
|
||||
/** Keyed by the server item id (IItem.Id). Add an entry here when adding an item on the server. */
|
||||
export const itemVisuals: Record<string, ItemVisual> = {
|
||||
add_line: {
|
||||
icon: '/assets/items/add_line.svg',
|
||||
icon: asset('assets/items/add_line.svg'),
|
||||
name: 'Add Line',
|
||||
color: '#ff4256',
|
||||
description: 'Pushes a garbage line into the target field.',
|
||||
},
|
||||
clear_line: {
|
||||
icon: '/assets/items/clear_line.svg',
|
||||
icon: asset('assets/items/clear_line.svg'),
|
||||
name: 'Clear Line',
|
||||
color: '#4fe35f',
|
||||
description: 'Removes the bottom line of the target.',
|
||||
},
|
||||
nuke: {
|
||||
icon: '/assets/items/nuke.svg',
|
||||
icon: asset('assets/items/nuke.svg'),
|
||||
name: 'Wipe Out',
|
||||
color: '#ffe23f',
|
||||
description: 'Clears every placed block of the target.',
|
||||
},
|
||||
swap: {
|
||||
icon: '/assets/items/swap.svg',
|
||||
icon: asset('assets/items/swap.svg'),
|
||||
name: 'Switch',
|
||||
color: '#3fe3f2',
|
||||
description: 'Trades your whole field with the target.',
|
||||
},
|
||||
blind: {
|
||||
icon: '/assets/items/blind.svg',
|
||||
icon: asset('assets/items/blind.svg'),
|
||||
name: 'Blackout',
|
||||
color: '#c452ff',
|
||||
description: 'Hides placed blocks and the drop shadow for 4 seconds.',
|
||||
@@ -49,7 +52,7 @@ export const itemVisuals: Record<string, ItemVisual> = {
|
||||
};
|
||||
|
||||
export const unknownItem: ItemVisual = {
|
||||
icon: '/assets/items/unknown.svg',
|
||||
icon: asset('assets/items/unknown.svg'),
|
||||
name: 'Item',
|
||||
color: '#ffffff',
|
||||
description: '',
|
||||
@@ -58,7 +61,7 @@ export const unknownItem: ItemVisual = {
|
||||
export const uiAssets = {
|
||||
/** Optional logo image. When null the text logo is rendered. */
|
||||
logo: null as string | null,
|
||||
favicon: '/assets/favicon.svg',
|
||||
favicon: asset('assets/favicon.svg'),
|
||||
};
|
||||
|
||||
export function itemVisual(id: string): ItemVisual {
|
||||
|
||||
@@ -6,6 +6,8 @@ const devServer = process.env.DEV_SERVER_URL ?? 'http://localhost:5080';
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
// Relative URLs so the site works under any sub-path (e.g. https://example.com/website/).
|
||||
base: './',
|
||||
build: {
|
||||
// Hashed bundles go to /static; /assets holds the exchangeable graphics from public/.
|
||||
assetsDir: 'static',
|
||||
|
||||
+6
-2
@@ -6,8 +6,11 @@
|
||||
# website -> actionblocks-website:80
|
||||
# game hub -> actionblocks-server:8080, path /hub (needs WebSocket upgrade support:
|
||||
# "Upgrade" and "Connection" headers must be forwarded).
|
||||
# If the hub is served from a different host, set SERVER_URL accordingly and list the
|
||||
# website origin in ALLOWED_ORIGINS.
|
||||
# Sub-paths are supported (e.g. site at https://example.com/website/, server at /server):
|
||||
# - the website works whether or not the proxy strips its prefix;
|
||||
# - set SERVER_URL to the hub URL the browser should use, e.g. https://example.com/server/hub;
|
||||
# - if the proxy does NOT strip the server prefix, set PATH_BASE=/server.
|
||||
# If the hub is served from a different host, also list the website origin in ALLOWED_ORIGINS.
|
||||
|
||||
services:
|
||||
actionblocks-website:
|
||||
@@ -26,6 +29,7 @@ services:
|
||||
environment:
|
||||
ALLOWED_ORIGINS: ${ALLOWED_ORIGINS:-}
|
||||
HUB_PATH: /hub
|
||||
PATH_BASE: ${PATH_BASE:-}
|
||||
networks:
|
||||
- actionBlocks_server
|
||||
|
||||
|
||||
Reference in New Issue
Block a user