3b3e83aa7a
Expo 移动壳只接受 http 和 https 基准 H5 地址 非法启动地址回退默认 H5 并继续附加宿主上下文 Deep link 继续限制为同源 H5 路径 补充启动地址检查测试和架构文档
70 lines
1.7 KiB
TypeScript
70 lines
1.7 KiB
TypeScript
import {
|
|
buildMobileShellUrl,
|
|
resolveMobileShellBaseWebUrl,
|
|
type MobileShellUrlOptions,
|
|
} from './mobileShellUrl';
|
|
|
|
const supportedHosts = new Set(['open', 'app']);
|
|
|
|
function extractPathFromNativeUrl(url: URL) {
|
|
if (supportedHosts.has(url.hostname)) {
|
|
return `${url.pathname}${url.search}${url.hash}`;
|
|
}
|
|
|
|
return `${url.hostname ? `/${url.hostname}` : ''}${url.pathname}${url.search}${url.hash}`;
|
|
}
|
|
|
|
function resolveTargetPath(rawUrl: string, webOrigin: string) {
|
|
try {
|
|
const url = new URL(rawUrl);
|
|
if (url.protocol === 'genarrative:') {
|
|
return extractPathFromNativeUrl(url);
|
|
}
|
|
|
|
if (url.protocol !== 'http:' && url.protocol !== 'https:') {
|
|
return null;
|
|
}
|
|
|
|
if (url.origin !== webOrigin) {
|
|
return null;
|
|
}
|
|
|
|
return `${url.pathname}${url.search}${url.hash}`;
|
|
} catch {
|
|
if (!rawUrl.startsWith('/') && !rawUrl.startsWith('#')) {
|
|
return null;
|
|
}
|
|
|
|
try {
|
|
const relativeUrl = new URL(rawUrl, webOrigin);
|
|
if (relativeUrl.origin !== webOrigin) {
|
|
return null;
|
|
}
|
|
|
|
return `${relativeUrl.pathname}${relativeUrl.search}${relativeUrl.hash}`;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
|
|
export function buildMobileShellUrlFromDeepLink(
|
|
rawUrl: string | null | undefined,
|
|
baseWebUrl: string,
|
|
options: MobileShellUrlOptions,
|
|
) {
|
|
const normalizedBaseWebUrl = resolveMobileShellBaseWebUrl(baseWebUrl);
|
|
const defaultUrl = buildMobileShellUrl(normalizedBaseWebUrl, options);
|
|
if (!rawUrl) {
|
|
return defaultUrl;
|
|
}
|
|
|
|
const webOrigin = new URL(normalizedBaseWebUrl).origin;
|
|
const targetPath = resolveTargetPath(rawUrl, webOrigin);
|
|
if (!targetPath) {
|
|
return defaultUrl;
|
|
}
|
|
|
|
return buildMobileShellUrl(new URL(targetPath, webOrigin).toString(), options);
|
|
}
|