com.jimuwd.xian.registry-proxy 1.0.60 → 1.0.63
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 +40 -24
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -160,8 +160,7 @@ async function fetchFromRegistry(registry, targetUrl, limiter) {
|
|
|
160
160
|
limiter.release();
|
|
161
161
|
}
|
|
162
162
|
}
|
|
163
|
-
|
|
164
|
-
async function writeSuccessfulResponse(registryInfo, targetUrl, res, upstreamResponse, req, proxyInfo, proxyPort, registryInfos) {
|
|
163
|
+
async function writeResponseToDownstreamClient(registryInfo, targetUrl, resToDownstreamClient, upstreamResponse, downstreamReq, proxyInfo, proxyPort, registryInfos) {
|
|
165
164
|
if (!upstreamResponse.ok)
|
|
166
165
|
throw new Error("Only 2xx upstream response is supported");
|
|
167
166
|
try {
|
|
@@ -184,7 +183,7 @@ async function writeSuccessfulResponse(registryInfo, targetUrl, res, upstreamRes
|
|
|
184
183
|
// JSON 处理逻辑
|
|
185
184
|
const data = await upstreamResponse.json();
|
|
186
185
|
if (data.versions) {
|
|
187
|
-
const host =
|
|
186
|
+
const host = downstreamReq.headers.host || `localhost:${proxyPort}`;
|
|
188
187
|
const baseUrl = `${proxyInfo.https ? 'https' : 'http'}://${host}${proxyInfo.basePath === '/' ? '' : proxyInfo.basePath}`;
|
|
189
188
|
for (const versionKey in data.versions) {
|
|
190
189
|
const packageVersion = data.versions[versionKey];
|
|
@@ -196,32 +195,49 @@ async function writeSuccessfulResponse(registryInfo, targetUrl, res, upstreamRes
|
|
|
196
195
|
}
|
|
197
196
|
}
|
|
198
197
|
}
|
|
199
|
-
|
|
198
|
+
resToDownstreamClient.writeHead(upstreamResponse.status, { "content-type": contentType }).end(JSON.stringify(data));
|
|
200
199
|
}
|
|
201
200
|
else {
|
|
202
201
|
// 二进制流处理
|
|
203
202
|
if (!upstreamResponse.body) {
|
|
204
203
|
logger.error(`Empty response body from ${targetUrl}`);
|
|
205
|
-
|
|
204
|
+
resToDownstreamClient.writeHead(502).end('Empty Upstream Response');
|
|
206
205
|
}
|
|
207
206
|
else {
|
|
208
207
|
// write back to client
|
|
209
|
-
|
|
208
|
+
resToDownstreamClient.writeHead(upstreamResponse.status, safeHeaders);
|
|
210
209
|
// stop transfer if client is closed accidentally.
|
|
211
|
-
|
|
210
|
+
const cleanup = () => {
|
|
211
|
+
downstreamReq.off('close', cleanup);
|
|
212
|
+
logger.warn("Stop transfer when client is closed accidentally.");
|
|
213
|
+
upstreamResponse.body?.unpipe();
|
|
214
|
+
};
|
|
215
|
+
downstreamReq.on('close', cleanup);
|
|
212
216
|
// write back body data (chunked probably)
|
|
217
|
+
// pipe upstream body to downstream client and end when upstream ends.
|
|
218
|
+
upstreamResponse.body.pipe(resToDownstreamClient, { end: true });
|
|
213
219
|
upstreamResponse.body
|
|
214
|
-
.on('data', (chunk) =>
|
|
215
|
-
.on('end', () =>
|
|
216
|
-
.
|
|
217
|
-
|
|
220
|
+
.on('data', (chunk) => logger.info(`chunk transferred size=${chunk.length}`))
|
|
221
|
+
.on('end', () => {
|
|
222
|
+
logger.info(`Upstream server ${registryInfo.normalizedRegistryUrl} response.body ended on url ${targetUrl}`);
|
|
223
|
+
})
|
|
224
|
+
.on('close', () => {
|
|
225
|
+
const errMsg = `Upstream server ${registryInfo.normalizedRegistryUrl} closed connection while transferring data on url ${targetUrl}`;
|
|
226
|
+
logger.error(errMsg);
|
|
227
|
+
// resToDownstreamClient.destroy(new Error(errMsg));
|
|
228
|
+
})
|
|
229
|
+
.on('error', (err) => {
|
|
230
|
+
const errMsg = `Stream error: ${err.message}`;
|
|
231
|
+
logger.error(errMsg);
|
|
232
|
+
resToDownstreamClient.destroy(new Error(errMsg, { cause: err, }));
|
|
233
|
+
});
|
|
218
234
|
}
|
|
219
235
|
}
|
|
220
236
|
}
|
|
221
237
|
catch (err) {
|
|
222
238
|
logger.error('Failed to write upstreamResponse:', err);
|
|
223
|
-
if (!
|
|
224
|
-
|
|
239
|
+
if (!resToDownstreamClient.headersSent) {
|
|
240
|
+
resToDownstreamClient.writeHead(502).end('Internal Server Error');
|
|
225
241
|
}
|
|
226
242
|
}
|
|
227
243
|
}
|
|
@@ -233,41 +249,41 @@ export async function startProxyServer(proxyConfigPath, localYarnConfigPath, glo
|
|
|
233
249
|
logger.info('Proxy base path:', basePathPrefixedWithSlash);
|
|
234
250
|
logger.info('HTTPS:', !!proxyInfo.https);
|
|
235
251
|
let proxyPort;
|
|
236
|
-
const requestHandler = async (
|
|
237
|
-
if (!
|
|
238
|
-
|
|
252
|
+
const requestHandler = async (reqFromDownstreamClient, resToDownstreamClient) => {
|
|
253
|
+
if (!reqFromDownstreamClient.url || !reqFromDownstreamClient.headers.host) {
|
|
254
|
+
resToDownstreamClient.writeHead(400).end('Invalid Request');
|
|
239
255
|
return;
|
|
240
256
|
}
|
|
241
|
-
const fullUrl = new URL(
|
|
257
|
+
const fullUrl = new URL(reqFromDownstreamClient.url, `${proxyInfo.https ? 'https' : 'http'}://${reqFromDownstreamClient.headers.host}`);
|
|
242
258
|
if (!fullUrl.pathname.startsWith(basePathPrefixedWithSlash)) {
|
|
243
|
-
|
|
259
|
+
resToDownstreamClient.writeHead(404).end('Not Found');
|
|
244
260
|
return;
|
|
245
261
|
}
|
|
246
262
|
const path = basePathPrefixedWithSlash === '/'
|
|
247
263
|
? fullUrl.pathname
|
|
248
264
|
: fullUrl.pathname.slice(basePathPrefixedWithSlash.length);
|
|
249
265
|
// 顺序尝试注册表,获取第一个成功响应
|
|
250
|
-
let
|
|
266
|
+
let successfulResponseFromUpstream = null;
|
|
251
267
|
let targetRegistry = null;
|
|
252
268
|
let targetUrl = null;
|
|
253
269
|
for (const registry of registryInfos) {
|
|
254
|
-
if (
|
|
270
|
+
if (reqFromDownstreamClient.destroyed)
|
|
255
271
|
break;
|
|
256
272
|
targetRegistry = registry;
|
|
257
273
|
const search = fullUrl.search || '';
|
|
258
274
|
targetUrl = `${registry.normalizedRegistryUrl}${path}${search}`;
|
|
259
275
|
const okResponseOrNull = await fetchFromRegistry(registry, targetUrl, limiter);
|
|
260
276
|
if (okResponseOrNull) {
|
|
261
|
-
|
|
277
|
+
successfulResponseFromUpstream = okResponseOrNull;
|
|
262
278
|
break;
|
|
263
279
|
}
|
|
264
280
|
}
|
|
265
281
|
// 统一回写响应
|
|
266
|
-
if (
|
|
267
|
-
await
|
|
282
|
+
if (successfulResponseFromUpstream) {
|
|
283
|
+
await writeResponseToDownstreamClient(targetRegistry, targetUrl, resToDownstreamClient, successfulResponseFromUpstream, reqFromDownstreamClient, proxyInfo, proxyPort, registryInfos);
|
|
268
284
|
}
|
|
269
285
|
else {
|
|
270
|
-
|
|
286
|
+
resToDownstreamClient.writeHead(404).end('All upstream registries failed');
|
|
271
287
|
}
|
|
272
288
|
};
|
|
273
289
|
let server;
|