Skip to content

Commit 55283ed

Browse files
use taipy resource handler route to resolve cookies (#1956)
1 parent a7f0a41 commit 55283ed

File tree

8 files changed

+97
-21
lines changed

8 files changed

+97
-21
lines changed

frontend/taipy-gui/base/src/app.ts

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { initSocket } from "./socket";
99
import { TaipyWsAdapter, WsAdapter } from "./wsAdapter";
1010
import { WsMessageType } from "../../src/context/wsUtils";
1111
import { getBase } from "./utils";
12+
import { CookieHandler } from "./cookieHandler";
1213

1314
export type OnInitHandler = (taipyApp: TaipyApp) => void;
1415
export type OnChangeHandler = (taipyApp: TaipyApp, encodedName: string, value: unknown, dataEventKey?: string) => void;
@@ -36,6 +37,7 @@ export class TaipyApp {
3637
_onWsStatusUpdate: OnWsStatusUpdate | undefined;
3738
_ackList: string[];
3839
_rdc: Record<string, Record<string, RequestDataCallback>>;
40+
_cookieHandler: CookieHandler | undefined;
3941
variableData: DataManager | undefined;
4042
functionData: DataManager | undefined;
4143
appId: string;
@@ -51,6 +53,7 @@ export class TaipyApp {
5153
onChange: OnChangeHandler | undefined = undefined,
5254
path: string | undefined = undefined,
5355
socket: Socket | undefined = undefined,
56+
handleCookie: boolean = true,
5457
) {
5558
socket = socket || io("/", { autoConnect: false, path: `${this.getBaseUrl()}socket.io` });
5659
this.onInit = onInit;
@@ -67,8 +70,10 @@ export class TaipyApp {
6770
this.wsAdapters = [new TaipyWsAdapter()];
6871
this._ackList = [];
6972
this._rdc = {};
70-
// Init socket io connection
71-
initSocket(socket, this);
73+
this._cookieHandler = handleCookie ? new CookieHandler() : undefined;
74+
// Init socket io connection only when cookie is not handled
75+
// Socket will be initialized by cookie handler when it is used
76+
this._cookieHandler ? this._cookieHandler?.init(socket, this) : initSocket(socket, this);
7277
}
7378

7479
// Getter and setter
@@ -169,7 +174,7 @@ export class TaipyApp {
169174
this.sendWsMessage("ID", TAIPY_CLIENT_ID, id);
170175
if (id !== "") {
171176
this.clientId = id;
172-
this.initApp()
177+
this.initApp();
173178
this.updateContext(this.path);
174179
}
175180
}
@@ -292,6 +297,12 @@ export class TaipyApp {
292297
}
293298
}
294299

295-
export const createApp = (onInit?: OnInitHandler, onChange?: OnChangeHandler, path?: string, socket?: Socket) => {
296-
return new TaipyApp(onInit, onChange, path, socket);
300+
export const createApp = (
301+
onInit?: OnInitHandler,
302+
onChange?: OnChangeHandler,
303+
path?: string,
304+
socket?: Socket,
305+
handleCookie?: boolean,
306+
) => {
307+
return new TaipyApp(onInit, onChange, path, socket, handleCookie);
297308
};
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import { Socket } from "socket.io-client";
2+
import { TaipyApp } from "./app";
3+
import { initSocket } from "./socket";
4+
import axios from "axios";
5+
import { getLocalStorageValue } from "../../src/context/utils";
6+
7+
export const TAIPY_RESOURCE_HANDLER = "tprh";
8+
9+
export class CookieHandler {
10+
resourceHandlerId: string;
11+
constructor() {
12+
this.resourceHandlerId = getLocalStorageValue(TAIPY_RESOURCE_HANDLER, "");
13+
}
14+
async init(socket: Socket, taipyApp: TaipyApp) {
15+
const hasValidCookies = await this.verifyCookieStatus();
16+
if (!hasValidCookies) {
17+
await this.deleteCookie();
18+
localStorage.removeItem(TAIPY_RESOURCE_HANDLER);
19+
window.location.reload();
20+
return;
21+
}
22+
this.addBeforeUnloadListener();
23+
initSocket(socket, taipyApp);
24+
}
25+
26+
async verifyCookieStatus(): Promise<boolean> {
27+
// check to see if local storage has the resource handler id (potentially having a cookie)
28+
// If not, then some part of the code must have removed the cookie
29+
// or wants to remove the cookie by removing the local storage
30+
if (!this.resourceHandlerId) {
31+
return new Promise((resolve) => resolve(false));
32+
}
33+
try {
34+
// call to get cookie status
35+
const { data } = await axios.get("taipy-rh");
36+
// validate cookie status
37+
if (data?.rh_id !== this.resourceHandlerId) {
38+
return new Promise((resolve) => resolve(false));
39+
}
40+
} catch (error) {
41+
console.error("Error while validating cookie:", error);
42+
return new Promise((resolve) => resolve(false));
43+
}
44+
return new Promise((resolve) => resolve(true));
45+
}
46+
47+
addBeforeUnloadListener() {
48+
window.addEventListener("beforeunload", () => {
49+
localStorage.removeItem(TAIPY_RESOURCE_HANDLER);
50+
this.deleteCookie();
51+
});
52+
}
53+
54+
async deleteCookie() {
55+
await axios.delete("taipy-rh");
56+
}
57+
}

frontend/taipy-gui/base/src/index-preview.ts

Lines changed: 0 additions & 6 deletions
This file was deleted.

frontend/taipy-gui/base/src/index.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,3 @@ import { ModuleData } from "./dataManager";
44
export default TaipyApp;
55
export { TaipyApp, createApp };
66
export type { OnChangeHandler, OnInitHandler, ModuleData };
7-
8-
window.addEventListener("beforeunload", () => {
9-
document.cookie = "tprh=;path=/;Max-Age=-99999999;";
10-
});

frontend/taipy-gui/base/src/packaging/taipy-gui-base.d.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,8 @@ export type WsMessageType =
7575
| "GDT"
7676
| "AID"
7777
| "GR"
78-
| "FV";
78+
| "FV"
79+
| "BC";
7980
export interface WsMessage {
8081
type: WsMessageType | string;
8182
name: string;
@@ -89,6 +90,14 @@ export declare abstract class WsAdapter {
8990
abstract supportedMessageTypes: string[];
9091
abstract handleWsMessage(message: WsMessage, app: TaipyApp): boolean;
9192
}
93+
declare class CookieHandler {
94+
resourceHandlerId: string;
95+
constructor();
96+
init(socket: Socket, taipyApp: TaipyApp): Promise<void>;
97+
verifyCookieStatus(): Promise<boolean>;
98+
addBeforeUnloadListener(): void;
99+
deleteCookie(): Promise<void>;
100+
}
92101
export type OnInitHandler = (taipyApp: TaipyApp) => void;
93102
export type OnChangeHandler = (taipyApp: TaipyApp, encodedName: string, value: unknown, dataEventKey?: string) => void;
94103
export type OnNotifyHandler = (taipyApp: TaipyApp, type: string, message: string) => void;
@@ -112,6 +121,7 @@ export declare class TaipyApp {
112121
_onWsStatusUpdate: OnWsStatusUpdate | undefined;
113122
_ackList: string[];
114123
_rdc: Record<string, Record<string, RequestDataCallback>>;
124+
_cookieHandler: CookieHandler | undefined;
115125
variableData: DataManager | undefined;
116126
functionData: DataManager | undefined;
117127
appId: string;
@@ -126,6 +136,7 @@ export declare class TaipyApp {
126136
onChange?: OnChangeHandler | undefined,
127137
path?: string | undefined,
128138
socket?: Socket | undefined,
139+
handleCookie?: boolean,
129140
);
130141
get onInit(): OnInitHandler | undefined;
131142
set onInit(handler: OnInitHandler | undefined);
@@ -173,6 +184,7 @@ export declare const createApp: (
173184
onChange?: OnChangeHandler,
174185
path?: string,
175186
socket?: Socket,
187+
handleCookie?: boolean,
176188
) => TaipyApp;
177189

178190
export { TaipyApp as default };

frontend/taipy-gui/base/webpack.config.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ module.exports = [
1313
target: "web",
1414
entry: {
1515
default: "./base/src/index.ts",
16-
preview: "./base/src/index-preview.ts",
1716
},
1817
output: {
1918
filename: (arg) => {

frontend/taipy-gui/src/components/Taipy/Navigate.tsx

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@
1212
*/
1313

1414
import { useContext, useEffect } from "react";
15+
import axios from "axios";
1516
import { useLocation, useNavigate } from "react-router-dom";
17+
1618
import { TaipyContext } from "../../context/taipyContext";
1719
import { createNavigateAction } from "../../context/taipyReducers";
1820
import { getBaseURL } from "../../utils";
@@ -65,9 +67,15 @@ const Navigate = ({ to, params, tab, force }: NavigateProps) => {
6567
// Handle Resource Handler Id
6668
const tprh = params?.tprh;
6769
if (tprh !== undefined) {
68-
// Add a session cookie for the resource handler id
69-
document.cookie = `tprh=${tprh};path=/;`;
70-
navigate(0);
70+
axios.post(`taipy-rh`, { tprh, is_secure: window.location.protocol.includes("https") }).then(() => {
71+
localStorage.setItem("tprh", tprh);
72+
navigate(0);
73+
}).catch((error) => {
74+
console.error(
75+
"Cannot resolve resource handler. Route `/taipy-rh` might be missing.",
76+
error,
77+
);
78+
});
7179
}
7280
}
7381
} else {

frontend/taipy-gui/webpack.config.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,6 @@ module.exports = (env, options) => {
175175
target: "web",
176176
entry: {
177177
"default": "./base/src/index.ts",
178-
"preview": "./base/src/index-preview.ts",
179178
},
180179
output: {
181180
filename: (arg) => {

0 commit comments

Comments
 (0)