give public lobbies smoother countdown, use admin token in server.

This commit is contained in:
Evan
2025-03-06 19:43:56 -08:00
parent e97fe402ef
commit edcfac2fe7
4 changed files with 23 additions and 32 deletions
+13 -3
View File
@@ -7,6 +7,8 @@ import { GameInfo } from "../core/Schemas";
@customElement("public-lobby")
export class PublicLobby extends LitElement {
private lobbyOutOfDate = true;
@state() private lobbies: GameInfo[] = [];
@state() public isLobbyHighlighted: boolean = false;
@state() private isButtonDebounced: boolean = false;
@@ -37,9 +39,17 @@ export class PublicLobby extends LitElement {
private async fetchAndUpdateLobbies(): Promise<void> {
try {
const lobbies = await this.fetchLobbies();
console.log(`got lobbies: ${JSON.stringify(lobbies)}`);
this.lobbies = lobbies;
// Due to cache we only update every 2s,
// but reduce time by 1s so countdown looks nice.
if (this.lobbyOutOfDate) {
this.lobbies = await this.fetchLobbies();
} else {
this.lobbies.forEach((l) => {
l.msUntilStart -= 1000;
});
this.requestUpdate();
}
this.lobbyOutOfDate = !this.lobbyOutOfDate;
} catch (error) {
consolex.error("Error fetching lobbies:", error);
}
+5 -2
View File
@@ -165,7 +165,9 @@ async function fetchLobbies(): Promise<void> {
for (const gameID of publicLobbyIDs) {
const port = config.workerPort(gameID);
const promise = fetch(`http://localhost:${port}/api/game/${gameID}`)
const promise = fetch(`http://localhost:${port}/api/game/${gameID}`, {
headers: { [config.adminHeader()]: config.adminToken() },
})
.then((resp) => resp.json())
.then((json) => {
return json as GameInfo;
@@ -232,7 +234,8 @@ async function schedulePublicGame() {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Internal-Request": "true", // Special header for internal requests
"X-Internal-Request": "true",
[config.adminHeader()]: config.adminToken(),
},
body: JSON.stringify({
gameID: gameID,
+4 -26
View File
@@ -79,7 +79,10 @@ export function startWorker() {
// TODO: if game is public make sure request came from localhohst!!!
const clientIP = req.ip || req.socket.remoteAddress || "unknown";
const gc = req.body?.gameConfig as GameConfig;
if (gc?.gameType == GameType.Public && !isLocalhost(req)) {
if (
gc?.gameType == GameType.Public &&
req.headers[config.adminHeader()] != config.adminToken()
) {
console.warn(
`cannot create public game ${id}, ip ${clientIP} not localhost`,
);
@@ -319,28 +322,3 @@ export function startWorker() {
});
});
}
const isLocalhost = (req: Request): boolean => {
// Get client IP address from various possible sources
const clientIP =
req.ip ||
req.socket.remoteAddress ||
(req.headers["x-forwarded-for"] as string)?.split(",").shift() ||
"unknown";
// Check if the request is from a loopback address
const isLoopbackIP =
// IPv4 localhost
clientIP === "127.0.0.1" ||
// IPv6 localhost
clientIP === "::1" ||
// Full loopback range
clientIP.startsWith("127.");
// Check hostname
const isLocalHostname =
req.hostname === "localhost" || req.headers.host?.startsWith("localhost:");
// Consider request local if either IP is loopback or hostname is localhost
return isLoopbackIP || isLocalHostname;
};