Skip to content

Commit

Permalink
feat: cache the endpoint url for the mock-provider in session storage (
Browse files Browse the repository at this point in the history
…#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
  • Loading branch information
musale authored Dec 14, 2022
1 parent adca163 commit b2cbbf2
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 11 deletions.
37 changes: 26 additions & 11 deletions packages/mgt-element/src/mock/MockGraph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
RetryHandlerOptions,
TelemetryHandler
} from '@microsoft/microsoft-graph-client';
import { SessionCache, storageAvailable } from '../utils/SessionCache';
import { MgtBaseComponent } from '../components/baseComponent';
import { Graph } from '../Graph';
import { chainMiddleware } from '../utils/GraphHelpers';
Expand Down Expand Up @@ -74,13 +75,21 @@ class MockMiddleware implements Middleware {
*/
private _nextMiddleware: Middleware;

private static _baseUrl;
private _baseUrl: string;

private _session: SessionCache;

constructor() {
if (storageAvailable('sessionStorage')) {
this._session = new SessionCache();
}
}

// tslint:disable-next-line: completed-docs
public async execute(context: Context): Promise<void> {
try {
const baseUrl = await MockMiddleware.getBaseUrl();
context.request = baseUrl + escape(context.request as string);
const baseUrl = await this.getBaseUrl();
context.request = baseUrl + encodeURIComponent(context.request as string);
} catch (error) {
// ignore error
}
Expand All @@ -96,15 +105,21 @@ class MockMiddleware implements Middleware {
this._nextMiddleware = next;
}

private static async getBaseUrl() {
private async getBaseUrl() {
if (!this._baseUrl) {
try {
// get the url we should be using from the endpoint service
let response = await fetch('https://cdn.graph.office.net/en-us/graph/api/proxy/endpoint');
this._baseUrl = (await response.json()) + '?url=';
} catch {
// fallback to hardcoded value
this._baseUrl = 'https://proxy.apisandbox.msdn.microsoft.com/svc?url=';
const sessionEndpoint = this._session?.getItem('endpointURL');
if (sessionEndpoint) {
this._baseUrl = sessionEndpoint;
} else {
try {
// get the url we should be using from the endpoint service
let response = await fetch('https://cdn.graph.office.net/en-us/graph/api/proxy/endpoint');
this._baseUrl = (await response.json()) + '?url=';
} catch {
// fallback to hardcoded value
this._baseUrl = 'https://proxy.apisandbox.msdn.microsoft.com/svc?url=';
}
this._session?.setItem('endpointURL', this._baseUrl);
}
}

Expand Down
63 changes: 63 additions & 0 deletions packages/mgt-element/src/utils/SessionCache.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/**
* -------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License.
* See License in the project root for license information.
* -------------------------------------------------------------------------------------------
*/

/**
* Wrapper around the window.sessionStorage API. Use
* this to set, get and clear session items.
*/
export class SessionCache {
private session: Storage;

constructor() {
this.session = window.sessionStorage;
}

setItem(key: string, value: string) {
this.session.setItem(key, value);
}

getItem(key: string): string {
return this.session.getItem(key);
}

clear() {
this.session.clear();
}
}

/**
* Checks if a sessionStorage or a localStorage is available
* for use in a browser.
* @param storageType can be 'sessionStorage' or 'localStorage'.
* @returns true if the storage is available for use.
*/
export function storageAvailable(storageType: string): boolean {
let storage: Storage;
try {
storage = window[storageType];
const x = '__storage_test__';
storage.setItem(x, x);
storage.removeItem(x);
return true;
} catch (e) {
return (
e instanceof DOMException &&
// everything except Firefox
(e.code === 22 ||
// Firefox
e.code === 1014 ||
// test name field too, because code might not be present
// everything except Firefox
e.name === 'QuotaExceededError' ||
// Firefox
e.name === 'NS_ERROR_DOM_QUOTA_REACHED') &&
// acknowledge QuotaExceededError only if there's something already stored
storage &&
storage.length !== 0
);
}
}

0 comments on commit b2cbbf2

Please sign in to comment.