com.jimuwd.xian.registry-proxy 1.0.85 → 1.0.87
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 +30 -25
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -143,10 +143,16 @@ async function fetchFromRegistry(registry, targetUrl, reqFromDownstreamClient, l
|
|
|
143
143
|
try {
|
|
144
144
|
logger.info(`Fetching from upstream: ${targetUrl}`);
|
|
145
145
|
const headersFromDownstreamClient = reqFromDownstreamClient.headers;
|
|
146
|
-
const
|
|
147
|
-
// 合并 headersFromDownstreamClient 和
|
|
148
|
-
const mergedHeaders = { ...headersFromDownstreamClient, ...
|
|
146
|
+
const authorizationHeaders = registry.token ? { Authorization: `Bearer ${registry.token}` } : {};
|
|
147
|
+
// 合并 headersFromDownstreamClient 和 authorizationHeaders
|
|
148
|
+
const mergedHeaders = { ...headersFromDownstreamClient, ...authorizationHeaders, };
|
|
149
149
|
// (mergedHeaders as any).connection = "keep-alive"; 不允许私自添加 connection: keep-alive header,应当最终下游客户端自己的选择
|
|
150
|
+
// 替换“Host”头为upstream的host
|
|
151
|
+
const upstreamHost = new URL(registry.normalizedRegistryUrl).host;
|
|
152
|
+
if (mergedHeaders.host) {
|
|
153
|
+
logger.info(`Replace 'Host=${mergedHeaders.host}' header in downstream request to upstream 'Host=${upstreamHost}' header when proxying to upstream ${targetUrl}.`);
|
|
154
|
+
mergedHeaders.host = upstreamHost;
|
|
155
|
+
}
|
|
150
156
|
const response = await fetch(targetUrl, { headers: mergedHeaders });
|
|
151
157
|
logger.info(`Response from upstream ${targetUrl}: ${response.status} ${response.statusText} content-type=${response.headers.get('content-type')} content-length=${response.headers.get('content-length')} transfer-encoding=${response.headers.get('transfer-encoding')}`);
|
|
152
158
|
return response.ok ? response : null;
|
|
@@ -169,30 +175,17 @@ async function fetchFromRegistry(registry, targetUrl, reqFromDownstreamClient, l
|
|
|
169
175
|
function resetHeaderContentLengthIfTransferEncodingIsAbsent(safeHeaders, targetUrl, bodyData) {
|
|
170
176
|
if (!safeHeaders["transfer-encoding"]) {
|
|
171
177
|
logger.info(`Transfer-Encoding header is absent, then set the content-length header, upstream url is ${targetUrl}`);
|
|
172
|
-
safeHeaders["content-length"] = bodyData
|
|
178
|
+
safeHeaders["content-length"] = Buffer.byteLength(bodyData);
|
|
173
179
|
}
|
|
174
180
|
}
|
|
175
181
|
async function writeResponseToDownstreamClient(registryInfo, targetUrl, resToDownstreamClient, upstreamResponse, reqFromDownstreamClient, proxyInfo, proxyPort, registryInfos) {
|
|
176
182
|
if (!upstreamResponse.ok)
|
|
177
183
|
throw new Error("Only 2xx upstream response is supported");
|
|
178
184
|
try {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
// 复制所有可能需要的头信息(不包含安全相关的敏感头信息,如access-control-allow-origin、set-cookie、server、strict-transport-security等,这意味着代理服务器向下游客户端屏蔽了这些认证等安全数据)
|
|
182
|
-
// 也不能包含cf-cache-status、cf-ray(Cloudflare 特有字段)可能干扰客户端解析。
|
|
183
|
-
const headersToCopy = ['cache-control', 'connection', 'content-type', 'content-encoding', 'content-length', 'date', 'etag', 'last-modified', 'transfer-encoding', 'vary',];
|
|
184
|
-
headersToCopy.forEach(header => {
|
|
185
|
-
const value = upstreamResponse.headers.get(header);
|
|
186
|
-
if (value)
|
|
187
|
-
safeHeaders[header] = value;
|
|
188
|
-
});
|
|
189
|
-
if (!safeHeaders['content-type'])
|
|
190
|
-
safeHeaders['content-type'] = 'application/octet-stream';
|
|
191
|
-
const contentType = safeHeaders['content-type'];
|
|
192
|
-
if (contentType.includes('application/json')) {
|
|
193
|
-
// JSON 处理逻辑
|
|
185
|
+
const contentType = upstreamResponse.headers.get("content-type") || "application/octet-stream";
|
|
186
|
+
if (contentType.includes('application/json')) { // JSON 处理逻辑
|
|
194
187
|
const data = await upstreamResponse.json();
|
|
195
|
-
if (data.versions) {
|
|
188
|
+
if (data.versions) { // 处理node依赖包元数据
|
|
196
189
|
const host = reqFromDownstreamClient.headers.host || `localhost:${proxyPort}`;
|
|
197
190
|
const baseUrl = `${proxyInfo.https ? 'https' : 'http'}://${host}${proxyInfo.basePath === '/' ? '' : proxyInfo.basePath}`;
|
|
198
191
|
for (const versionKey in data.versions) {
|
|
@@ -206,12 +199,24 @@ async function writeResponseToDownstreamClient(registryInfo, targetUrl, resToDow
|
|
|
206
199
|
}
|
|
207
200
|
}
|
|
208
201
|
const bodyData = JSON.stringify(data);
|
|
209
|
-
|
|
202
|
+
const safeHeaders = { 'content-type': 'application/json', 'content-length': Buffer.byteLength(bodyData) };
|
|
210
203
|
logger.info(`Response to downstream client headers`, JSON.stringify(safeHeaders), targetUrl);
|
|
211
|
-
resToDownstreamClient.writeHead(upstreamResponse.status,
|
|
204
|
+
resToDownstreamClient.writeHead(upstreamResponse.status, { 'content-type': 'application/json' }).end(bodyData);
|
|
212
205
|
}
|
|
213
|
-
else if (contentType.includes('application/octet-stream')) {
|
|
214
|
-
//
|
|
206
|
+
else if (contentType.includes('application/octet-stream')) { // 二进制流处理
|
|
207
|
+
// 准备通用响应头信息
|
|
208
|
+
const safeHeaders = {};
|
|
209
|
+
// 复制所有可能需要的头信息(不包含安全相关的敏感头信息,如access-control-allow-origin、set-cookie、server、strict-transport-security等,这意味着代理服务器向下游客户端屏蔽了这些认证等安全数据)
|
|
210
|
+
// 也不能包含cf-cache-status、cf-ray(Cloudflare 特有字段)可能干扰客户端解析。
|
|
211
|
+
const headersToCopy = ['cache-control', 'connection', 'content-type', 'content-encoding', 'content-length', 'date', 'etag', 'last-modified', 'transfer-encoding', 'vary',];
|
|
212
|
+
headersToCopy.forEach(header => {
|
|
213
|
+
const value = upstreamResponse.headers.get(header);
|
|
214
|
+
if (value)
|
|
215
|
+
safeHeaders[header] = value;
|
|
216
|
+
});
|
|
217
|
+
if (!safeHeaders['content-type'])
|
|
218
|
+
safeHeaders['content-type'] = 'application/octet-stream';
|
|
219
|
+
const contentType = safeHeaders['content-type'];
|
|
215
220
|
if (!upstreamResponse.body) {
|
|
216
221
|
logger.error(`Empty response body from upstream ${targetUrl}`);
|
|
217
222
|
resToDownstreamClient.writeHead(502).end('Empty Upstream Response');
|
|
@@ -259,7 +264,7 @@ async function writeResponseToDownstreamClient(registryInfo, targetUrl, resToDow
|
|
|
259
264
|
else {
|
|
260
265
|
logger.warn(`Unsupported response content-type from upstream ${targetUrl}`);
|
|
261
266
|
const bodyData = await upstreamResponse.text();
|
|
262
|
-
|
|
267
|
+
const safeHeaders = { 'content-type': contentType, 'content-length': Buffer.byteLength(bodyData) };
|
|
263
268
|
logger.info(`Response to downstream client headers`, JSON.stringify(safeHeaders), targetUrl);
|
|
264
269
|
resToDownstreamClient.writeHead(upstreamResponse.status, safeHeaders).end(bodyData);
|
|
265
270
|
}
|