Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
5 changes: 5 additions & 0 deletions .changeset/upset-apples-judge.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"saleor-dashboard": patch
---

Fixed resolving Saleor absolute API URL. It was broken for some setups when extensions received imparital URL
4 changes: 2 additions & 2 deletions src/apps/components/AppWidgets/AppWidgets.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { isUrlAbsolute } from "@dashboard/apps/isUrlAbsolute";
import { AppDetailsUrlMountQueryParams, AppUrls } from "@dashboard/apps/urls";
import { DashboardCard } from "@dashboard/components/Card";
import Link from "@dashboard/components/Link";
import { APP_VERSION, getApiUrl } from "@dashboard/config";
import { APP_VERSION, getAbsoluteApiUrl } from "@dashboard/config";
import { extensionActions } from "@dashboard/extensions/messages";
import { ExtensionWithParams } from "@dashboard/extensions/types";
import { AppExtensionTargetEnum } from "@dashboard/graphql";
Expand Down Expand Up @@ -83,7 +83,7 @@ const IframePost = ({
return (
<Box>
<form ref={formRef} action={extensionUrl} method="POST" target={`ext-frame-${extensionId}`}>
<input type="hidden" name="saleorApiUrl" value={getApiUrl()} />
<input type="hidden" name="saleorApiUrl" value={getAbsoluteApiUrl()} />
<input type="hidden" name="accessToken" value={accessToken} />
<input type="hidden" name="appId" value={appId} />
<>
Expand Down
4 changes: 2 additions & 2 deletions src/apps/urls.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getApiUrl } from "@dashboard/config";
import { getAbsoluteApiUrl } from "@dashboard/config";
import { FlagList } from "@dashboard/featureFlags";
import { stringifyQs } from "@dashboard/utils/urls";
import { ThemeType } from "@saleor/app-sdk/app-bridge";
Expand Down Expand Up @@ -77,7 +77,7 @@ export const AppUrls = {
appUrl: string,
params: AppDetailsUrlQueryParams & AppDetailsCommonParams,
) => {
const apiUrl = new URL(getApiUrl(), window.location.origin).href;
const apiUrl = getAbsoluteApiUrl();
/**
* Use host to preserve port, in case of multiple Saleors running on localhost
*/
Expand Down
60 changes: 60 additions & 0 deletions src/config.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { getAbsoluteApiUrl, getApiUrl } from "@dashboard/config";

describe("global config", () => {
const { location } = window;

beforeEach((): void => {
jest.clearAllMocks();

delete (window as { location?: unknown }).location;

const testingUrl = new URL("https://foo.saleor.cloud/dashboard/product/asdf?aaaa=bbbb");

// Mock window.location for testing purposes
Object.defineProperty(window, "location", {
// URL matches fields from location so we can just put it there
value: testingUrl,
writable: true,
configurable: true,
});
});
afterAll((): void => {
Object.defineProperty(window, "location", {
value: location,
writable: true,
configurable: true,
});
});

describe("getApiUrl", () => {
it.each(["/graphql/", "https://foo.saleor.cloud/graphql/"])(
"Returns value assigned to global window: %s",
param => {
window.__SALEOR_CONFIG__.API_URL = param;

expect(getApiUrl()).toEqual(param);
},
);
});

describe("getAbsoluteApiUrl", () => {
it.each<{ envParam: string; expected: string }>([
{
envParam: "/graphql/",
expected: "https://foo.saleor.cloud/graphql/",
},
{
envParam: "https://foo.saleor.cloud/graphql/",
expected: "https://foo.saleor.cloud/graphql/",
},
{
envParam: "https://other.saleor.cloud/graphql/",
expected: "https://other.saleor.cloud/graphql/",
},
])("Correctly builds absolute url: %s", ({ envParam, expected }) => {
window.__SALEOR_CONFIG__.API_URL = envParam;

expect(getAbsoluteApiUrl()).toEqual(expected);
});
});
});
7 changes: 7 additions & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,14 @@ import { ListSettings, ListViews, Pagination } from "./types";

export const getAppDefaultUri = () => "/";
export const getAppMountUri = () => window?.__SALEOR_CONFIG__?.APP_MOUNT_URI || getAppDefaultUri();
// Can be `/graphql/` so don't rely on it
export const getApiUrl = () => window.__SALEOR_CONFIG__.API_URL;
/**
* Resolves full API URL.
* If config provided with absolute url, will use it directly
* If config is relative, e.g. /graphql/ it will merge it with Dashboard URL
*/
export const getAbsoluteApiUrl = () => new URL(getApiUrl(), window.location.origin).href;
export const SW_INTERVAL = parseInt(process.env.SW_INTERVAL ?? "300", 10);
export const IS_CLOUD_INSTANCE = window.__SALEOR_CONFIG__.IS_CLOUD_INSTANCE === "true";

Expand Down
4 changes: 2 additions & 2 deletions src/extensions/new-tab-actions.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getApiUrl } from "@dashboard/config";
import { getAbsoluteApiUrl } from "@dashboard/config";
import { AppDetailsUrlMountQueryParams } from "@dashboard/extensions/urls";

const createInputElement = (name: string, value: string): HTMLInputElement => {
Expand Down Expand Up @@ -57,7 +57,7 @@ export const newTabActions = {
...args.appParams,
accessToken: args.accessToken,
appId: args.appId,
saleorApiUrl: getApiUrl(),
saleorApiUrl: getAbsoluteApiUrl(),
};

const form = document.createElement("form");
Expand Down
4 changes: 2 additions & 2 deletions src/extensions/urls.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { AppPaths } from "@dashboard/apps/urls";
import { getApiUrl } from "@dashboard/config";
import { getAbsoluteApiUrl } from "@dashboard/config";
import { FlagList } from "@dashboard/featureFlags";
import { Dialog, SingleAction } from "@dashboard/types";
import { stringifyQs } from "@dashboard/utils/urls";
Expand Down Expand Up @@ -155,7 +155,7 @@ export const ExtensionsUrls = {
appUrl: string,
params: AppDetailsUrlQueryParams & AppDetailsCommonParams,
) => {
const apiUrl = new URL(getApiUrl(), window.location.origin).href;
const apiUrl = getAbsoluteApiUrl();
/**
* Use host to preserve port, in case of multiple Saleors running on localhost
*/
Expand Down
Loading