Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: set the endpoint URL for the mock-provider in the session storage #1979

Merged
merged 3 commits into from
Dec 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
);
}
}