cnpmcore
Version:
Private NPM Registry for Enterprise
146 lines • 12.3 kB
JavaScript
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import crypto from 'node:crypto';
import { SingletonProto } from 'egg';
import binaries from "../../../../config/binaries.js";
import { BinaryType } from "../../enum/Binary.js";
import { BinaryAdapter } from "./AbstractBinary.js";
import { BucketBinary } from "./BucketBinary.js";
/**
* NW.js binary adapter.
*
* Root directory: scraped from https://dl.nwjs.io/ (HTML index)
* Sub directories: listed via Cloudflare R2 S3-compatible API (ListObjectsV2)
*
* The R2 bucket credentials are publicly available in the nwjs frontend page.
* @see https://github.com/cnpm/cnpmcore/issues/891
*/
let NwjsBinary = class NwjsBinary extends BucketBinary {
constructor() {
super(...arguments);
// Cloudflare R2 S3-compatible endpoint for nwjs bucket
this.r2Endpoint = 'https://6883a4a09c48918c64df1ec7ddb744ba.r2.cloudflarestorage.com';
this.r2BucketName = 'nwjs';
this.r2AccessKeyId = '90fdca5d031b05eed0ef896a56a9521a';
this.r2SecretAccessKey = '34eeb665b34bfb9b773a8ff763a15e76621f541fdbbadeca6ed23e6d99c878ad';
this.r2Region = 'auto';
}
async fetch(dir) {
const binaryConfig = binaries.nwjs;
const isRootDir = dir === '/';
if (isRootDir) {
return this.fetchRootDir(binaryConfig.distUrl);
}
return this.fetchSubDir(dir, binaryConfig);
}
async fetchRootDir(distUrl) {
const xml = await this.requestXml(distUrl);
if (!xml)
return;
const items = [];
const re = /<td><a [^>]+?>([^<]+?\/)<\/a><\/td><td [^>]+?>([^>]+?)<\/td>/gi;
const matchs = xml.matchAll(re);
for (const m of matchs) {
const name = m[1].trim();
// ignore live-build/ name
if (name === 'live-build/')
continue;
const date = m[2].trim();
items.push({
name,
isDir: true,
url: '',
size: '-',
date,
});
}
return { items, nextParams: null };
}
async fetchSubDir(dir, binaryConfig) {
// /foo/ => foo/
const prefix = dir.slice(1);
const xml = await this.requestR2Xml(prefix);
if (!xml)
return;
return { items: this.parseItems(xml, dir, binaryConfig), nextParams: null };
}
/**
* Request R2 S3 ListObjectsV2 API with AWS Signature V4 authentication.
*/
async requestR2Xml(prefix) {
const host = new URL(this.r2Endpoint).host;
const now = new Date();
const amzDate = now
.toISOString()
.replace(/[-:]/g, '')
.replace(/\.\d{3}/, '');
const dateStamp = amzDate.slice(0, 8);
const method = 'GET';
const canonicalUri = `/${this.r2BucketName}`;
// Build sorted query string
const queryParams = new URLSearchParams({
delimiter: '/',
'list-type': '2',
prefix: prefix,
});
queryParams.sort();
const canonicalQueryString = queryParams.toString();
// Build canonical request
const payloadHash = crypto.createHash('sha256').update('').digest('hex');
const canonicalHeaders = `host:${host}\nx-amz-content-sha256:${payloadHash}\nx-amz-date:${amzDate}\n`;
const signedHeaders = 'host;x-amz-content-sha256;x-amz-date';
const canonicalRequest = [
method,
canonicalUri,
canonicalQueryString,
canonicalHeaders,
signedHeaders,
payloadHash,
].join('\n');
// Build string to sign
const credentialScope = `${dateStamp}/${this.r2Region}/s3/aws4_request`;
const stringToSign = [
'AWS4-HMAC-SHA256',
amzDate,
credentialScope,
crypto.createHash('sha256').update(canonicalRequest).digest('hex'),
].join('\n');
// Calculate signature
const signingKey = this.getSignatureKey(this.r2SecretAccessKey, dateStamp, this.r2Region, 's3');
const signature = crypto.createHmac('sha256', signingKey).update(stringToSign).digest('hex');
const authorization = `AWS4-HMAC-SHA256 Credential=${this.r2AccessKeyId}/${credentialScope}, SignedHeaders=${signedHeaders}, Signature=${signature}`;
const url = `${this.r2Endpoint}/${this.r2BucketName}?${canonicalQueryString}`;
const { status, data, headers } = await this.httpclient.request(url, {
timeout: 30_000,
followRedirect: true,
gzip: true,
headers: {
Authorization: authorization,
'X-Amz-Content-Sha256': payloadHash,
'X-Amz-Date': amzDate,
},
});
const xml = data.toString();
if (status !== 200) {
this.logger.warn('[NwjsBinary.requestR2Xml:non-200-status] url: %s, status: %s, headers: %j, xml: %j', url, status, headers, xml);
return '';
}
return xml;
}
getSignatureKey(key, dateStamp, region, service) {
const kDate = crypto.createHmac('sha256', `AWS4${key}`).update(dateStamp).digest();
const kRegion = crypto.createHmac('sha256', kDate).update(region).digest();
const kService = crypto.createHmac('sha256', kRegion).update(service).digest();
return crypto.createHmac('sha256', kService).update('aws4_request').digest();
}
};
NwjsBinary = __decorate([
SingletonProto(),
BinaryAdapter(BinaryType.Nwjs)
], NwjsBinary);
export { NwjsBinary };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTndqc0JpbmFyeS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL2FwcC9jb21tb24vYWRhcHRlci9iaW5hcnkvTndqc0JpbmFyeS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSxPQUFPLE1BQU0sTUFBTSxhQUFhLENBQUM7QUFFakMsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLEtBQUssQ0FBQztBQUVyQyxPQUFPLFFBQVEsTUFBTSxnQ0FBZ0MsQ0FBQztBQUN0RCxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDbEQsT0FBTyxFQUFFLGFBQWEsRUFBcUMsTUFBTSxxQkFBcUIsQ0FBQztBQUN2RixPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFFakQ7Ozs7Ozs7O0dBUUc7QUFHSSxJQUFNLFVBQVUsR0FBaEIsTUFBTSxVQUFXLFNBQVEsWUFBWTtJQUFyQzs7UUFDTCx1REFBdUQ7UUFDL0MsZUFBVSxHQUFHLG1FQUFtRSxDQUFDO1FBQ2pGLGlCQUFZLEdBQUcsTUFBTSxDQUFDO1FBQ3RCLGtCQUFhLEdBQUcsa0NBQWtDLENBQUM7UUFDbkQsc0JBQWlCLEdBQUcsa0VBQWtFLENBQUM7UUFDdkYsYUFBUSxHQUFHLE1BQU0sQ0FBQztJQWtJNUIsQ0FBQztJQWhJQyxLQUFLLENBQUMsS0FBSyxDQUFDLEdBQVc7UUFDckIsTUFBTSxZQUFZLEdBQUcsUUFBUSxDQUFDLElBQUksQ0FBQztRQUNuQyxNQUFNLFNBQVMsR0FBRyxHQUFHLEtBQUssR0FBRyxDQUFDO1FBRTlCLElBQUksU0FBUyxFQUFFLENBQUM7WUFDZCxPQUFPLElBQUksQ0FBQyxZQUFZLENBQUMsWUFBWSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ2pELENBQUM7UUFFRCxPQUFPLElBQUksQ0FBQyxXQUFXLENBQUMsR0FBRyxFQUFFLFlBQVksQ0FBQyxDQUFDO0lBQzdDLENBQUM7SUFFTyxLQUFLLENBQUMs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