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
This commit is contained in:
@@ -1 +1,2 @@
|
|||||||
window.matchMedia = data => data;
|
window.matchMedia = (data) => data;
|
||||||
|
window.env = {};
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import retry from "fetch-retry";
|
import retry from "fetch-retry";
|
||||||
import invariant from "invariant";
|
import invariant from "invariant";
|
||||||
import { map, trim } from "lodash";
|
import { map, trim } from "lodash";
|
||||||
import { getCookie } from "tiny-cookie";
|
|
||||||
import EDITOR_VERSION from "@shared/editor/version";
|
import EDITOR_VERSION from "@shared/editor/version";
|
||||||
import stores from "~/stores";
|
import stores from "~/stores";
|
||||||
|
import env from "~/env";
|
||||||
import download from "./download";
|
import download from "./download";
|
||||||
import {
|
import {
|
||||||
AuthorizationError,
|
AuthorizationError,
|
||||||
@@ -19,21 +19,15 @@ import {
|
|||||||
type Options = {
|
type Options = {
|
||||||
baseUrl?: string;
|
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 fetchWithRetry = retry(fetch);
|
||||||
|
const isHosted = env.DEPLOYMENT === "hosted";
|
||||||
|
|
||||||
class ApiClient {
|
class ApiClient {
|
||||||
baseUrl: string;
|
baseUrl: string;
|
||||||
|
|
||||||
userAgent: string;
|
|
||||||
|
|
||||||
constructor(options: Options = {}) {
|
constructor(options: Options = {}) {
|
||||||
this.baseUrl = options.baseUrl || "/api";
|
this.baseUrl = options.baseUrl || "/api";
|
||||||
this.userAgent = "OutlineFrontend";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fetch = async (
|
fetch = async (
|
||||||
@@ -105,7 +99,11 @@ class ApiClient {
|
|||||||
body,
|
body,
|
||||||
headers,
|
headers,
|
||||||
redirect: "follow",
|
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",
|
cache: "no-cache",
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -203,8 +201,7 @@ class ApiClient {
|
|||||||
return this.fetch(path, "POST", data, options);
|
return this.fetch(path, "POST", data, options);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Helpers
|
private constructQueryString = (data: Record<string, any>) => {
|
||||||
constructQueryString = (data: Record<string, any>) => {
|
|
||||||
return map(
|
return map(
|
||||||
data,
|
data,
|
||||||
(v, k) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`
|
(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();
|
export const client = new ApiClient();
|
||||||
|
|||||||
Reference in New Issue
Block a user