UNPKG

@sap/ams-dev

Version:

NodesJS AMS development environment

82 lines (69 loc) 3.1 kB
const https = require('node:https'); const { URL } = require('node:url'); const { addDefaultHeaders, createHTTPSAgent, createTgzFromDirectory } = require('./util'); const { sanitizeForLog } = require('../util'); const APPNAME_HEADER = "X-Appname"; async function uploadBaseDcl(credentials, dclRoot, uploadParams) { const bundle = await createTgzFromDirectory(dclRoot); // Todo: Calculate SHA256 of local policies and upload only when it differs from current policies // For comparison, use the new HEAD request to get current SHA256 from server const request = createDclUploadRequest(credentials, bundle, uploadParams); await postDcl(request); } /** * Creates an abstract DCL upload request object for use with an arbitrary http client * @param {object} credentials - the Identity Service credentials * @param {Buffer} bundle - the .tgz archive buffer containing the DCL files * @param {object} [uploadParams] - optional parameters for the upload request * @param {string} [uploadParams.deployerAppName] - a descriptive name of this deployer application to trace back the currently deployed DCL bundle on the AMS server to its source when DCL is deployed from more than one source. * @returns {object} - the request object */ function createDclUploadRequest(credentials, bundle, uploadParams) { const appName = uploadParams.deployerAppName || "@sap/ams-dev:AmsClient"; const request = { url: `${credentials.url}/sap/ams/v1/ams-instances/${credentials.authorization_instance_id}/dcl-upload`, method: "POST", headers: { "Content-Type": "application/gzip", [APPNAME_HEADER]: appName }, body: bundle, agent: createHTTPSAgent(credentials) }; addDefaultHeaders(request.headers, credentials); return request; } async function postDcl(request) { return new Promise((resolve, reject) => { const url = new URL(request.url); const options = { hostname: url.hostname, port: url.port || 443, path: url.pathname + url.search, method: request.method, headers: { ...request.headers, 'Content-Length': request.body.length }, agent: request.agent }; const req = https.request(options, (res) => { let data = ''; res.on('data', chunk => data += chunk); res.on('end', () => { if (res.statusCode >= 200 && res.statusCode < 300) { resolve(data); } else { // statusCode/statusMessage are server-controlled; sanitize to prevent log injection reject(new Error(`DCL upload rejected by server: ${res.statusCode} ${sanitizeForLog(res.statusMessage)}`)); } }); }); req.on('error', (e) => { reject(new Error(`DCL upload could not be sent: ${e.message}`)); }); req.write(request.body); req.end(); }); } module.exports = uploadBaseDcl;