Skip to content

Commit b2cbbf2

Browse files
authored
feat: cache the endpoint url for the mock-provider in session storage (#1979)
* feat: set the endpoint URL for mock-provide in session storage * refactor: test to check the storage exists, rename to SessionCache * refactor: use better access modifiers for properties and methods
1 parent adca163 commit b2cbbf2

File tree

2 files changed

+89
-11
lines changed

2 files changed

+89
-11
lines changed

packages/mgt-element/src/mock/MockGraph.ts

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
RetryHandlerOptions,
1616
TelemetryHandler
1717
} from '@microsoft/microsoft-graph-client';
18+
import { SessionCache, storageAvailable } from '../utils/SessionCache';
1819
import { MgtBaseComponent } from '../components/baseComponent';
1920
import { Graph } from '../Graph';
2021
import { chainMiddleware } from '../utils/GraphHelpers';
@@ -74,13 +75,21 @@ class MockMiddleware implements Middleware {
7475
*/
7576
private _nextMiddleware: Middleware;
7677

77-
private static _baseUrl;
78+
private _baseUrl: string;
79+
80+
private _session: SessionCache;
81+
82+
constructor() {
83+
if (storageAvailable('sessionStorage')) {
84+
this._session = new SessionCache();
85+
}
86+
}
7887

7988
// tslint:disable-next-line: completed-docs
8089
public async execute(context: Context): Promise<void> {
8190
try {
82-
const baseUrl = await MockMiddleware.getBaseUrl();
83-
context.request = baseUrl + escape(context.request as string);
91+
const baseUrl = await this.getBaseUrl();
92+
context.request = baseUrl + encodeURIComponent(context.request as string);
8493
} catch (error) {
8594
// ignore error
8695
}
@@ -96,15 +105,21 @@ class MockMiddleware implements Middleware {
96105
this._nextMiddleware = next;
97106
}
98107

99-
private static async getBaseUrl() {
108+
private async getBaseUrl() {
100109
if (!this._baseUrl) {
101-
try {
102-
// get the url we should be using from the endpoint service
103-
let response = await fetch('https://cdn.graph.office.net/en-us/graph/api/proxy/endpoint');
104-
this._baseUrl = (await response.json()) + '?url=';
105-
} catch {
106-
// fallback to hardcoded value
107-
this._baseUrl = 'https://proxy.apisandbox.msdn.microsoft.com/svc?url=';
110+
const sessionEndpoint = this._session?.getItem('endpointURL');
111+
if (sessionEndpoint) {
112+
this._baseUrl = sessionEndpoint;
113+
} else {
114+
try {
115+
// get the url we should be using from the endpoint service
116+
let response = await fetch('https://cdn.graph.office.net/en-us/graph/api/proxy/endpoint');
117+
this._baseUrl = (await response.json()) + '?url=';
118+
} catch {
119+
// fallback to hardcoded value
120+
this._baseUrl = 'https://proxy.apisandbox.msdn.microsoft.com/svc?url=';
121+
}
122+
this._session?.setItem('endpointURL', this._baseUrl);
108123
}
109124
}
110125

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/**
2+
* -------------------------------------------------------------------------------------------
3+
* Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License.
4+
* See License in the project root for license information.
5+
* -------------------------------------------------------------------------------------------
6+
*/
7+
8+
/**
9+
* Wrapper around the window.sessionStorage API. Use
10+
* this to set, get and clear session items.
11+
*/
12+
export class SessionCache {
13+
private session: Storage;
14+
15+
constructor() {
16+
this.session = window.sessionStorage;
17+
}
18+
19+
setItem(key: string, value: string) {
20+
this.session.setItem(key, value);
21+
}
22+
23+
getItem(key: string): string {
24+
return this.session.getItem(key);
25+
}
26+
27+
clear() {
28+
this.session.clear();
29+
}
30+
}
31+
32+
/**
33+
* Checks if a sessionStorage or a localStorage is available
34+
* for use in a browser.
35+
* @param storageType can be 'sessionStorage' or 'localStorage'.
36+
* @returns true if the storage is available for use.
37+
*/
38+
export function storageAvailable(storageType: string): boolean {
39+
let storage: Storage;
40+
try {
41+
storage = window[storageType];
42+
const x = '__storage_test__';
43+
storage.setItem(x, x);
44+
storage.removeItem(x);
45+
return true;
46+
} catch (e) {
47+
return (
48+
e instanceof DOMException &&
49+
// everything except Firefox
50+
(e.code === 22 ||
51+
// Firefox
52+
e.code === 1014 ||
53+
// test name field too, because code might not be present
54+
// everything except Firefox
55+
e.name === 'QuotaExceededError' ||
56+
// Firefox
57+
e.name === 'NS_ERROR_DOM_QUOTA_REACHED') &&
58+
// acknowledge QuotaExceededError only if there's something already stored
59+
storage &&
60+
storage.length !== 0
61+
);
62+
}
63+
}

0 commit comments

Comments
 (0)