@verdaccio/url 12.0.0-next.6 → 13.0.0-next-8.1
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 +139 -0
- package/build/index.d.ts +4 -4
- package/build/index.js +10 -2
- package/build/index.js.map +1 -1
- package/package.json +6 -6
- package/src/index.ts +15 -4
- package/tests/combineBaseUrl.spec.ts +2 -0
- package/tests/getPublicUrl.spec.ts +27 -1
- package/tests/getWebProtocol.spec.ts +2 -0
- package/tests/htttProtocol.spec.ts +2 -0
- package/tests/validHost.spec.ts +2 -0
- package/jest.config.js +0 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,144 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
+
## 13.0.0-next-8.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- @verdaccio/core@8.0.0-next-8.1
|
|
8
|
+
|
|
9
|
+
## 13.0.0-next-8.0
|
|
10
|
+
|
|
11
|
+
### Major Changes
|
|
12
|
+
|
|
13
|
+
- chore: move v7 next to v8 next
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- Updated dependencies
|
|
18
|
+
- @verdaccio/core@8.0.0-next-8.0
|
|
19
|
+
|
|
20
|
+
## 12.0.0
|
|
21
|
+
|
|
22
|
+
### Major Changes
|
|
23
|
+
|
|
24
|
+
- 47f61c6: feat!: bump to v7
|
|
25
|
+
- e7ebccb: update major dependencies, remove old nodejs support
|
|
26
|
+
|
|
27
|
+
### Minor Changes
|
|
28
|
+
|
|
29
|
+
- daceb6d: restore legacy support
|
|
30
|
+
- f047cc8: refactor: auth with legacy sign support
|
|
31
|
+
|
|
32
|
+
### Patch Changes
|
|
33
|
+
|
|
34
|
+
- b0946b2: Improved TS types for renderHTML() and related functions (by @tobbe in #4605)
|
|
35
|
+
- ccc7bd1: fix(middleware): link to favicon in template
|
|
36
|
+
- 38b1e82: patch(core/url): Throw if VERDACCIO_FORWARDED_PROTO resolves to an array (#4613 by @Tobbe)
|
|
37
|
+
- Updated dependencies [47f61c6]
|
|
38
|
+
- Updated dependencies [6e764e3]
|
|
39
|
+
- Updated dependencies [daceb6d]
|
|
40
|
+
- Updated dependencies [e7ebccb]
|
|
41
|
+
- Updated dependencies [f047cc8]
|
|
42
|
+
- Updated dependencies [7c9f3cf]
|
|
43
|
+
- Updated dependencies [bd8703e]
|
|
44
|
+
- @verdaccio/core@7.0.0
|
|
45
|
+
|
|
46
|
+
## 12.0.0-next-8.21
|
|
47
|
+
|
|
48
|
+
### Patch Changes
|
|
49
|
+
|
|
50
|
+
- Updated dependencies [7c9f3cf]
|
|
51
|
+
- @verdaccio/core@7.0.0-next-8.21
|
|
52
|
+
|
|
53
|
+
## 12.0.0-next-7.20
|
|
54
|
+
|
|
55
|
+
### Patch Changes
|
|
56
|
+
|
|
57
|
+
- ccc7bd1: fix(middleware): link to favicon in template
|
|
58
|
+
- @verdaccio/core@7.0.0-next-7.20
|
|
59
|
+
|
|
60
|
+
## 12.0.0-next-7.19
|
|
61
|
+
|
|
62
|
+
### Patch Changes
|
|
63
|
+
|
|
64
|
+
- @verdaccio/core@7.0.0-next-7.19
|
|
65
|
+
|
|
66
|
+
## 12.0.0-next-7.18
|
|
67
|
+
|
|
68
|
+
### Patch Changes
|
|
69
|
+
|
|
70
|
+
- @verdaccio/core@7.0.0-next-7.18
|
|
71
|
+
|
|
72
|
+
## 12.0.0-next-7.17
|
|
73
|
+
|
|
74
|
+
### Patch Changes
|
|
75
|
+
|
|
76
|
+
- Updated dependencies [6e764e3]
|
|
77
|
+
- @verdaccio/core@7.0.0-next-7.17
|
|
78
|
+
|
|
79
|
+
## 12.0.0-next-7.16
|
|
80
|
+
|
|
81
|
+
### Patch Changes
|
|
82
|
+
|
|
83
|
+
- 38b1e82: patch(core/url): Throw if VERDACCIO_FORWARDED_PROTO resolves to an array (#4613 by @Tobbe)
|
|
84
|
+
- @verdaccio/core@7.0.0-next-7.16
|
|
85
|
+
|
|
86
|
+
## 12.0.0-next-7.15
|
|
87
|
+
|
|
88
|
+
### Patch Changes
|
|
89
|
+
|
|
90
|
+
- Updated dependencies [bd8703e]
|
|
91
|
+
- @verdaccio/core@7.0.0-next-7.15
|
|
92
|
+
|
|
93
|
+
## 12.0.0-next-7.14
|
|
94
|
+
|
|
95
|
+
### Patch Changes
|
|
96
|
+
|
|
97
|
+
- b0946b2: Improved TS types for renderHTML() and related functions (by @tobbe in #4605)
|
|
98
|
+
- @verdaccio/core@7.0.0-next-7.14
|
|
99
|
+
|
|
100
|
+
## 12.0.0-next-7.13
|
|
101
|
+
|
|
102
|
+
### Patch Changes
|
|
103
|
+
|
|
104
|
+
- @verdaccio/core@7.0.0-next-7.13
|
|
105
|
+
|
|
106
|
+
## 12.0.0-next-7.12
|
|
107
|
+
|
|
108
|
+
### Patch Changes
|
|
109
|
+
|
|
110
|
+
- @verdaccio/core@7.0.0-next-7.12
|
|
111
|
+
|
|
112
|
+
## 12.0.0-next-7.11
|
|
113
|
+
|
|
114
|
+
### Patch Changes
|
|
115
|
+
|
|
116
|
+
- @verdaccio/core@7.0.0-next-7.11
|
|
117
|
+
|
|
118
|
+
## 12.0.0-next-7.10
|
|
119
|
+
|
|
120
|
+
### Patch Changes
|
|
121
|
+
|
|
122
|
+
- @verdaccio/core@7.0.0-next-7.10
|
|
123
|
+
|
|
124
|
+
## 12.0.0-next-7.9
|
|
125
|
+
|
|
126
|
+
### Patch Changes
|
|
127
|
+
|
|
128
|
+
- @verdaccio/core@7.0.0-next-7.9
|
|
129
|
+
|
|
130
|
+
## 12.0.0-next-7.8
|
|
131
|
+
|
|
132
|
+
### Patch Changes
|
|
133
|
+
|
|
134
|
+
- @verdaccio/core@7.0.0-next-7.8
|
|
135
|
+
|
|
136
|
+
## 12.0.0-next-7.7
|
|
137
|
+
|
|
138
|
+
### Patch Changes
|
|
139
|
+
|
|
140
|
+
- @verdaccio/core@7.0.0-next-7.7
|
|
141
|
+
|
|
3
142
|
## 12.0.0-next.6
|
|
4
143
|
|
|
5
144
|
### Patch Changes
|
package/build/index.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import type { IncomingHttpHeaders } from 'node:http';
|
|
1
3
|
/**
|
|
2
4
|
* Check if URI is starting with "http://", "https://" or "//"
|
|
3
5
|
* @param {string} uri
|
|
@@ -7,7 +9,7 @@ export declare function isHost(url?: string, options?: {}): boolean;
|
|
|
7
9
|
/**
|
|
8
10
|
* Detect running protocol (http or https)
|
|
9
11
|
*/
|
|
10
|
-
export declare function getWebProtocol(headerProtocol: string |
|
|
12
|
+
export declare function getWebProtocol(headerProtocol: string | undefined, protocol: string): string;
|
|
11
13
|
export declare function wrapPrefix(prefix: string | void): string;
|
|
12
14
|
/**
|
|
13
15
|
* Create base url for registry.
|
|
@@ -27,9 +29,7 @@ export type RequestOptions = {
|
|
|
27
29
|
/**
|
|
28
30
|
* Request headers.
|
|
29
31
|
*/
|
|
30
|
-
headers:
|
|
31
|
-
[key: string]: string;
|
|
32
|
-
};
|
|
32
|
+
headers: IncomingHttpHeaders;
|
|
33
33
|
remoteAddress?: string;
|
|
34
34
|
/**
|
|
35
35
|
* Logged username the request, usually after token verification.
|
package/build/index.js
CHANGED
|
@@ -15,7 +15,7 @@ var _debug = _interopRequireDefault(require("debug"));
|
|
|
15
15
|
var _url = require("url");
|
|
16
16
|
var _validator = _interopRequireDefault(require("validator"));
|
|
17
17
|
var _core = require("@verdaccio/core");
|
|
18
|
-
function _interopRequireDefault(
|
|
18
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
19
19
|
const debug = (0, _debug.default)('verdaccio:core:url');
|
|
20
20
|
const validProtocols = ['https', 'http'];
|
|
21
21
|
|
|
@@ -106,8 +106,16 @@ function getPublicUrl(url_prefix = '', requestOptions) {
|
|
|
106
106
|
if (!isHost(host)) {
|
|
107
107
|
throw new Error('invalid host');
|
|
108
108
|
}
|
|
109
|
+
|
|
110
|
+
// 'X-Forwarded-Proto' is the default header
|
|
109
111
|
const protoHeader = (_process$env$VERDACCI = (_process$env$VERDACCI2 = process.env.VERDACCIO_FORWARDED_PROTO) === null || _process$env$VERDACCI2 === void 0 ? void 0 : _process$env$VERDACCI2.toLocaleLowerCase()) !== null && _process$env$VERDACCI !== void 0 ? _process$env$VERDACCI : _core.HEADERS.FORWARDED_PROTO.toLowerCase();
|
|
110
|
-
const
|
|
112
|
+
const forwardedProtocolHeaderValue = requestOptions.headers[protoHeader];
|
|
113
|
+
if (Array.isArray(forwardedProtocolHeaderValue)) {
|
|
114
|
+
// This really should never happen - only set-cookie is allowed to have
|
|
115
|
+
// multiple values.
|
|
116
|
+
throw new Error('invalid forwarded protocol header value. Reading header ' + protoHeader);
|
|
117
|
+
}
|
|
118
|
+
const protocol = getWebProtocol(forwardedProtocolHeaderValue, requestOptions.protocol);
|
|
111
119
|
const combinedUrl = combineBaseUrl(protocol, host, url_prefix);
|
|
112
120
|
debug('public url by request %o', combinedUrl);
|
|
113
121
|
return combinedUrl;
|
package/build/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["_debug","_interopRequireDefault","require","_url","_validator","_core","
|
|
1
|
+
{"version":3,"file":"index.js","names":["_debug","_interopRequireDefault","require","_url","_validator","_core","e","__esModule","default","debug","buildDebug","validProtocols","isURLhasValidProtocol","uri","test","isHost","url","options","validator","isURL","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","_process$env$VERDACCI","_process$env$VERDACCI2","protoHeader","VERDACCIO_FORWARDED_PROTO","toLocaleLowerCase","HEADERS","FORWARDED_PROTO","toLowerCase","forwardedProtocolHeaderValue","Array","isArray","combinedUrl","exports"],"sources":["../src/index.ts"],"sourcesContent":["import buildDebug from 'debug';\nimport type { IncomingHttpHeaders } from 'node:http';\nimport { URL } from 'url';\nimport validator from 'validator';\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 validator.isURL(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 | undefined, 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 /**\n * Request host.\n */\n host: string;\n /**\n * Request protocol.\n */\n protocol: string;\n /**\n * Request headers.\n */\n headers: IncomingHttpHeaders;\n remoteAddress?: string;\n /**\n * Logged username the request, usually after token verification.\n */\n username?: 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\n // 'X-Forwarded-Proto' is the default header\n const protoHeader: string =\n process.env.VERDACCIO_FORWARDED_PROTO?.toLocaleLowerCase() ??\n HEADERS.FORWARDED_PROTO.toLowerCase();\n const forwardedProtocolHeaderValue = requestOptions.headers[protoHeader];\n\n if (Array.isArray(forwardedProtocolHeaderValue)) {\n // This really should never happen - only set-cookie is allowed to have\n // multiple values.\n throw new Error('invalid forwarded protocol header value. Reading header ' + protoHeader);\n }\n\n const protocol = getWebProtocol(forwardedProtocolHeaderValue, 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\nexport const isURL = validator.isURL;\n"],"mappings":"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","ignoreList":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@verdaccio/url",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "13.0.0-next-8.1",
|
|
4
4
|
"description": "url utilities resolver",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"private",
|
|
@@ -33,13 +33,13 @@
|
|
|
33
33
|
"access": "public"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@verdaccio/core": "
|
|
37
|
-
"debug": "4.3.
|
|
36
|
+
"@verdaccio/core": "8.0.0-next-8.1",
|
|
37
|
+
"debug": "4.3.7",
|
|
38
38
|
"lodash": "4.17.21",
|
|
39
|
-
"validator": "13.
|
|
39
|
+
"validator": "13.12.0"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@verdaccio/types": "
|
|
42
|
+
"@verdaccio/types": "13.0.0-next-8.0",
|
|
43
43
|
"node-mocks-http": "1.14.1"
|
|
44
44
|
},
|
|
45
45
|
"funding": {
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
},
|
|
49
49
|
"scripts": {
|
|
50
50
|
"clean": "rimraf ./build",
|
|
51
|
-
"test": "
|
|
51
|
+
"test": "vitest run",
|
|
52
52
|
"type-check": "tsc --noEmit -p tsconfig.build.json",
|
|
53
53
|
"build:types": "tsc --emitDeclarationOnly -p tsconfig.build.json",
|
|
54
54
|
"build:js": "babel src/ --out-dir build/ --copy-files --extensions \".ts,.tsx\" --source-maps",
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import buildDebug from 'debug';
|
|
2
|
+
import type { IncomingHttpHeaders } from 'node:http';
|
|
2
3
|
import { URL } from 'url';
|
|
3
4
|
import validator from 'validator';
|
|
4
5
|
|
|
@@ -31,7 +32,7 @@ export function isHost(url: string = '', options = {}): boolean {
|
|
|
31
32
|
/**
|
|
32
33
|
* Detect running protocol (http or https)
|
|
33
34
|
*/
|
|
34
|
-
export function getWebProtocol(headerProtocol: string |
|
|
35
|
+
export function getWebProtocol(headerProtocol: string | undefined, protocol: string): string {
|
|
35
36
|
let returnProtocol;
|
|
36
37
|
const [, defaultProtocol] = validProtocols;
|
|
37
38
|
// HAProxy variant might return http,http with X-Forwarded-Proto
|
|
@@ -101,7 +102,7 @@ export type RequestOptions = {
|
|
|
101
102
|
/**
|
|
102
103
|
* Request headers.
|
|
103
104
|
*/
|
|
104
|
-
headers:
|
|
105
|
+
headers: IncomingHttpHeaders;
|
|
105
106
|
remoteAddress?: string;
|
|
106
107
|
/**
|
|
107
108
|
* Logged username the request, usually after token verification.
|
|
@@ -119,10 +120,20 @@ export function getPublicUrl(url_prefix: string = '', requestOptions: RequestOpt
|
|
|
119
120
|
if (!isHost(host)) {
|
|
120
121
|
throw new Error('invalid host');
|
|
121
122
|
}
|
|
122
|
-
|
|
123
|
+
|
|
124
|
+
// 'X-Forwarded-Proto' is the default header
|
|
125
|
+
const protoHeader: string =
|
|
123
126
|
process.env.VERDACCIO_FORWARDED_PROTO?.toLocaleLowerCase() ??
|
|
124
127
|
HEADERS.FORWARDED_PROTO.toLowerCase();
|
|
125
|
-
const
|
|
128
|
+
const forwardedProtocolHeaderValue = requestOptions.headers[protoHeader];
|
|
129
|
+
|
|
130
|
+
if (Array.isArray(forwardedProtocolHeaderValue)) {
|
|
131
|
+
// This really should never happen - only set-cookie is allowed to have
|
|
132
|
+
// multiple values.
|
|
133
|
+
throw new Error('invalid forwarded protocol header value. Reading header ' + protoHeader);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const protocol = getWebProtocol(forwardedProtocolHeaderValue, requestOptions.protocol);
|
|
126
137
|
const combinedUrl = combineBaseUrl(protocol, host, url_prefix);
|
|
127
138
|
debug('public url by request %o', combinedUrl);
|
|
128
139
|
return combinedUrl;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as httpMocks from 'node-mocks-http';
|
|
2
|
+
import { describe, expect, test } from 'vitest';
|
|
2
3
|
|
|
3
4
|
import { HEADERS } from '@verdaccio/core';
|
|
4
5
|
|
|
@@ -102,7 +103,7 @@ describe('host', () => {
|
|
|
102
103
|
});
|
|
103
104
|
|
|
104
105
|
expect(
|
|
105
|
-
getPublicUrl(
|
|
106
|
+
getPublicUrl(undefined, {
|
|
106
107
|
host: req.hostname,
|
|
107
108
|
headers: req.headers as any,
|
|
108
109
|
protocol: req.protocol,
|
|
@@ -316,6 +317,31 @@ describe('env variable', () => {
|
|
|
316
317
|
delete process.env.VERDACCIO_FORWARDED_PROTO;
|
|
317
318
|
});
|
|
318
319
|
|
|
320
|
+
test('with the VERDACCIO_FORWARDED_PROTO environment variable set to "set-cookie"', () => {
|
|
321
|
+
process.env.VERDACCIO_FORWARDED_PROTO = 'set-cookie';
|
|
322
|
+
const req = httpMocks.createRequest({
|
|
323
|
+
method: 'GET',
|
|
324
|
+
headers: {
|
|
325
|
+
host: 'some.com',
|
|
326
|
+
cookie: 'name=value; name2=value2;',
|
|
327
|
+
'set-cookie': [
|
|
328
|
+
'cookieName1=value; expires=Tue, 19 Jan 2038 03:14:07 GMT;',
|
|
329
|
+
'cookieName2=value; expires=Tue, 19 Jan 2038 03:14:07 GMT;',
|
|
330
|
+
],
|
|
331
|
+
},
|
|
332
|
+
url: '/',
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
expect(() =>
|
|
336
|
+
getPublicUrl('/test/', {
|
|
337
|
+
host: req.hostname,
|
|
338
|
+
headers: req.headers as any,
|
|
339
|
+
protocol: req.protocol,
|
|
340
|
+
})
|
|
341
|
+
).toThrow('invalid forwarded protocol header value. Reading header set-cookie');
|
|
342
|
+
delete process.env.VERDACCIO_FORWARDED_PROTO;
|
|
343
|
+
});
|
|
344
|
+
|
|
319
345
|
test('with a invalid X-Forwarded-Proto https and host injection with invalid host', () => {
|
|
320
346
|
process.env.VERDACCIO_PUBLIC_URL = 'http://injection.test.com"><svg onload="alert(1)">';
|
|
321
347
|
const req = httpMocks.createRequest({
|
package/tests/validHost.spec.ts
CHANGED
package/jest.config.js
DELETED