@verdaccio/url 11.0.0-6-next.6 → 11.0.0-6-next.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +22 -0
- package/build/index.d.ts +8 -1
- package/build/index.js +18 -22
- package/build/index.js.map +1 -1
- package/package.json +6 -6
- package/src/index.ts +16 -7
- package/tests/getPublicUrl.spec.ts +112 -17
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
+
## 11.0.0-6-next.9
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [82cb0f2b]
|
|
8
|
+
- Updated dependencies [5167bb52]
|
|
9
|
+
- @verdaccio/core@6.0.0-6-next.5
|
|
10
|
+
|
|
11
|
+
## 11.0.0-6-next.8
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- Updated dependencies [24b9be02]
|
|
16
|
+
- @verdaccio/core@6.0.0-6-next.4
|
|
17
|
+
|
|
18
|
+
## 11.0.0-6-next.7
|
|
19
|
+
|
|
20
|
+
### Patch Changes
|
|
21
|
+
|
|
22
|
+
- Updated dependencies [6c1eb021]
|
|
23
|
+
- @verdaccio/core@6.0.0-6-next.3
|
|
24
|
+
|
|
3
25
|
## 11.0.0-6-next.6
|
|
4
26
|
|
|
5
27
|
### Major Changes
|
package/build/index.d.ts
CHANGED
|
@@ -15,4 +15,11 @@ export declare function wrapPrefix(prefix: string | void): string;
|
|
|
15
15
|
*/
|
|
16
16
|
export declare function combineBaseUrl(protocol: string, host: string, prefix?: string): string;
|
|
17
17
|
export declare function validateURL(publicUrl: string | void): boolean;
|
|
18
|
-
export declare
|
|
18
|
+
export declare type RequestOptions = {
|
|
19
|
+
host: string;
|
|
20
|
+
protocol: string;
|
|
21
|
+
headers: {
|
|
22
|
+
[key: string]: string;
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
export declare function getPublicUrl(url_prefix: string | undefined, requestOptions: RequestOptions): string;
|
package/build/index.js
CHANGED
|
@@ -3,30 +3,24 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.isURLhasValidProtocol = isURLhasValidProtocol;
|
|
7
|
-
exports.isHost = isHost;
|
|
8
|
-
exports.getWebProtocol = getWebProtocol;
|
|
9
|
-
exports.wrapPrefix = wrapPrefix;
|
|
10
6
|
exports.combineBaseUrl = combineBaseUrl;
|
|
11
|
-
exports.validateURL = validateURL;
|
|
12
7
|
exports.getPublicUrl = getPublicUrl;
|
|
13
|
-
|
|
14
|
-
|
|
8
|
+
exports.getWebProtocol = getWebProtocol;
|
|
9
|
+
exports.isHost = isHost;
|
|
10
|
+
exports.isURLhasValidProtocol = isURLhasValidProtocol;
|
|
11
|
+
exports.validateURL = validateURL;
|
|
12
|
+
exports.wrapPrefix = wrapPrefix;
|
|
15
13
|
|
|
16
14
|
var _debug = _interopRequireDefault(require("debug"));
|
|
17
15
|
|
|
16
|
+
var _url = require("url");
|
|
17
|
+
|
|
18
18
|
var _isURL = _interopRequireDefault(require("validator/lib/isURL"));
|
|
19
19
|
|
|
20
20
|
var _core = require("@verdaccio/core");
|
|
21
21
|
|
|
22
22
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
23
23
|
|
|
24
|
-
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
|
|
25
|
-
|
|
26
|
-
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
|
|
27
|
-
|
|
28
|
-
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
29
|
-
|
|
30
24
|
const debug = (0, _debug.default)('verdaccio:core:url');
|
|
31
25
|
const validProtocols = ['https', 'http'];
|
|
32
26
|
/**
|
|
@@ -39,14 +33,15 @@ function isURLhasValidProtocol(uri) {
|
|
|
39
33
|
}
|
|
40
34
|
|
|
41
35
|
function isHost(url = '', options = {}) {
|
|
42
|
-
return (0, _isURL.default)(url,
|
|
36
|
+
return (0, _isURL.default)(url, {
|
|
43
37
|
require_host: true,
|
|
44
38
|
allow_trailing_dot: false,
|
|
45
39
|
require_valid_protocol: false,
|
|
46
40
|
// @ts-ignore
|
|
47
41
|
require_port: false,
|
|
48
|
-
require_tld: false
|
|
49
|
-
|
|
42
|
+
require_tld: false,
|
|
43
|
+
...options
|
|
44
|
+
});
|
|
50
45
|
}
|
|
51
46
|
/**
|
|
52
47
|
* Detect running protocol (http or https)
|
|
@@ -60,7 +55,7 @@ function getWebProtocol(headerProtocol, protocol) {
|
|
|
60
55
|
if (typeof headerProtocol === 'string' && headerProtocol !== '') {
|
|
61
56
|
debug('header protocol: %o', protocol);
|
|
62
57
|
const commaIndex = headerProtocol.indexOf(',');
|
|
63
|
-
returnProtocol = commaIndex > 0 ? headerProtocol.
|
|
58
|
+
returnProtocol = commaIndex > 0 ? headerProtocol.slice(0, commaIndex) : headerProtocol;
|
|
64
59
|
} else {
|
|
65
60
|
debug('req protocol: %o', headerProtocol);
|
|
66
61
|
returnProtocol = protocol;
|
|
@@ -114,22 +109,23 @@ function validateURL(publicUrl) {
|
|
|
114
109
|
}
|
|
115
110
|
}
|
|
116
111
|
|
|
117
|
-
function getPublicUrl(url_prefix = '',
|
|
112
|
+
function getPublicUrl(url_prefix = '', requestOptions) {
|
|
118
113
|
if (validateURL(process.env.VERDACCIO_PUBLIC_URL)) {
|
|
119
114
|
const envURL = new _url.URL(wrapPrefix(url_prefix), process.env.VERDACCIO_PUBLIC_URL).href;
|
|
120
115
|
debug('public url by env %o', envURL);
|
|
121
116
|
return envURL;
|
|
122
|
-
} else if (
|
|
117
|
+
} else if (requestOptions.headers['host']) {
|
|
123
118
|
var _process$env$VERDACCI;
|
|
124
119
|
|
|
125
|
-
const host =
|
|
120
|
+
const host = requestOptions.headers['host'];
|
|
126
121
|
|
|
127
122
|
if (!isHost(host)) {
|
|
128
123
|
throw new Error('invalid host');
|
|
129
124
|
}
|
|
130
125
|
|
|
131
|
-
const protoHeader = (_process$env$VERDACCI = process.env.VERDACCIO_FORWARDED_PROTO)
|
|
132
|
-
|
|
126
|
+
const protoHeader = ((_process$env$VERDACCI = process.env.VERDACCIO_FORWARDED_PROTO) === null || _process$env$VERDACCI === void 0 ? void 0 : _process$env$VERDACCI.toLocaleLowerCase()) ?? _core.HEADERS.FORWARDED_PROTO.toLowerCase();
|
|
127
|
+
|
|
128
|
+
const protocol = getWebProtocol(requestOptions.headers[protoHeader], requestOptions.protocol);
|
|
133
129
|
const combinedUrl = combineBaseUrl(protocol, host, url_prefix);
|
|
134
130
|
debug('public url by request %o', combinedUrl);
|
|
135
131
|
return combinedUrl;
|
package/build/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"names":["debug","validProtocols","isURLhasValidProtocol","uri","test","isHost","url","options","require_host","allow_trailing_dot","require_valid_protocol","require_port","require_tld","getWebProtocol","headerProtocol","protocol","returnProtocol","defaultProtocol","commaIndex","indexOf","
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"names":["debug","validProtocols","isURLhasValidProtocol","uri","test","isHost","url","options","require_host","allow_trailing_dot","require_valid_protocol","require_port","require_tld","getWebProtocol","headerProtocol","protocol","returnProtocol","defaultProtocol","commaIndex","indexOf","slice","includes","wrapPrefix","prefix","startsWith","endsWith","combineBaseUrl","host","newPrefix","groupedURI","URL","result","href","validateURL","publicUrl","parsed","replace","Error","err","getPublicUrl","url_prefix","requestOptions","process","env","VERDACCIO_PUBLIC_URL","envURL","headers","protoHeader","VERDACCIO_FORWARDED_PROTO","toLocaleLowerCase","HEADERS","FORWARDED_PROTO","toLowerCase","combinedUrl"],"mappings":"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","sourcesContent":["import buildDebug from 'debug';\nimport { URL } from 'url';\nimport isURLValidator from 'validator/lib/isURL';\n\nimport { HEADERS } from '@verdaccio/core';\n\nconst debug = buildDebug('verdaccio:core:url');\n\nconst validProtocols = ['https', 'http'];\n\n/**\n * Check if URI is starting with \"http://\", \"https://\" or \"//\"\n * @param {string} uri\n */\nexport function isURLhasValidProtocol(uri: string): boolean {\n return /^(https?:)?\\/\\//.test(uri);\n}\n\nexport function isHost(url: string = '', options = {}): boolean {\n return isURLValidator(url, {\n require_host: true,\n allow_trailing_dot: false,\n require_valid_protocol: false,\n // @ts-ignore\n require_port: false,\n require_tld: false,\n ...options,\n });\n}\n\n/**\n * Detect running protocol (http or https)\n */\nexport function getWebProtocol(headerProtocol: string | void, protocol: string): string {\n let returnProtocol;\n const [, defaultProtocol] = validProtocols;\n // HAProxy variant might return http,http with X-Forwarded-Proto\n if (typeof headerProtocol === 'string' && headerProtocol !== '') {\n debug('header protocol: %o', protocol);\n const commaIndex = headerProtocol.indexOf(',');\n returnProtocol = commaIndex > 0 ? headerProtocol.slice(0, commaIndex) : headerProtocol;\n } else {\n debug('req protocol: %o', headerProtocol);\n returnProtocol = protocol;\n }\n\n return validProtocols.includes(returnProtocol) ? returnProtocol : defaultProtocol;\n}\n\nexport function wrapPrefix(prefix: string | void): string {\n if (prefix === '' || typeof prefix === 'undefined' || prefix === null) {\n return '';\n } else if (!prefix.startsWith('/') && prefix.endsWith('/')) {\n return `/${prefix}`;\n } else if (!prefix.startsWith('/') && !prefix.endsWith('/')) {\n return `/${prefix}/`;\n } else if (prefix.startsWith('/') && !prefix.endsWith('/')) {\n return `${prefix}/`;\n } else {\n return prefix;\n }\n}\n\n/**\n * Create base url for registry.\n * @return {String} base registry url\n */\nexport function combineBaseUrl(protocol: string, host: string, prefix: string = ''): string {\n debug('combined protocol %o', protocol);\n debug('combined host %o', host);\n const newPrefix = wrapPrefix(prefix);\n debug('combined prefix %o', newPrefix);\n const groupedURI = new URL(wrapPrefix(prefix), `${protocol}://${host}`);\n const result = groupedURI.href;\n debug('combined url %o', result);\n return result;\n}\n\nexport function validateURL(publicUrl: string | void) {\n try {\n const parsed = new URL(publicUrl as string);\n if (!validProtocols.includes(parsed.protocol.replace(':', ''))) {\n throw Error('invalid protocol');\n }\n return true;\n } catch (err: any) {\n // TODO: add error logger here\n return false;\n }\n}\n\nexport type RequestOptions = {\n host: string;\n protocol: string;\n headers: { [key: string]: string };\n};\n\nexport function getPublicUrl(url_prefix: string = '', requestOptions: RequestOptions): string {\n if (validateURL(process.env.VERDACCIO_PUBLIC_URL as string)) {\n const envURL = new URL(wrapPrefix(url_prefix), process.env.VERDACCIO_PUBLIC_URL as string).href;\n debug('public url by env %o', envURL);\n return envURL;\n } else if (requestOptions.headers['host']) {\n const host = requestOptions.headers['host'];\n if (!isHost(host)) {\n throw new Error('invalid host');\n }\n const protoHeader =\n process.env.VERDACCIO_FORWARDED_PROTO?.toLocaleLowerCase() ??\n HEADERS.FORWARDED_PROTO.toLowerCase();\n const protocol = getWebProtocol(requestOptions.headers[protoHeader], requestOptions.protocol);\n const combinedUrl = combineBaseUrl(protocol, host, url_prefix);\n debug('public url by request %o', combinedUrl);\n return combinedUrl;\n } else {\n return '/';\n }\n}\n"],"file":"index.js"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@verdaccio/url",
|
|
3
|
-
"version": "11.0.0-6-next.
|
|
3
|
+
"version": "11.0.0-6-next.9",
|
|
4
4
|
"description": "url utilities resolver",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"private",
|
|
@@ -34,14 +34,14 @@
|
|
|
34
34
|
"access": "public"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@verdaccio/core": "6.0.0-6-next.
|
|
38
|
-
"debug": "4.3.
|
|
37
|
+
"@verdaccio/core": "6.0.0-6-next.5",
|
|
38
|
+
"debug": "4.3.3",
|
|
39
39
|
"lodash": "4.17.21",
|
|
40
|
-
"validator": "13.
|
|
40
|
+
"validator": "13.7.0"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
|
-
"@verdaccio/types": "11.0.0-6-next.
|
|
44
|
-
"node-mocks-http": "1.
|
|
43
|
+
"@verdaccio/types": "11.0.0-6-next.11",
|
|
44
|
+
"node-mocks-http": "1.11.0"
|
|
45
45
|
},
|
|
46
46
|
"funding": {
|
|
47
47
|
"type": "opencollective",
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { URL } from 'url';
|
|
2
1
|
import buildDebug from 'debug';
|
|
2
|
+
import { URL } from 'url';
|
|
3
3
|
import isURLValidator from 'validator/lib/isURL';
|
|
4
|
+
|
|
4
5
|
import { HEADERS } from '@verdaccio/core';
|
|
5
6
|
|
|
6
7
|
const debug = buildDebug('verdaccio:core:url');
|
|
@@ -37,7 +38,7 @@ export function getWebProtocol(headerProtocol: string | void, protocol: string):
|
|
|
37
38
|
if (typeof headerProtocol === 'string' && headerProtocol !== '') {
|
|
38
39
|
debug('header protocol: %o', protocol);
|
|
39
40
|
const commaIndex = headerProtocol.indexOf(',');
|
|
40
|
-
returnProtocol = commaIndex > 0 ? headerProtocol.
|
|
41
|
+
returnProtocol = commaIndex > 0 ? headerProtocol.slice(0, commaIndex) : headerProtocol;
|
|
41
42
|
} else {
|
|
42
43
|
debug('req protocol: %o', headerProtocol);
|
|
43
44
|
returnProtocol = protocol;
|
|
@@ -88,18 +89,26 @@ export function validateURL(publicUrl: string | void) {
|
|
|
88
89
|
}
|
|
89
90
|
}
|
|
90
91
|
|
|
91
|
-
export
|
|
92
|
+
export type RequestOptions = {
|
|
93
|
+
host: string;
|
|
94
|
+
protocol: string;
|
|
95
|
+
headers: { [key: string]: string };
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
export function getPublicUrl(url_prefix: string = '', requestOptions: RequestOptions): string {
|
|
92
99
|
if (validateURL(process.env.VERDACCIO_PUBLIC_URL as string)) {
|
|
93
100
|
const envURL = new URL(wrapPrefix(url_prefix), process.env.VERDACCIO_PUBLIC_URL as string).href;
|
|
94
101
|
debug('public url by env %o', envURL);
|
|
95
102
|
return envURL;
|
|
96
|
-
} else if (
|
|
97
|
-
const host =
|
|
103
|
+
} else if (requestOptions.headers['host']) {
|
|
104
|
+
const host = requestOptions.headers['host'];
|
|
98
105
|
if (!isHost(host)) {
|
|
99
106
|
throw new Error('invalid host');
|
|
100
107
|
}
|
|
101
|
-
const protoHeader =
|
|
102
|
-
|
|
108
|
+
const protoHeader =
|
|
109
|
+
process.env.VERDACCIO_FORWARDED_PROTO?.toLocaleLowerCase() ??
|
|
110
|
+
HEADERS.FORWARDED_PROTO.toLowerCase();
|
|
111
|
+
const protocol = getWebProtocol(requestOptions.headers[protoHeader], requestOptions.protocol);
|
|
103
112
|
const combinedUrl = combineBaseUrl(protocol, host, url_prefix);
|
|
104
113
|
debug('public url by request %o', combinedUrl);
|
|
105
114
|
return combinedUrl;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as httpMocks from 'node-mocks-http';
|
|
2
2
|
|
|
3
3
|
import { HEADERS } from '@verdaccio/core';
|
|
4
|
+
|
|
4
5
|
import { getPublicUrl } from '../src';
|
|
5
6
|
|
|
6
7
|
describe('host', () => {
|
|
@@ -11,7 +12,13 @@ describe('host', () => {
|
|
|
11
12
|
method: 'GET',
|
|
12
13
|
url: '/',
|
|
13
14
|
});
|
|
14
|
-
expect(
|
|
15
|
+
expect(
|
|
16
|
+
getPublicUrl(undefined, {
|
|
17
|
+
host: req.hostname,
|
|
18
|
+
headers: req.headers as any,
|
|
19
|
+
protocol: req.protocol,
|
|
20
|
+
})
|
|
21
|
+
).toEqual('/');
|
|
15
22
|
});
|
|
16
23
|
|
|
17
24
|
test('get a valid host', () => {
|
|
@@ -22,7 +29,13 @@ describe('host', () => {
|
|
|
22
29
|
},
|
|
23
30
|
url: '/',
|
|
24
31
|
});
|
|
25
|
-
expect(
|
|
32
|
+
expect(
|
|
33
|
+
getPublicUrl(undefined, {
|
|
34
|
+
host: req.hostname,
|
|
35
|
+
headers: req.headers as any,
|
|
36
|
+
protocol: req.protocol,
|
|
37
|
+
})
|
|
38
|
+
).toEqual('http://some.com/');
|
|
26
39
|
});
|
|
27
40
|
|
|
28
41
|
test('check a valid host header injection', () => {
|
|
@@ -31,11 +44,15 @@ describe('host', () => {
|
|
|
31
44
|
headers: {
|
|
32
45
|
host: `some.com"><svg onload="alert(1)">`,
|
|
33
46
|
},
|
|
47
|
+
hostname: `some.com"><svg onload="alert(1)">`,
|
|
34
48
|
url: '/',
|
|
35
49
|
});
|
|
36
50
|
expect(function () {
|
|
37
|
-
|
|
38
|
-
|
|
51
|
+
getPublicUrl('', {
|
|
52
|
+
host: req.hostname,
|
|
53
|
+
headers: req.headers as any,
|
|
54
|
+
protocol: req.protocol,
|
|
55
|
+
});
|
|
39
56
|
}).toThrow('invalid host');
|
|
40
57
|
});
|
|
41
58
|
|
|
@@ -48,7 +65,13 @@ describe('host', () => {
|
|
|
48
65
|
url: '/',
|
|
49
66
|
});
|
|
50
67
|
|
|
51
|
-
expect(
|
|
68
|
+
expect(
|
|
69
|
+
getPublicUrl('/prefix/', {
|
|
70
|
+
host: req.hostname,
|
|
71
|
+
headers: req.headers as any,
|
|
72
|
+
protocol: req.protocol,
|
|
73
|
+
})
|
|
74
|
+
).toEqual('http://some.com/prefix/');
|
|
52
75
|
});
|
|
53
76
|
|
|
54
77
|
test('get a valid host with prefix no trailing', () => {
|
|
@@ -60,7 +83,13 @@ describe('host', () => {
|
|
|
60
83
|
url: '/',
|
|
61
84
|
});
|
|
62
85
|
|
|
63
|
-
expect(
|
|
86
|
+
expect(
|
|
87
|
+
getPublicUrl('/prefix-no-trailing', {
|
|
88
|
+
host: req.hostname,
|
|
89
|
+
headers: req.headers as any,
|
|
90
|
+
protocol: req.protocol,
|
|
91
|
+
})
|
|
92
|
+
).toEqual('http://some.com/prefix-no-trailing/');
|
|
64
93
|
});
|
|
65
94
|
|
|
66
95
|
test('get a valid host with null prefix', () => {
|
|
@@ -72,7 +101,13 @@ describe('host', () => {
|
|
|
72
101
|
url: '/',
|
|
73
102
|
});
|
|
74
103
|
|
|
75
|
-
expect(
|
|
104
|
+
expect(
|
|
105
|
+
getPublicUrl(null, {
|
|
106
|
+
host: req.hostname,
|
|
107
|
+
headers: req.headers as any,
|
|
108
|
+
protocol: req.protocol,
|
|
109
|
+
})
|
|
110
|
+
).toEqual('http://some.com/');
|
|
76
111
|
});
|
|
77
112
|
});
|
|
78
113
|
|
|
@@ -87,7 +122,13 @@ describe('X-Forwarded-Proto', () => {
|
|
|
87
122
|
url: '/',
|
|
88
123
|
});
|
|
89
124
|
|
|
90
|
-
expect(
|
|
125
|
+
expect(
|
|
126
|
+
getPublicUrl(undefined, {
|
|
127
|
+
host: req.hostname,
|
|
128
|
+
headers: req.headers as any,
|
|
129
|
+
protocol: req.protocol,
|
|
130
|
+
})
|
|
131
|
+
).toEqual('https://some.com/');
|
|
91
132
|
});
|
|
92
133
|
|
|
93
134
|
test('with a invalid X-Forwarded-Proto https', () => {
|
|
@@ -100,7 +141,13 @@ describe('X-Forwarded-Proto', () => {
|
|
|
100
141
|
url: '/',
|
|
101
142
|
});
|
|
102
143
|
|
|
103
|
-
expect(
|
|
144
|
+
expect(
|
|
145
|
+
getPublicUrl(undefined, {
|
|
146
|
+
host: req.hostname,
|
|
147
|
+
headers: req.headers as any,
|
|
148
|
+
protocol: req.protocol,
|
|
149
|
+
})
|
|
150
|
+
).toEqual('http://some.com/');
|
|
104
151
|
});
|
|
105
152
|
|
|
106
153
|
test('with a HAProxy X-Forwarded-Proto https', () => {
|
|
@@ -113,7 +160,13 @@ describe('X-Forwarded-Proto', () => {
|
|
|
113
160
|
url: '/',
|
|
114
161
|
});
|
|
115
162
|
|
|
116
|
-
expect(
|
|
163
|
+
expect(
|
|
164
|
+
getPublicUrl(undefined, {
|
|
165
|
+
host: req.hostname,
|
|
166
|
+
headers: req.headers as any,
|
|
167
|
+
protocol: req.protocol,
|
|
168
|
+
})
|
|
169
|
+
).toEqual('https://some.com/');
|
|
117
170
|
});
|
|
118
171
|
|
|
119
172
|
test('with a HAProxy X-Forwarded-Proto different protocol', () => {
|
|
@@ -126,7 +179,13 @@ describe('X-Forwarded-Proto', () => {
|
|
|
126
179
|
url: '/',
|
|
127
180
|
});
|
|
128
181
|
|
|
129
|
-
expect(
|
|
182
|
+
expect(
|
|
183
|
+
getPublicUrl(undefined, {
|
|
184
|
+
host: req.hostname,
|
|
185
|
+
headers: req.headers as any,
|
|
186
|
+
protocol: req.protocol,
|
|
187
|
+
})
|
|
188
|
+
).toEqual('http://some.com/');
|
|
130
189
|
});
|
|
131
190
|
});
|
|
132
191
|
|
|
@@ -142,7 +201,13 @@ describe('env variable', () => {
|
|
|
142
201
|
url: '/',
|
|
143
202
|
});
|
|
144
203
|
|
|
145
|
-
expect(
|
|
204
|
+
expect(
|
|
205
|
+
getPublicUrl(undefined, {
|
|
206
|
+
host: req.hostname,
|
|
207
|
+
headers: req.headers as any,
|
|
208
|
+
protocol: req.protocol,
|
|
209
|
+
})
|
|
210
|
+
).toEqual('https://env.domain.com/');
|
|
146
211
|
delete process.env.VERDACCIO_PUBLIC_URL;
|
|
147
212
|
});
|
|
148
213
|
|
|
@@ -157,7 +222,13 @@ describe('env variable', () => {
|
|
|
157
222
|
url: '/',
|
|
158
223
|
});
|
|
159
224
|
|
|
160
|
-
expect(
|
|
225
|
+
expect(
|
|
226
|
+
getPublicUrl(undefined, {
|
|
227
|
+
host: req.hostname,
|
|
228
|
+
headers: req.headers as any,
|
|
229
|
+
protocol: req.protocol,
|
|
230
|
+
})
|
|
231
|
+
).toEqual('https://env.domain.com/urlPrefix/');
|
|
161
232
|
delete process.env.VERDACCIO_PUBLIC_URL;
|
|
162
233
|
});
|
|
163
234
|
|
|
@@ -172,7 +243,13 @@ describe('env variable', () => {
|
|
|
172
243
|
url: '/',
|
|
173
244
|
});
|
|
174
245
|
|
|
175
|
-
expect(
|
|
246
|
+
expect(
|
|
247
|
+
getPublicUrl(undefined, {
|
|
248
|
+
host: req.hostname,
|
|
249
|
+
headers: req.headers as any,
|
|
250
|
+
protocol: req.protocol,
|
|
251
|
+
})
|
|
252
|
+
).toEqual('https://env.domain.com/');
|
|
176
253
|
delete process.env.VERDACCIO_PUBLIC_URL;
|
|
177
254
|
});
|
|
178
255
|
|
|
@@ -187,7 +264,13 @@ describe('env variable', () => {
|
|
|
187
264
|
url: '/',
|
|
188
265
|
});
|
|
189
266
|
|
|
190
|
-
expect(
|
|
267
|
+
expect(
|
|
268
|
+
getPublicUrl(undefined, {
|
|
269
|
+
host: req.hostname,
|
|
270
|
+
headers: req.headers as any,
|
|
271
|
+
protocol: req.protocol,
|
|
272
|
+
})
|
|
273
|
+
).toEqual('http://some.com/');
|
|
191
274
|
delete process.env.VERDACCIO_PUBLIC_URL;
|
|
192
275
|
});
|
|
193
276
|
|
|
@@ -202,7 +285,13 @@ describe('env variable', () => {
|
|
|
202
285
|
url: '/',
|
|
203
286
|
});
|
|
204
287
|
|
|
205
|
-
expect(
|
|
288
|
+
expect(
|
|
289
|
+
getPublicUrl(undefined, {
|
|
290
|
+
host: req.hostname,
|
|
291
|
+
headers: req.headers as any,
|
|
292
|
+
protocol: req.protocol,
|
|
293
|
+
})
|
|
294
|
+
).toEqual('http://some.com/');
|
|
206
295
|
delete process.env.VERDACCIO_PUBLIC_URL;
|
|
207
296
|
});
|
|
208
297
|
|
|
@@ -217,7 +306,13 @@ describe('env variable', () => {
|
|
|
217
306
|
url: '/',
|
|
218
307
|
});
|
|
219
308
|
|
|
220
|
-
expect(
|
|
309
|
+
expect(
|
|
310
|
+
getPublicUrl(undefined, {
|
|
311
|
+
host: req.hostname,
|
|
312
|
+
headers: req.headers as any,
|
|
313
|
+
protocol: req.protocol,
|
|
314
|
+
})
|
|
315
|
+
).toEqual('http://some/');
|
|
221
316
|
delete process.env.VERDACCIO_PUBLIC_URL;
|
|
222
317
|
});
|
|
223
318
|
});
|