com.jimuwd.xian.registry-proxy 1.0.25 → 1.0.27
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 +25 -25
- package/package.json +1 -1
- package/src/index.ts +22 -26
package/dist/index.js
CHANGED
|
@@ -34,49 +34,49 @@ class ConcurrencyLimiter {
|
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
36
|
const limiter = new ConcurrencyLimiter(3);
|
|
37
|
-
function
|
|
37
|
+
function removeEndingSlashAndForceStartingSlash(str) {
|
|
38
38
|
if (!str)
|
|
39
39
|
return '/';
|
|
40
|
-
|
|
40
|
+
let trimmed = str.trim();
|
|
41
|
+
if (trimmed === '/')
|
|
41
42
|
return '/';
|
|
42
|
-
|
|
43
|
+
if (trimmed === '')
|
|
44
|
+
return '/';
|
|
45
|
+
if (!trimmed.startsWith('/'))
|
|
46
|
+
trimmed = '/' + trimmed;
|
|
47
|
+
return trimmed.replace(/\/+$/, '');
|
|
43
48
|
}
|
|
44
|
-
function normalizeUrl(
|
|
49
|
+
function normalizeUrl(httpOrHttpsUrl) {
|
|
50
|
+
if (!httpOrHttpsUrl.startsWith("http"))
|
|
51
|
+
throw new Error("http(s) url must starts with 'http(s)://'");
|
|
45
52
|
try {
|
|
46
|
-
const urlObj = new URL(
|
|
53
|
+
const urlObj = new URL(httpOrHttpsUrl);
|
|
47
54
|
if (urlObj.protocol === 'http:' && (urlObj.port === '80' || urlObj.port === '')) {
|
|
48
55
|
urlObj.port = '';
|
|
49
56
|
}
|
|
50
57
|
else if (urlObj.protocol === 'https:' && (urlObj.port === '443' || urlObj.port === '')) {
|
|
51
58
|
urlObj.port = '';
|
|
52
59
|
}
|
|
53
|
-
urlObj.
|
|
54
|
-
return urlObj.toString();
|
|
60
|
+
return urlObj.toString().replace(/\/+$/, '');
|
|
55
61
|
}
|
|
56
62
|
catch (e) {
|
|
57
|
-
|
|
58
|
-
return url.replace(/\/+$/, '');
|
|
63
|
+
throw new Error(`Invalid URL: ${httpOrHttpsUrl}`, { cause: e });
|
|
59
64
|
}
|
|
60
65
|
}
|
|
61
66
|
function resolvePath(path) {
|
|
62
67
|
return path.startsWith('~/') ? join(homedir(), path.slice(2)) : resolve(path);
|
|
63
68
|
}
|
|
64
69
|
function removeRegistryPrefix(tarballUrl, registries) {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
return normalizedTarball.slice(normalizedRegistry.length) || '/';
|
|
73
|
-
}
|
|
70
|
+
const normalizedTarball = normalizeUrl(tarballUrl);
|
|
71
|
+
const normalizedRegistries = registries
|
|
72
|
+
.map(r => normalizeUrl(r.url))
|
|
73
|
+
.sort((a, b) => b.length - a.length);
|
|
74
|
+
for (const normalizedRegistry of normalizedRegistries) {
|
|
75
|
+
if (normalizedTarball.startsWith(normalizedRegistry)) {
|
|
76
|
+
return normalizedTarball.slice(normalizedRegistry.length) || '/';
|
|
74
77
|
}
|
|
75
78
|
}
|
|
76
|
-
|
|
77
|
-
console.error(`Invalid URL in removeRegistryPrefix: ${tarballUrl}`, e);
|
|
78
|
-
}
|
|
79
|
-
return tarballUrl;
|
|
79
|
+
throw new Error(`Can't find tarball url ${tarballUrl} does not match given registries ${normalizedRegistries}`);
|
|
80
80
|
}
|
|
81
81
|
async function loadProxyConfig(proxyConfigPath = './.registry-proxy.yml') {
|
|
82
82
|
const resolvedPath = resolvePath(proxyConfigPath);
|
|
@@ -143,7 +143,7 @@ export async function startProxyServer(proxyConfigPath, localYarnConfigPath, glo
|
|
|
143
143
|
return;
|
|
144
144
|
}
|
|
145
145
|
const fullUrl = new URL(req.url, `${proxyConfig.https ? 'https' : 'http'}://${req.headers.host}`);
|
|
146
|
-
if (
|
|
146
|
+
if (!fullUrl.pathname.startsWith(basePathPrefixedWithSlash)) {
|
|
147
147
|
console.error(`Path ${fullUrl.pathname} does not match basePath ${basePathPrefixedWithSlash}`);
|
|
148
148
|
res.writeHead(404).end('Not Found');
|
|
149
149
|
return;
|
|
@@ -194,8 +194,8 @@ export async function startProxyServer(proxyConfigPath, localYarnConfigPath, glo
|
|
|
194
194
|
const originalSearchParamsStr = originalUrl.search || '';
|
|
195
195
|
const tarballPathPrefixedWithSlash = removeRegistryPrefix(dist.tarball, registries);
|
|
196
196
|
dist.tarball = `${proxyBaseUrlNoSuffixedWithSlash}${tarballPathPrefixedWithSlash}${originalSearchParamsStr}`;
|
|
197
|
-
|
|
198
|
-
|
|
197
|
+
if (!tarballPathPrefixedWithSlash.startsWith("/"))
|
|
198
|
+
console.error("bad tarballPath, must be PrefixedWithSlash", tarballPathPrefixedWithSlash);
|
|
199
199
|
}
|
|
200
200
|
}
|
|
201
201
|
}
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -74,25 +74,27 @@ class ConcurrencyLimiter {
|
|
|
74
74
|
|
|
75
75
|
const limiter = new ConcurrencyLimiter(3);
|
|
76
76
|
|
|
77
|
-
function
|
|
77
|
+
function removeEndingSlashAndForceStartingSlash(str: string): string {
|
|
78
78
|
if (!str) return '/';
|
|
79
|
-
|
|
80
|
-
|
|
79
|
+
let trimmed = str.trim();
|
|
80
|
+
if (trimmed === '/') return '/';
|
|
81
|
+
if (trimmed === '') return '/';
|
|
82
|
+
if (!trimmed.startsWith('/')) trimmed = '/' + trimmed;
|
|
83
|
+
return trimmed.replace(/\/+$/, '');
|
|
81
84
|
}
|
|
82
85
|
|
|
83
|
-
function normalizeUrl(
|
|
86
|
+
function normalizeUrl(httpOrHttpsUrl: string): string {
|
|
87
|
+
if (!httpOrHttpsUrl.startsWith("http")) throw new Error("http(s) url must starts with 'http(s)://'");
|
|
84
88
|
try {
|
|
85
|
-
const urlObj = new URL(
|
|
89
|
+
const urlObj = new URL(httpOrHttpsUrl);
|
|
86
90
|
if (urlObj.protocol === 'http:' && (urlObj.port === '80' || urlObj.port === '')) {
|
|
87
91
|
urlObj.port = '';
|
|
88
92
|
} else if (urlObj.protocol === 'https:' && (urlObj.port === '443' || urlObj.port === '')) {
|
|
89
93
|
urlObj.port = '';
|
|
90
94
|
}
|
|
91
|
-
urlObj.
|
|
92
|
-
return urlObj.toString();
|
|
95
|
+
return urlObj.toString().replace(/\/+$/, '');
|
|
93
96
|
} catch (e) {
|
|
94
|
-
|
|
95
|
-
return url.replace(/\/+$/, '');
|
|
97
|
+
throw new Error(`Invalid URL: ${httpOrHttpsUrl}`, {cause: e});
|
|
96
98
|
}
|
|
97
99
|
}
|
|
98
100
|
|
|
@@ -101,21 +103,16 @@ function resolvePath(path: string): string {
|
|
|
101
103
|
}
|
|
102
104
|
|
|
103
105
|
function removeRegistryPrefix(tarballUrl: string, registries: RegistryInfo[]): string {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
if (normalizedTarball.startsWith(normalizedRegistry)) {
|
|
112
|
-
return normalizedTarball.slice(normalizedRegistry.length) || '/';
|
|
113
|
-
}
|
|
106
|
+
const normalizedTarball = normalizeUrl(tarballUrl);
|
|
107
|
+
const normalizedRegistries = registries
|
|
108
|
+
.map(r => normalizeUrl(r.url))
|
|
109
|
+
.sort((a, b) => b.length - a.length);
|
|
110
|
+
for (const normalizedRegistry of normalizedRegistries) {
|
|
111
|
+
if (normalizedTarball.startsWith(normalizedRegistry)) {
|
|
112
|
+
return normalizedTarball.slice(normalizedRegistry.length) || '/';
|
|
114
113
|
}
|
|
115
|
-
} catch (e) {
|
|
116
|
-
console.error(`Invalid URL in removeRegistryPrefix: ${tarballUrl}`, e);
|
|
117
114
|
}
|
|
118
|
-
|
|
115
|
+
throw new Error(`Can't find tarball url ${tarballUrl} does not match given registries ${normalizedRegistries}`)
|
|
119
116
|
}
|
|
120
117
|
|
|
121
118
|
async function loadProxyConfig(proxyConfigPath = './.registry-proxy.yml'): Promise<ProxyConfig> {
|
|
@@ -183,7 +180,7 @@ export async function startProxyServer(
|
|
|
183
180
|
): Promise<HttpServer | HttpsServer> {
|
|
184
181
|
const proxyConfig = await loadProxyConfig(proxyConfigPath);
|
|
185
182
|
const registries = await loadRegistries(proxyConfigPath, localYarnConfigPath, globalYarnConfigPath);
|
|
186
|
-
const basePathPrefixedWithSlash = proxyConfig.basePath ? `/${proxyConfig.basePath.replace(/^\/|\/$/g, '')}` : '/';
|
|
183
|
+
const basePathPrefixedWithSlash: string = proxyConfig.basePath ? `/${proxyConfig.basePath.replace(/^\/|\/$/g, '')}` : '/';
|
|
187
184
|
|
|
188
185
|
console.log('Active registries:', registries.map(r => r.url));
|
|
189
186
|
console.log('Proxy base path:', basePathPrefixedWithSlash);
|
|
@@ -199,7 +196,7 @@ export async function startProxyServer(
|
|
|
199
196
|
}
|
|
200
197
|
|
|
201
198
|
const fullUrl = new URL(req.url, `${proxyConfig.https ? 'https' : 'http'}://${req.headers.host}`);
|
|
202
|
-
if (
|
|
199
|
+
if (!fullUrl.pathname.startsWith(basePathPrefixedWithSlash)) {
|
|
203
200
|
console.error(`Path ${fullUrl.pathname} does not match basePath ${basePathPrefixedWithSlash}`);
|
|
204
201
|
res.writeHead(404).end('Not Found');
|
|
205
202
|
return;
|
|
@@ -252,8 +249,7 @@ export async function startProxyServer(
|
|
|
252
249
|
const originalSearchParamsStr = originalUrl.search || '';
|
|
253
250
|
const tarballPathPrefixedWithSlash = removeRegistryPrefix(dist.tarball, registries);
|
|
254
251
|
dist.tarball = `${proxyBaseUrlNoSuffixedWithSlash}${tarballPathPrefixedWithSlash}${originalSearchParamsStr}`;
|
|
255
|
-
console.
|
|
256
|
-
console.log("dist.tarballUrl", dist.tarball);
|
|
252
|
+
if (!tarballPathPrefixedWithSlash.startsWith("/")) console.error("bad tarballPath, must be PrefixedWithSlash", tarballPathPrefixedWithSlash);
|
|
257
253
|
}
|
|
258
254
|
}
|
|
259
255
|
}
|