com.jimuwd.xian.registry-proxy 1.0.94 → 1.0.96
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 +31 -8
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -205,6 +205,9 @@ async function writeResponseToDownstreamClient(registryInfo, targetUrl, resToDow
|
|
|
205
205
|
}
|
|
206
206
|
const bodyData = JSON.stringify(data);
|
|
207
207
|
resToDownstreamClient.removeHeader('Transfer-Encoding');
|
|
208
|
+
// 默认是 connection: keep-alive 和 keep-alive: timeout=5,这里直接给它咔嚓掉
|
|
209
|
+
resToDownstreamClient.setHeader('Connection', 'close');
|
|
210
|
+
resToDownstreamClient.removeHeader('Keep-Alive');
|
|
208
211
|
resToDownstreamClient.setHeader('content-type', 'application/json');
|
|
209
212
|
resToDownstreamClient.setHeader('content-length', Buffer.byteLength(bodyData));
|
|
210
213
|
logger.info(`Response to downstream client headers`, JSON.stringify(resToDownstreamClient.getHeaders()), targetUrl);
|
|
@@ -283,6 +286,15 @@ async function writeResponseToDownstreamClient(registryInfo, targetUrl, resToDow
|
|
|
283
286
|
}
|
|
284
287
|
}
|
|
285
288
|
}
|
|
289
|
+
function getDownstreamClientIp(req) {
|
|
290
|
+
// 如果经过代理(如 Nginx),取 X-Forwarded-For 的第一个 IP
|
|
291
|
+
const forwardedFor = req.headers['x-forwarded-for'];
|
|
292
|
+
if (forwardedFor) {
|
|
293
|
+
return forwardedFor.toString().split(',')[0].trim();
|
|
294
|
+
}
|
|
295
|
+
// 直接连接时,取 socket.remoteAddress
|
|
296
|
+
return req.socket.remoteAddress;
|
|
297
|
+
}
|
|
286
298
|
export async function startProxyServer(proxyConfigPath, localYarnConfigPath, globalYarnConfigPath, port = 0) {
|
|
287
299
|
const proxyInfo = await loadProxyInfo(proxyConfigPath, localYarnConfigPath, globalYarnConfigPath);
|
|
288
300
|
const registryInfos = proxyInfo.registries;
|
|
@@ -292,11 +304,19 @@ export async function startProxyServer(proxyConfigPath, localYarnConfigPath, glo
|
|
|
292
304
|
logger.info('HTTPS:', !!proxyInfo.https);
|
|
293
305
|
let proxyPort;
|
|
294
306
|
const requestHandler = async (reqFromDownstreamClient, resToDownstreamClient) => {
|
|
295
|
-
|
|
307
|
+
const downstreamUserAgent = reqFromDownstreamClient.headers["user-agent"]; // "curl/x.x.x"
|
|
308
|
+
const downstreamIp = getDownstreamClientIp(reqFromDownstreamClient);
|
|
309
|
+
const downstreamRequestedHttpMethod = reqFromDownstreamClient.method; // "GET", "POST", etc.
|
|
310
|
+
const downstreamRequestedHost = reqFromDownstreamClient.headers.host; // "example.com:8080"
|
|
311
|
+
const downstreamRequestedFullPath = reqFromDownstreamClient.url; // "/some/path?param=1¶m=2"
|
|
312
|
+
logger.info(`Received downstream request ${downstreamUserAgent} ${downstreamIp} ${downstreamRequestedHttpMethod} ${downstreamRequestedHost} ${downstreamRequestedFullPath}`);
|
|
313
|
+
if (!downstreamRequestedFullPath || !downstreamRequestedHost) {
|
|
314
|
+
logger.warn(`400 Invalid Request, downstream ${downstreamUserAgent} req.url is absent or downstream.headers.host is absent.`);
|
|
296
315
|
resToDownstreamClient.writeHead(400).end('Invalid Request');
|
|
297
316
|
return;
|
|
298
317
|
}
|
|
299
|
-
const
|
|
318
|
+
const baseUrl = `${proxyInfo.https ? 'https' : 'http'}://${downstreamRequestedHost}`;
|
|
319
|
+
const fullUrl = new URL(downstreamRequestedFullPath, baseUrl);
|
|
300
320
|
if (!fullUrl.pathname.startsWith(basePathPrefixedWithSlash)) {
|
|
301
321
|
resToDownstreamClient.writeHead(404).end('Not Found');
|
|
302
322
|
return;
|
|
@@ -304,19 +324,22 @@ export async function startProxyServer(proxyConfigPath, localYarnConfigPath, glo
|
|
|
304
324
|
const path = basePathPrefixedWithSlash === '/'
|
|
305
325
|
? fullUrl.pathname
|
|
306
326
|
: fullUrl.pathname.slice(basePathPrefixedWithSlash.length);
|
|
307
|
-
|
|
327
|
+
const search = fullUrl.search || '';
|
|
328
|
+
const targetPath = path + search;
|
|
329
|
+
logger.info(`Proxying to ${targetPath}`);
|
|
330
|
+
// 按配置顺序尝试注册表,获取第一个成功响应
|
|
308
331
|
let successfulResponseFromUpstream = null;
|
|
309
332
|
let targetRegistry = null;
|
|
310
333
|
let targetUrl = null;
|
|
311
|
-
for (const
|
|
334
|
+
for (const registry_i of registryInfos) {
|
|
335
|
+
targetRegistry = registry_i;
|
|
336
|
+
targetUrl = `${targetRegistry.normalizedRegistryUrl}${targetPath}`;
|
|
312
337
|
if (reqFromDownstreamClient.destroyed) {
|
|
313
338
|
// 如果下游客户端自己提前断开(或取消)请求,那么这里不再逐个fallback方式请求(fetch)上游数据了,直接退出循环并返回
|
|
339
|
+
logger.warn(`Downstream ${reqFromDownstreamClient.headers["user-agent"]} request is destroyed, no need to proxy request to upstream ${targetUrl} any more.`);
|
|
314
340
|
return;
|
|
315
341
|
}
|
|
316
|
-
|
|
317
|
-
const search = fullUrl.search || '';
|
|
318
|
-
targetUrl = `${registry.normalizedRegistryUrl}${path}${search}`;
|
|
319
|
-
const okResponseOrNull = await fetchFromRegistry(registry, targetUrl, reqFromDownstreamClient, limiter);
|
|
342
|
+
const okResponseOrNull = await fetchFromRegistry(targetRegistry, targetUrl, reqFromDownstreamClient, limiter);
|
|
320
343
|
if (okResponseOrNull) {
|
|
321
344
|
successfulResponseFromUpstream = okResponseOrNull;
|
|
322
345
|
break;
|