import {BasicParams, AppDistribution} from '../../../types';
import {appBridgeUrl} from '../../helpers/app-bridge-url';
import {addDocumentResponseHeaders} from '../../helpers/add-response-headers';
import {sanitizeRedirectUrl} from './validate-redirect-url';
import type {RedirectTarget} from '.';
export interface RedirectToOptions {
url: string | URL;
target?: RedirectTarget;
}
export function renderAppBridge(
{api, config}: BasicParams,
request: Request,
redirectTo?: RedirectToOptions,
): never {
let redirectToScript = '';
if (redirectTo) {
const destination = sanitizeRedirectUrl(config.appUrl, redirectTo.url);
const target = redirectTo.target ?? '_top';
redirectToScript = ``;
}
const responseHeaders = new Headers({
'content-type': 'text/html;charset=utf-8',
});
const isEmbeddedApp = config.distribution !== AppDistribution.ShopifyAdmin;
// Sanitize the shop param before using it in response headers (e.g. CSP
// frame-ancestors, Link preconnect). An attacker-controlled `?shop=evil.com`
// must not end up in security-sensitive headers.
const shop = api.utils.sanitizeShop(
new URL(request.url).searchParams.get('shop')!,
);
addDocumentResponseHeaders(responseHeaders, isEmbeddedApp, shop);
throw new Response(
`
${redirectToScript}
`,
{headers: responseHeaders},
);
}