Fix dev TrackerHub transport
This commit is contained in:
@@ -142,6 +142,23 @@ app.use(["/api", "/flights"], (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
function normalizeTrackerCookie(cookie) {
|
||||
if (!cookie.startsWith("signal-id=")) return cookie;
|
||||
|
||||
const parts = cookie
|
||||
.split(";")
|
||||
.map((part) => part.trim())
|
||||
.filter(
|
||||
(part) =>
|
||||
part.length > 0 &&
|
||||
!part.toLowerCase().startsWith("domain=") &&
|
||||
!part.toLowerCase().startsWith("path=") &&
|
||||
!part.toLowerCase().startsWith("samesite="),
|
||||
);
|
||||
|
||||
return [...parts, "Path=/tracker/hub", "SameSite=Lax"].join("; ");
|
||||
}
|
||||
|
||||
// --- SignalR TrackerHub proxy ---
|
||||
// Browser-direct localhost → platform.test.aeroflot.ru fails CORS. Keep the
|
||||
// hub same-origin in development and let proxy-helper / gost route the
|
||||
@@ -153,6 +170,16 @@ const trackerProxy = createProxyMiddleware({
|
||||
ws: true,
|
||||
logLevel: "warn",
|
||||
pathRewrite: (path) => `/tracker${path}`,
|
||||
on: {
|
||||
proxyRes(proxyRes) {
|
||||
const setCookie = proxyRes.headers["set-cookie"];
|
||||
if (Array.isArray(setCookie)) {
|
||||
proxyRes.headers["set-cookie"] = setCookie.map(normalizeTrackerCookie);
|
||||
} else if (typeof setCookie === "string") {
|
||||
proxyRes.headers["set-cookie"] = normalizeTrackerCookie(setCookie);
|
||||
}
|
||||
},
|
||||
},
|
||||
...(SYSTEM_PROXY ? { agent: new HttpsProxyAgent(SYSTEM_PROXY) } : {}),
|
||||
});
|
||||
app.use("/tracker", trackerProxy);
|
||||
|
||||
@@ -3,6 +3,7 @@ import {
|
||||
SignalRConnection,
|
||||
getSharedConnection,
|
||||
_resetSharedConnections,
|
||||
_shouldUseLongPollingForDevTrackerProxy,
|
||||
type ConnectionStatus,
|
||||
} from "./connection.js";
|
||||
|
||||
@@ -269,3 +270,19 @@ describe("getSharedConnection", () => {
|
||||
expect(a).not.toBe(b);
|
||||
});
|
||||
});
|
||||
|
||||
describe("_shouldUseLongPollingForDevTrackerProxy", () => {
|
||||
it("enables LongPolling only for the local tracker proxy", () => {
|
||||
expect(
|
||||
_shouldUseLongPollingForDevTrackerProxy(
|
||||
"http://localhost:8080/tracker/hub",
|
||||
),
|
||||
).toBe(true);
|
||||
expect(_shouldUseLongPollingForDevTrackerProxy("/tracker/hub")).toBe(true);
|
||||
expect(
|
||||
_shouldUseLongPollingForDevTrackerProxy(
|
||||
"https://platform.test.aeroflot.ru/tracker/hub",
|
||||
),
|
||||
).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -224,13 +224,32 @@ export function _resetSharedConnections(): void {
|
||||
|
||||
// ---- Default builder (dynamic import) ----
|
||||
|
||||
export function _shouldUseLongPollingForDevTrackerProxy(url: string): boolean {
|
||||
try {
|
||||
const parsed = new URL(url, "http://localhost");
|
||||
const isLocalHost =
|
||||
parsed.hostname === "localhost" ||
|
||||
parsed.hostname === "127.0.0.1" ||
|
||||
parsed.hostname === "::1";
|
||||
return isLocalHost && parsed.pathname.replace(/\/$/, "") === "/tracker/hub";
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async function defaultBuildConnection(
|
||||
url: string,
|
||||
delays: number[],
|
||||
): Promise<HubConnectionLike> {
|
||||
const { HubConnectionBuilder, LogLevel } = await import("@microsoft/signalr");
|
||||
return new HubConnectionBuilder()
|
||||
.withUrl(url)
|
||||
const { HubConnectionBuilder, HttpTransportType, LogLevel } = await import(
|
||||
"@microsoft/signalr"
|
||||
);
|
||||
const builder = new HubConnectionBuilder();
|
||||
const withUrlOptions = _shouldUseLongPollingForDevTrackerProxy(url)
|
||||
? { transport: HttpTransportType.LongPolling }
|
||||
: undefined;
|
||||
|
||||
return (withUrlOptions ? builder.withUrl(url, withUrlOptions) : builder.withUrl(url))
|
||||
.withAutomaticReconnect(delays)
|
||||
// Suppress SignalR's internal console logging. The hub is optional
|
||||
// (failures degrade to polling) and we already handle status via
|
||||
|
||||
Reference in New Issue
Block a user