/
url.ts
85 lines (75 loc) · 2.68 KB
/
url.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
/*
* @forgerock/javascript-sdk
*
* url.ts
*
* Copyright (c) 2020 ForgeRock. All rights reserved.
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
import type { ConfigurablePaths, CustomPathConfig } from '../config/interfaces';
import type { StringDict } from '../shared/interfaces';
import { getRealmUrlPath } from '../util/realm';
/**
* Returns the base URL including protocol, hostname and any non-standard port.
* The returned URL does not include a trailing slash.
*/
function getBaseUrl(url: URL): string {
const isNonStandardPort =
(url.protocol === 'http:' && ['', '80'].indexOf(url.port) === -1) ||
(url.protocol === 'https:' && ['', '443'].indexOf(url.port) === -1);
const port = isNonStandardPort ? `:${url.port}` : '';
const baseUrl = `${url.protocol}//${url.hostname}${port}`;
return baseUrl;
}
function getEndpointPath(
endpoint: ConfigurablePaths,
realmPath?: string,
customPaths?: CustomPathConfig,
): string {
const realmUrlPath = getRealmUrlPath(realmPath);
const defaultPaths = {
authenticate: `json/${realmUrlPath}/authenticate`,
authorize: `oauth2/${realmUrlPath}/authorize`,
accessToken: `oauth2/${realmUrlPath}/access_token`,
endSession: `oauth2/${realmUrlPath}/connect/endSession`,
userInfo: `oauth2/${realmUrlPath}/userinfo`,
revoke: `oauth2/${realmUrlPath}/token/revoke`,
sessions: `json/${realmUrlPath}/sessions/`,
};
if (customPaths && customPaths[endpoint]) {
// TypeScript is not correctly reading the condition above
// It's thinking that customPaths[endpoint] may result in undefined
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
return customPaths[endpoint];
} else {
return defaultPaths[endpoint];
}
}
function resolve(baseUrl: string, path: string): string {
const url = new URL(baseUrl);
if (path.startsWith('/')) {
return `${getBaseUrl(url)}${path}`;
}
const basePath = url.pathname.split('/');
const destPath = path.split('/').filter((x) => !!x);
const newPath = [...basePath.slice(0, -1), ...destPath].join('/');
return `${getBaseUrl(url)}${newPath}`;
}
function parseQuery(fullUrl: string): StringDict<string> {
const url = new URL(fullUrl);
const query: StringDict<string> = {};
url.searchParams.forEach((v, k) => (query[k] = v));
return query;
}
function stringify(data: StringDict<string | undefined>): string {
const pairs: string[] = [];
for (const k in data) {
if (data[k]) {
pairs.push(k + '=' + encodeURIComponent(data[k] as string));
}
}
return pairs.join('&');
}
export { getBaseUrl, getEndpointPath, parseQuery, resolve, stringify };