com.jimuwd.xian.registry-proxy 1.0.15 → 1.0.17
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/index.js +12 -10
- package/package.json +1 -1
- package/src/index.ts +19 -18
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createServer } from 'http';
|
|
3
3
|
import { createServer as createHttpsServer } from 'https';
|
|
4
|
-
import {
|
|
4
|
+
import { promises as fsPromises, readFileSync } from 'fs';
|
|
5
5
|
import { load } from 'js-yaml';
|
|
6
6
|
import fetch from 'node-fetch';
|
|
7
7
|
import { homedir } from 'os';
|
|
@@ -39,13 +39,21 @@ const limiter = new ConcurrencyLimiter(5); // 限制为 5 个并发请求
|
|
|
39
39
|
function normalizeUrl(url) {
|
|
40
40
|
try {
|
|
41
41
|
const urlObj = new URL(url);
|
|
42
|
+
// 规范化端口
|
|
42
43
|
if (urlObj.protocol === 'http:' && (urlObj.port === '80' || urlObj.port === '')) {
|
|
43
44
|
urlObj.port = '';
|
|
44
45
|
}
|
|
45
46
|
else if (urlObj.protocol === 'https:' && (urlObj.port === '443' || urlObj.port === '')) {
|
|
46
47
|
urlObj.port = '';
|
|
47
48
|
}
|
|
48
|
-
|
|
49
|
+
// 处理路径末尾斜杠
|
|
50
|
+
const pathname = urlObj.pathname;
|
|
51
|
+
if (pathname.endsWith('.tgz') || pathname.endsWith('.tgz/')) {
|
|
52
|
+
// tarball 文件,去除末尾斜杠
|
|
53
|
+
urlObj.pathname = pathname.replace(/\/+$/, '');
|
|
54
|
+
}
|
|
55
|
+
else if (!pathname.endsWith('/')) {
|
|
56
|
+
// 注册表根路径,确保末尾有斜杠
|
|
49
57
|
urlObj.pathname += '/';
|
|
50
58
|
}
|
|
51
59
|
console.debug(`Normalized URL: ${url} -> ${urlObj.toString()}`);
|
|
@@ -53,13 +61,11 @@ function normalizeUrl(url) {
|
|
|
53
61
|
}
|
|
54
62
|
catch (e) {
|
|
55
63
|
console.error(`Invalid URL: ${url}`, e);
|
|
56
|
-
return url.endsWith('/') ? url :
|
|
64
|
+
return url.endsWith('/') ? url.slice(0, -1) : url; // 默认去除末尾斜杠
|
|
57
65
|
}
|
|
58
66
|
}
|
|
59
67
|
function resolvePath(path) {
|
|
60
|
-
|
|
61
|
-
console.debug(`Resolved path: ${path} -> ${resolved}`);
|
|
62
|
-
return resolved;
|
|
68
|
+
return path.startsWith('~/') ? join(homedir(), path.slice(2)) : resolve(path);
|
|
63
69
|
}
|
|
64
70
|
function removeRegistryPrefix(tarballUrl, registries) {
|
|
65
71
|
try {
|
|
@@ -176,7 +182,6 @@ export async function startProxyServer(proxyConfigPath, localYarnConfigPath, glo
|
|
|
176
182
|
const headers = token ? { Authorization: `Bearer ${token}` } : undefined;
|
|
177
183
|
const response = await fetch(targetUrl, { headers });
|
|
178
184
|
console.log(`Response from ${url}: ${response.status} ${response.statusText}`);
|
|
179
|
-
console.debug(`Response headers from ${url}:`, Object.fromEntries(response.headers.entries()));
|
|
180
185
|
return response.ok ? response : null;
|
|
181
186
|
}
|
|
182
187
|
catch (e) {
|
|
@@ -195,7 +200,6 @@ export async function startProxyServer(proxyConfigPath, localYarnConfigPath, glo
|
|
|
195
200
|
return;
|
|
196
201
|
}
|
|
197
202
|
const contentType = successResponse.headers.get('Content-Type') || 'application/octet-stream';
|
|
198
|
-
console.debug(`Content-Type: ${contentType}`);
|
|
199
203
|
if (contentType.includes('application/json')) {
|
|
200
204
|
try {
|
|
201
205
|
const data = await successResponse.json();
|
|
@@ -231,7 +235,6 @@ export async function startProxyServer(proxyConfigPath, localYarnConfigPath, glo
|
|
|
231
235
|
'Content-Type': successResponse.headers.get('Content-Type'),
|
|
232
236
|
'Content-Length': successResponse.headers.get('Content-Length'),
|
|
233
237
|
};
|
|
234
|
-
console.debug(`Streaming response with headers:`, safeHeaders);
|
|
235
238
|
res.writeHead(successResponse.status, safeHeaders);
|
|
236
239
|
successResponse.body.pipe(res).on('error', (err) => {
|
|
237
240
|
console.error(`Stream error for ${relativePath}:`, err);
|
|
@@ -244,7 +247,6 @@ export async function startProxyServer(proxyConfigPath, localYarnConfigPath, glo
|
|
|
244
247
|
const { key, cert } = proxyConfig.https;
|
|
245
248
|
const keyPath = resolvePath(key);
|
|
246
249
|
const certPath = resolvePath(cert);
|
|
247
|
-
console.debug(`Loading HTTPS key: ${keyPath}, cert: ${certPath}`);
|
|
248
250
|
try {
|
|
249
251
|
await fsPromises.access(keyPath);
|
|
250
252
|
await fsPromises.access(certPath);
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import fetch, {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
2
|
+
import {createServer, Server as HttpServer} from 'http';
|
|
3
|
+
import {createServer as createHttpsServer, Server as HttpsServer} from 'https';
|
|
4
|
+
import {promises as fsPromises, readFileSync} from 'fs';
|
|
5
|
+
import {AddressInfo} from 'net';
|
|
6
|
+
import {load} from 'js-yaml';
|
|
7
|
+
import fetch, {Response} from 'node-fetch';
|
|
8
|
+
import {homedir} from 'os';
|
|
9
|
+
import {join, resolve} from 'path';
|
|
10
|
+
import {URL} from 'url';
|
|
11
11
|
|
|
12
12
|
const { readFile, writeFile } = fsPromises;
|
|
13
13
|
|
|
@@ -59,26 +59,31 @@ const limiter = new ConcurrencyLimiter(5); // 限制为 5 个并发请求
|
|
|
59
59
|
function normalizeUrl(url: string): string {
|
|
60
60
|
try {
|
|
61
61
|
const urlObj = new URL(url);
|
|
62
|
+
// 规范化端口
|
|
62
63
|
if (urlObj.protocol === 'http:' && (urlObj.port === '80' || urlObj.port === '')) {
|
|
63
64
|
urlObj.port = '';
|
|
64
65
|
} else if (urlObj.protocol === 'https:' && (urlObj.port === '443' || urlObj.port === '')) {
|
|
65
66
|
urlObj.port = '';
|
|
66
67
|
}
|
|
67
|
-
|
|
68
|
+
// 处理路径末尾斜杠
|
|
69
|
+
const pathname = urlObj.pathname;
|
|
70
|
+
if (pathname.endsWith('.tgz') || pathname.endsWith('.tgz/')) {
|
|
71
|
+
// tarball 文件,去除末尾斜杠
|
|
72
|
+
urlObj.pathname = pathname.replace(/\/+$/, '');
|
|
73
|
+
} else if (!pathname.endsWith('/')) {
|
|
74
|
+
// 注册表根路径,确保末尾有斜杠
|
|
68
75
|
urlObj.pathname += '/';
|
|
69
76
|
}
|
|
70
77
|
console.debug(`Normalized URL: ${url} -> ${urlObj.toString()}`);
|
|
71
78
|
return urlObj.toString();
|
|
72
79
|
} catch (e) {
|
|
73
80
|
console.error(`Invalid URL: ${url}`, e);
|
|
74
|
-
return url.endsWith('/') ? url :
|
|
81
|
+
return url.endsWith('/') ? url.slice(0, -1) : url; // 默认去除末尾斜杠
|
|
75
82
|
}
|
|
76
83
|
}
|
|
77
84
|
|
|
78
85
|
function resolvePath(path: string): string {
|
|
79
|
-
|
|
80
|
-
console.debug(`Resolved path: ${path} -> ${resolved}`);
|
|
81
|
-
return resolved;
|
|
86
|
+
return path.startsWith('~/') ? join(homedir(), path.slice(2)) : resolve(path);
|
|
82
87
|
}
|
|
83
88
|
|
|
84
89
|
function removeRegistryPrefix(tarballUrl: string, registries: RegistryInfo[]): string {
|
|
@@ -215,7 +220,6 @@ export async function startProxyServer(
|
|
|
215
220
|
const headers = token ? { Authorization: `Bearer ${token}` } : undefined;
|
|
216
221
|
const response = await fetch(targetUrl, { headers });
|
|
217
222
|
console.log(`Response from ${url}: ${response.status} ${response.statusText}`);
|
|
218
|
-
console.debug(`Response headers from ${url}:`, Object.fromEntries(response.headers.entries()));
|
|
219
223
|
return response.ok ? response : null;
|
|
220
224
|
} catch (e) {
|
|
221
225
|
console.error(`Failed to fetch from ${url}:`, e);
|
|
@@ -234,7 +238,6 @@ export async function startProxyServer(
|
|
|
234
238
|
}
|
|
235
239
|
|
|
236
240
|
const contentType = successResponse.headers.get('Content-Type') || 'application/octet-stream';
|
|
237
|
-
console.debug(`Content-Type: ${contentType}`);
|
|
238
241
|
if (contentType.includes('application/json')) {
|
|
239
242
|
try {
|
|
240
243
|
const data = await successResponse.json() as PackageData;
|
|
@@ -268,7 +271,6 @@ export async function startProxyServer(
|
|
|
268
271
|
'Content-Type': successResponse.headers.get('Content-Type'),
|
|
269
272
|
'Content-Length': successResponse.headers.get('Content-Length'),
|
|
270
273
|
};
|
|
271
|
-
console.debug(`Streaming response with headers:`, safeHeaders);
|
|
272
274
|
res.writeHead(successResponse.status, safeHeaders);
|
|
273
275
|
successResponse.body.pipe(res).on('error', (err:any) => {
|
|
274
276
|
console.error(`Stream error for ${relativePath}:`, err);
|
|
@@ -282,7 +284,6 @@ export async function startProxyServer(
|
|
|
282
284
|
const { key, cert } = proxyConfig.https;
|
|
283
285
|
const keyPath = resolvePath(key);
|
|
284
286
|
const certPath = resolvePath(cert);
|
|
285
|
-
console.debug(`Loading HTTPS key: ${keyPath}, cert: ${certPath}`);
|
|
286
287
|
try {
|
|
287
288
|
await fsPromises.access(keyPath);
|
|
288
289
|
await fsPromises.access(certPath);
|