maven-proxy 1.0.3 → 1.1.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/bin/maven-proxy.js
CHANGED
|
@@ -44,7 +44,8 @@ function resolveEffectiveMode(options) {
|
|
|
44
44
|
return forced;
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
// CLI defaults to user mode to load ~/maven-proxy/config unless explicitly overridden.
|
|
48
|
+
return "user";
|
|
48
49
|
}
|
|
49
50
|
|
|
50
51
|
function printHelp() {
|
|
@@ -213,9 +214,7 @@ async function startServer(options) {
|
|
|
213
214
|
}
|
|
214
215
|
|
|
215
216
|
function applyConfigOverrides(options) {
|
|
216
|
-
|
|
217
|
-
process.env.MAVEN_PROXY_CONFIG_MODE = options.mode;
|
|
218
|
-
}
|
|
217
|
+
process.env.MAVEN_PROXY_CONFIG_MODE = resolveEffectiveMode(options);
|
|
219
218
|
|
|
220
219
|
if (options.configPath) {
|
|
221
220
|
process.env.MAVEN_PROXY_CONFIG_FILE = resolvePath(options.configPath);
|
package/package.json
CHANGED
package/src/cache/downloader.js
CHANGED
|
@@ -261,6 +261,27 @@ async function removeIfExists(filePath) {
|
|
|
261
261
|
}
|
|
262
262
|
}
|
|
263
263
|
|
|
264
|
+
function toHost(urlObj) {
|
|
265
|
+
if (!urlObj || typeof urlObj !== "object") {
|
|
266
|
+
return "";
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
return String(urlObj.hostname || "");
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
function toBodyPreview(value, maxLength = 512) {
|
|
273
|
+
const text = String(value || "").replace(/\s+/g, " ").trim();
|
|
274
|
+
if (!text) {
|
|
275
|
+
return "";
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
if (text.length <= maxLength) {
|
|
279
|
+
return text;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
return `${text.slice(0, maxLength)}...(truncated)`;
|
|
283
|
+
}
|
|
284
|
+
|
|
264
285
|
export class Downloader {
|
|
265
286
|
constructor(config, domainMatcher, upstreamProxyManager = null) {
|
|
266
287
|
this.config = config;
|
|
@@ -305,6 +326,8 @@ export class Downloader {
|
|
|
305
326
|
}
|
|
306
327
|
|
|
307
328
|
async #downloadAtomic(urlObj, finalPath, requestHeaders) {
|
|
329
|
+
const startedAt = Date.now();
|
|
330
|
+
|
|
308
331
|
await fs.promises.mkdir(path.dirname(finalPath), { recursive: true });
|
|
309
332
|
const tempPath = `${finalPath}.temp`;
|
|
310
333
|
await removeIfExists(tempPath);
|
|
@@ -367,6 +390,14 @@ export class Downloader {
|
|
|
367
390
|
|
|
368
391
|
await verifyFileSize(tempPath, metadata.contentLength);
|
|
369
392
|
await fs.promises.rename(tempPath, finalPath);
|
|
393
|
+
|
|
394
|
+
const finalStats = await fs.promises.stat(finalPath);
|
|
395
|
+
this.logDownload("download succeeded", downloadUrl, {
|
|
396
|
+
host: hostname,
|
|
397
|
+
targetPath: finalPath,
|
|
398
|
+
size: finalStats.size,
|
|
399
|
+
elapsedMs: Date.now() - startedAt,
|
|
400
|
+
});
|
|
370
401
|
} catch (error) {
|
|
371
402
|
if (isLocalFsWriteError(error)) {
|
|
372
403
|
if (!error.statusCode) {
|
|
@@ -381,6 +412,16 @@ export class Downloader {
|
|
|
381
412
|
});
|
|
382
413
|
}
|
|
383
414
|
|
|
415
|
+
this.logDownload("download failed", urlObj, {
|
|
416
|
+
host: toHost(urlObj),
|
|
417
|
+
code: error.code || "UNKNOWN",
|
|
418
|
+
statusCode: error.statusCode || 0,
|
|
419
|
+
targetPath: finalPath,
|
|
420
|
+
tempPath,
|
|
421
|
+
message: error.message,
|
|
422
|
+
upstreamBodyPreview: toBodyPreview(error.upstreamBody),
|
|
423
|
+
});
|
|
424
|
+
|
|
384
425
|
await removeIfExists(tempPath);
|
|
385
426
|
throw error;
|
|
386
427
|
}
|
|
@@ -74,6 +74,11 @@ function sendText(res, statusCode, message) {
|
|
|
74
74
|
res.end(message);
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
+
function sendErrorText(res, statusCode, message, context = "proxy") {
|
|
78
|
+
console.error(`[${context}] response error status=${statusCode} message=${message}`);
|
|
79
|
+
sendText(res, statusCode, message);
|
|
80
|
+
}
|
|
81
|
+
|
|
77
82
|
function buildUrl(req, forcedProtocol = null) {
|
|
78
83
|
const raw = req.url || "/";
|
|
79
84
|
if (/^https?:\/\//i.test(raw)) {
|
|
@@ -143,7 +148,8 @@ function forwardDirectRequest(req, res, urlObj, timeoutMs, upstreamProxyManager
|
|
|
143
148
|
|
|
144
149
|
upstreamReq.on("error", (error) => {
|
|
145
150
|
if (!res.headersSent) {
|
|
146
|
-
|
|
151
|
+
const message = `Proxy forward failed: ${error.message}`;
|
|
152
|
+
sendErrorText(res, 502, message, "proxy");
|
|
147
153
|
} else {
|
|
148
154
|
res.destroy(error);
|
|
149
155
|
}
|
|
@@ -158,7 +164,8 @@ export function createHttpRequestHandler({ config, downloader, upstreamProxyMana
|
|
|
158
164
|
try {
|
|
159
165
|
urlObj = buildUrl(req, forcedProtocol);
|
|
160
166
|
} catch (error) {
|
|
161
|
-
|
|
167
|
+
const message = `Bad request: ${error.message}`;
|
|
168
|
+
sendErrorText(res, 400, message, "proxy");
|
|
162
169
|
return;
|
|
163
170
|
}
|
|
164
171
|
|
|
@@ -176,7 +183,8 @@ export function createHttpRequestHandler({ config, downloader, upstreamProxyMana
|
|
|
176
183
|
includeHost: ecosystem !== "maven",
|
|
177
184
|
});
|
|
178
185
|
} catch (error) {
|
|
179
|
-
|
|
186
|
+
const message = `Invalid cache path: ${error.message}`;
|
|
187
|
+
sendErrorText(res, 400, message, "proxy");
|
|
180
188
|
return;
|
|
181
189
|
}
|
|
182
190
|
|
|
@@ -210,7 +218,8 @@ export function createHttpRequestHandler({ config, downloader, upstreamProxyMana
|
|
|
210
218
|
|
|
211
219
|
const statusCode = error.statusCode || 502;
|
|
212
220
|
const label = statusCode === 500 ? "Local cache write failed" : "Download failed";
|
|
213
|
-
|
|
221
|
+
const message = `${label}: ${error.message}`;
|
|
222
|
+
sendErrorText(res, statusCode, message, "proxy");
|
|
214
223
|
}
|
|
215
224
|
};
|
|
216
225
|
}
|
|
@@ -218,7 +227,8 @@ export function createHttpRequestHandler({ config, downloader, upstreamProxyMana
|
|
|
218
227
|
export function createMitmHttpServer(handleHttpRequestPath) {
|
|
219
228
|
const server = http.createServer((req, res) => {
|
|
220
229
|
handleHttpRequestPath(req, res, "https:").catch((error) => {
|
|
221
|
-
|
|
230
|
+
const message = `MITM request failed: ${error.message}`;
|
|
231
|
+
sendErrorText(res, 500, message, "proxy-mitm");
|
|
222
232
|
});
|
|
223
233
|
});
|
|
224
234
|
|
|
@@ -7,6 +7,11 @@ function sendText(res, statusCode, message) {
|
|
|
7
7
|
res.end(message);
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
+
function sendErrorText(res, statusCode, message) {
|
|
11
|
+
console.error(`[proxy] response error status=${statusCode} message=${message}`);
|
|
12
|
+
sendText(res, statusCode, message);
|
|
13
|
+
}
|
|
14
|
+
|
|
10
15
|
export function startProxyServer(config, certManager, downloader, matchesDomain, upstreamProxyManager = null) {
|
|
11
16
|
const handleHttpRequestPath = createHttpRequestHandler({
|
|
12
17
|
config,
|
|
@@ -18,7 +23,8 @@ export function startProxyServer(config, certManager, downloader, matchesDomain,
|
|
|
18
23
|
|
|
19
24
|
const server = http.createServer((req, res) => {
|
|
20
25
|
handleHttpRequestPath(req, res, null).catch((error) => {
|
|
21
|
-
|
|
26
|
+
const message = `Proxy request failed: ${error.message}`;
|
|
27
|
+
sendErrorText(res, 500, message);
|
|
22
28
|
});
|
|
23
29
|
});
|
|
24
30
|
|
|
@@ -118,7 +118,13 @@ export class UpstreamProxyManager {
|
|
|
118
118
|
|
|
119
119
|
const cacheKey = `${proxyUrl}`;
|
|
120
120
|
if (!this.agentCache.has(cacheKey)) {
|
|
121
|
-
|
|
121
|
+
// proxy-agent v6 expects resolver-style options for deterministic proxy routing.
|
|
122
|
+
this.agentCache.set(
|
|
123
|
+
cacheKey,
|
|
124
|
+
new ProxyAgent({
|
|
125
|
+
getProxyForUrl: () => proxyUrl,
|
|
126
|
+
}),
|
|
127
|
+
);
|
|
122
128
|
}
|
|
123
129
|
|
|
124
130
|
return this.agentCache.get(cacheKey);
|
package/src/repo/repo-server.js
CHANGED
|
@@ -110,8 +110,10 @@ export function startRepoServer(config, downloader = null) {
|
|
|
110
110
|
fs.createReadStream(filePath).pipe(res);
|
|
111
111
|
} catch (error) {
|
|
112
112
|
const statusCode = error.statusCode && error.statusCode >= 400 ? 502 : 500;
|
|
113
|
+
const message = `Repo server error: ${error.message}`;
|
|
114
|
+
console.error(`[repo] response error status=${statusCode} message=${message}`);
|
|
113
115
|
res.writeHead(statusCode, { "content-type": "text/plain; charset=utf-8" });
|
|
114
|
-
res.end(
|
|
116
|
+
res.end(message);
|
|
115
117
|
}
|
|
116
118
|
});
|
|
117
119
|
|