From d8104c6cb6474f8a54b6fe19eee2b7c5444120f1 Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Sat, 12 Mar 2022 15:45:57 -0800 Subject: [PATCH] fix: Detect Pomerium proxy (#3219) * chore: Remove unused DocumentList component * fix: Add support for detecting Pomerium * Refactor to avoid reading cookies on every request * refactor: Just enable cookies for all self-hosted builds * Remove unused userAgent * test: Add window.env to mock --- __mocks__/window.js | 3 ++- app/utils/ApiClient.ts | 21 ++++++++------------- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/__mocks__/window.js b/__mocks__/window.js index 3b827de32..3c3a486fb 100644 --- a/__mocks__/window.js +++ b/__mocks__/window.js @@ -1 +1,2 @@ -window.matchMedia = data => data; +window.matchMedia = (data) => data; +window.env = {}; diff --git a/app/utils/ApiClient.ts b/app/utils/ApiClient.ts index 42a70309b..55441a5be 100644 --- a/app/utils/ApiClient.ts +++ b/app/utils/ApiClient.ts @@ -1,9 +1,9 @@ import retry from "fetch-retry"; import invariant from "invariant"; import { map, trim } from "lodash"; -import { getCookie } from "tiny-cookie"; import EDITOR_VERSION from "@shared/editor/version"; import stores from "~/stores"; +import env from "~/env"; import download from "./download"; import { AuthorizationError, @@ -19,21 +19,15 @@ import { type Options = { baseUrl?: string; }; -// authorization cookie set by a Cloudflare Access proxy -const CF_AUTHORIZATION = getCookie("CF_Authorization"); -// if the cookie is set, we must pass it with all ApiClient requests -const CREDENTIALS = CF_AUTHORIZATION ? "same-origin" : "omit"; const fetchWithRetry = retry(fetch); +const isHosted = env.DEPLOYMENT === "hosted"; class ApiClient { baseUrl: string; - userAgent: string; - constructor(options: Options = {}) { this.baseUrl = options.baseUrl || "/api"; - this.userAgent = "OutlineFrontend"; } fetch = async ( @@ -105,7 +99,11 @@ class ApiClient { body, headers, redirect: "follow", - credentials: CREDENTIALS, + // For the hosted deployment we omit cookies on API requests as they are + // not needed for authentication this offers a performance increase. + // For self-hosted we include them to support a wide variety of + // authenticated proxies, e.g. Pomerium, Cloudflare Access etc. + credentials: isHosted ? "omit" : "same-origin", cache: "no-cache", }); } catch (err) { @@ -203,8 +201,7 @@ class ApiClient { return this.fetch(path, "POST", data, options); }; - // Helpers - constructQueryString = (data: Record) => { + private constructQueryString = (data: Record) => { return map( data, (v, k) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}` @@ -212,6 +209,4 @@ class ApiClient { }; } -export default ApiClient; // In case you don't want to always initiate, just import with `import { client } ...` - export const client = new ApiClient();