netlify-cli 17.17.1 → 17.17.2
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/dist/lib/images/proxy.d.ts +5 -5
- package/dist/lib/images/proxy.d.ts.map +1 -1
- package/dist/lib/images/proxy.js +43 -30
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/npm-shrinkwrap.json +584 -345
- package/package.json +2 -2
|
@@ -13,17 +13,17 @@ interface QueryParams {
|
|
|
13
13
|
fit?: string;
|
|
14
14
|
position?: string;
|
|
15
15
|
}
|
|
16
|
-
export declare const
|
|
16
|
+
export declare const parseAllRemoteImages: (config: any) => {
|
|
17
17
|
errors: ErrorObject[];
|
|
18
|
-
|
|
18
|
+
remotePatterns: RegExp[];
|
|
19
19
|
};
|
|
20
20
|
interface ErrorObject {
|
|
21
21
|
message: string;
|
|
22
22
|
}
|
|
23
|
-
export declare const
|
|
24
|
-
export declare const
|
|
23
|
+
export declare const handleRemoteImagesErrors: (errors: ErrorObject[]) => Promise<void>;
|
|
24
|
+
export declare const parseRemoteImages: ({ config }: {
|
|
25
25
|
config: any;
|
|
26
|
-
}) => Promise<
|
|
26
|
+
}) => Promise<RegExp[]>;
|
|
27
27
|
export declare const isImageRequest: (req: Request) => boolean;
|
|
28
28
|
export declare const transformImageParams: (query: QueryParams) => string;
|
|
29
29
|
export declare const initializeProxy: ({ config, settings, }: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../../../src/lib/images/proxy.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAM9C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAE5D,eAAO,MAAM,iBAAiB,qBAAqB,CAAA;AAEnD,UAAU,WAAW;IACnB,CAAC,CAAC,EAAE,MAAM,CAAA;IACV,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,CAAC,CAAC,EAAE,MAAM,CAAA;IACV,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,CAAC,CAAC,EAAE,MAAM,CAAA;IACV,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAaD,eAAO,MAAM,
|
|
1
|
+
{"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../../../src/lib/images/proxy.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAM9C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAE5D,eAAO,MAAM,iBAAiB,qBAAqB,CAAA;AAEnD,UAAU,WAAW;IACnB,CAAC,CAAC,EAAE,MAAM,CAAA;IACV,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,CAAC,CAAC,EAAE,MAAM,CAAA;IACV,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,CAAC,CAAC,EAAE,MAAM,CAAA;IACV,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAaD,eAAO,MAAM,oBAAoB;YAAgC,WAAW,EAAE;oBAAkB,MAAM,EAAE;CAqBvG,CAAA;AAED,UAAU,WAAW;IACnB,OAAO,EAAE,MAAM,CAAA;CAChB;AAMD,eAAO,MAAM,wBAAwB,WAA2B,WAAW,EAAE,kBAO5E,CAAA;AAGD,eAAO,MAAM,iBAAiB;;uBAS7B,CAAA;AAED,eAAO,MAAM,cAAc,QAAkB,OAAO,KAAG,OAEtD,CAAA;AAED,eAAO,MAAM,oBAAoB,UAAoB,WAAW,KAAG,MA4BlE,CAAA;AAED,eAAO,MAAM,eAAe;YAIlB,aAAa;cACX,cAAc;0DA4DzB,CAAA"}
|
package/dist/lib/images/proxy.js
CHANGED
|
@@ -4,52 +4,43 @@ import { log, NETLIFYDEVERR } from '../../utils/command-helpers.js';
|
|
|
4
4
|
import { getProxyUrl } from '../../utils/proxy.js';
|
|
5
5
|
export const IMAGE_URL_PATTERN = '/.netlify/images';
|
|
6
6
|
// @ts-expect-error TS(7006) FIXME: Parameter 'config' implicitly has an 'any' type.
|
|
7
|
-
export const
|
|
8
|
-
const
|
|
7
|
+
export const parseAllRemoteImages = function (config) {
|
|
8
|
+
const remotePatterns = [];
|
|
9
9
|
const errors = [];
|
|
10
|
-
const
|
|
11
|
-
if (!
|
|
12
|
-
return { errors,
|
|
10
|
+
const remoteImages = config?.images?.remote_images;
|
|
11
|
+
if (!remoteImages) {
|
|
12
|
+
return { errors, remotePatterns };
|
|
13
13
|
}
|
|
14
|
-
for (const patternString of
|
|
14
|
+
for (const patternString of remoteImages) {
|
|
15
15
|
try {
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
remoteDomains.push(url.hostname);
|
|
19
|
-
}
|
|
20
|
-
else {
|
|
21
|
-
errors.push({ message: `The URL '${patternString}' does not have a valid hostname.` });
|
|
22
|
-
}
|
|
16
|
+
const urlRegex = new RegExp(patternString);
|
|
17
|
+
remotePatterns.push(urlRegex);
|
|
23
18
|
}
|
|
24
19
|
catch (error) {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}
|
|
28
|
-
else {
|
|
29
|
-
errors.push({ message: `Invalid URL '${patternString}': An unknown error occurred` });
|
|
30
|
-
}
|
|
20
|
+
const message = error instanceof Error ? error.message : 'An unknown error occurred';
|
|
21
|
+
errors.push({ message });
|
|
31
22
|
}
|
|
32
23
|
}
|
|
33
|
-
return { errors,
|
|
24
|
+
return { errors, remotePatterns };
|
|
34
25
|
};
|
|
35
26
|
const getErrorMessage = function ({ message }) {
|
|
36
27
|
return message;
|
|
37
28
|
};
|
|
38
|
-
export const
|
|
29
|
+
export const handleRemoteImagesErrors = async function (errors) {
|
|
39
30
|
if (errors.length === 0) {
|
|
40
31
|
return;
|
|
41
32
|
}
|
|
42
33
|
const errorMessage = await errors.map(getErrorMessage).join('\n\n');
|
|
43
|
-
log(NETLIFYDEVERR, `
|
|
34
|
+
log(NETLIFYDEVERR, `Remote images syntax errors:\n${errorMessage}`);
|
|
44
35
|
};
|
|
45
36
|
// @ts-expect-error TS(7031) FIXME: Binding element 'config' implicitly has an 'any' t... Remove this comment to see the full error message
|
|
46
|
-
export const
|
|
37
|
+
export const parseRemoteImages = async function ({ config }) {
|
|
47
38
|
if (!config) {
|
|
48
39
|
return [];
|
|
49
40
|
}
|
|
50
|
-
const { errors,
|
|
51
|
-
await
|
|
52
|
-
return
|
|
41
|
+
const { errors, remotePatterns } = await parseAllRemoteImages(config);
|
|
42
|
+
await handleRemoteImagesErrors(errors);
|
|
43
|
+
return remotePatterns;
|
|
53
44
|
};
|
|
54
45
|
export const isImageRequest = function (req) {
|
|
55
46
|
return req.url.startsWith(IMAGE_URL_PATTERN);
|
|
@@ -79,14 +70,17 @@ export const transformImageParams = function (query) {
|
|
|
79
70
|
.join(',');
|
|
80
71
|
};
|
|
81
72
|
export const initializeProxy = async function ({ config, settings, }) {
|
|
82
|
-
const
|
|
73
|
+
const remoteImages = await parseRemoteImages({ config });
|
|
83
74
|
const devServerUrl = getProxyUrl(settings);
|
|
84
75
|
const ipx = createIPX({
|
|
85
76
|
storage: ipxFSStorage({ dir: config?.build?.publish ?? './public' }),
|
|
86
|
-
httpStorage: ipxHttpStorage({
|
|
77
|
+
httpStorage: ipxHttpStorage({
|
|
78
|
+
allowAllDomains: true,
|
|
79
|
+
}),
|
|
87
80
|
});
|
|
88
81
|
const handler = createIPXNodeServer(ipx);
|
|
89
82
|
const app = express();
|
|
83
|
+
let lastTimeRemoteImagesConfigurationDetailsMessageWasLogged = 0;
|
|
90
84
|
app.use(IMAGE_URL_PATTERN, async (req, res) => {
|
|
91
85
|
const { url, ...query } = req.query;
|
|
92
86
|
const sourceImagePath = url;
|
|
@@ -95,11 +89,30 @@ export const initializeProxy = async function ({ config, settings, }) {
|
|
|
95
89
|
// Construct the full URL for relative paths to request from development server
|
|
96
90
|
const sourceImagePathWithLeadingSlash = sourceImagePath.startsWith('/') ? sourceImagePath : `/${sourceImagePath}`;
|
|
97
91
|
const fullImageUrl = `${devServerUrl}${encodeURIComponent(sourceImagePathWithLeadingSlash)}`;
|
|
98
|
-
console.log(`fullImageUrl: ${fullImageUrl}`);
|
|
99
92
|
req.url = `/${modifiers}/${fullImageUrl}`;
|
|
100
93
|
}
|
|
101
94
|
else {
|
|
102
|
-
// If the image is remote, we
|
|
95
|
+
// If the image is remote, we first check if it's allowed by any of patterns
|
|
96
|
+
if (!remoteImages.some((remoteImage) => remoteImage.test(sourceImagePath))) {
|
|
97
|
+
const remoteImageNotAllowedLogMessage = `Remote image "${sourceImagePath}" source for Image CDN is not allowed.`;
|
|
98
|
+
// Contextual information about the remote image configuration is throttled
|
|
99
|
+
// to avoid spamming the console as it's quite verbose
|
|
100
|
+
// Each not allowed remote image will still be logged, just without configuration details
|
|
101
|
+
if (Date.now() - lastTimeRemoteImagesConfigurationDetailsMessageWasLogged > 1000 * 30) {
|
|
102
|
+
log(`${remoteImageNotAllowedLogMessage}\n\n${remoteImages.length === 0
|
|
103
|
+
? 'Currently no remote images are allowed.'
|
|
104
|
+
: `Currently allowed remote images configuration details:\n${remoteImages
|
|
105
|
+
.map((pattern) => ` - ${pattern}`)
|
|
106
|
+
.join('\n')}`}\n\nRefer to https://ntl.fyi/remote-images for information about how to configure allowed remote images.`);
|
|
107
|
+
lastTimeRemoteImagesConfigurationDetailsMessageWasLogged = Date.now();
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
log(remoteImageNotAllowedLogMessage);
|
|
111
|
+
}
|
|
112
|
+
res.status(400).end();
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
// Construct the full URL for remote paths
|
|
103
116
|
req.url = `/${modifiers}/${encodeURIComponent(sourceImagePath)}`;
|
|
104
117
|
}
|
|
105
118
|
handler(req, res);
|