usezap-cli
Version:
Zap CLI - Command-line interface for Zap API client
339 lines (294 loc) • 12.9 kB
JavaScript
const { get, each, filter } = require('lodash');
const decomment = require('decomment');
const crypto = require('node:crypto');
const { mergeHeaders, mergeScripts, mergeVars, mergeAuth, getTreePathFromCollectionToItem } = require('../utils/collection');
const { createFormData } = require('../utils/form-data');
const prepareRequest = (item = {}, collection = {}) => {
const request = item?.request;
const zapConfig = get(collection, 'zapConfig', {});
const headers = {};
let contentTypeDefined = false;
const scriptFlow = zapConfig?.scripts?.flow ?? 'sandwich';
const requestTreePath = getTreePathFromCollectionToItem(collection, item);
if (requestTreePath && requestTreePath.length > 0) {
mergeHeaders(collection, request, requestTreePath);
mergeScripts(collection, request, requestTreePath, scriptFlow);
mergeVars(collection, request, requestTreePath);
mergeAuth(collection, request, requestTreePath);
}
each(get(request, 'headers', []), (h) => {
if (h.enabled) {
headers[h.name] = h.value;
if (h.name.toLowerCase() === 'content-type') {
contentTypeDefined = true;
}
}
});
let axiosRequest = {
method: request.method,
url: request.url,
headers: headers,
name: item.name,
pathParams: request?.params?.filter((param) => param.type === 'path'),
responseType: 'arraybuffer'
};
const collectionAuth = get(collection, 'root.request.auth');
if (collectionAuth && request.auth?.mode === 'inherit') {
if (collectionAuth.mode === 'basic') {
axiosRequest.basicAuth = {
username: get(collectionAuth, 'basic.username'),
password: get(collectionAuth, 'basic.password')
};
}
if (collectionAuth.mode === 'bearer') {
axiosRequest.headers['Authorization'] = `Bearer ${get(collectionAuth, 'bearer.token')}`;
}
if (collectionAuth.mode === 'apikey') {
if (collectionAuth.apikey?.placement === 'header') {
axiosRequest.headers[collectionAuth.apikey?.key] = collectionAuth.apikey?.value;
}
if (collectionAuth.apikey?.placement === 'queryparams') {
if (axiosRequest.url && collectionAuth.apikey?.key) {
try {
const urlObj = new URL(request.url);
urlObj.searchParams.set(collectionAuth.apikey?.key, collectionAuth.apikey?.value);
axiosRequest.url = urlObj.toString();
} catch (error) {
console.error('Invalid URL:', request.url, error);
}
}
}
}
if (collectionAuth.mode === 'digest') {
axiosRequest.digestConfig = {
username: get(collectionAuth, 'digest.username'),
password: get(collectionAuth, 'digest.password')
};
}
if (collectionAuth.mode === 'oauth2') {
const grantType = get(collectionAuth, 'oauth2.grantType');
if (grantType === 'client_credentials') {
axiosRequest.oauth2 = {
grantType,
accessTokenUrl: get(collectionAuth, 'oauth2.accessTokenUrl'),
clientId: get(collectionAuth, 'oauth2.clientId'),
clientSecret: get(collectionAuth, 'oauth2.clientSecret'),
scope: get(collectionAuth, 'oauth2.scope'),
credentialsPlacement: get(collectionAuth, 'oauth2.credentialsPlacement'),
tokenPlacement: get(collectionAuth, 'oauth2.tokenPlacement'),
tokenHeaderPrefix: get(collectionAuth, 'oauth2.tokenHeaderPrefix'),
tokenQueryKey: get(collectionAuth, 'oauth2.tokenQueryKey')
};
} else if (grantType === 'password') {
axiosRequest.oauth2 = {
grantType,
accessTokenUrl: get(collectionAuth, 'oauth2.accessTokenUrl'),
username: get(collectionAuth, 'oauth2.username'),
password: get(collectionAuth, 'oauth2.password'),
clientId: get(collectionAuth, 'oauth2.clientId'),
clientSecret: get(collectionAuth, 'oauth2.clientSecret'),
scope: get(collectionAuth, 'oauth2.scope'),
credentialsPlacement: get(collectionAuth, 'oauth2.credentialsPlacement'),
tokenPlacement: get(collectionAuth, 'oauth2.tokenPlacement'),
tokenHeaderPrefix: get(collectionAuth, 'oauth2.tokenHeaderPrefix'),
tokenQueryKey: get(collectionAuth, 'oauth2.tokenQueryKey')
};
}
}
if (collectionAuth.mode === 'awsv4') {
axiosRequest.awsv4config = {
accessKeyId: get(collectionAuth, 'awsv4.accessKeyId'),
secretAccessKey: get(collectionAuth, 'awsv4.secretAccessKey'),
sessionToken: get(collectionAuth, 'awsv4.sessionToken'),
service: get(collectionAuth, 'awsv4.service'),
region: get(collectionAuth, 'awsv4.region'),
profileName: get(collectionAuth, 'awsv4.profileName')
};
}
if (collectionAuth.mode === 'ntlm') {
axiosRequest.ntlmConfig = {
username: get(collectionAuth, 'ntlm.username'),
password: get(collectionAuth, 'ntlm.password'),
domain: get(collectionAuth, 'ntlm.domain')
};
}
if (collectionAuth.mode === 'wsse') {
const username = get(collectionAuth, 'wsse.username', '');
const password = get(collectionAuth, 'wsse.password', '');
const ts = new Date().toISOString();
const nonce = crypto.randomBytes(16).toString('hex');
// Create the password digest using SHA-1 as required for WSSE
const hash = crypto.createHash('sha1');
hash.update(nonce + ts + password);
const digest = Buffer.from(hash.digest('hex').toString('utf8')).toString('base64');
// Construct the WSSE header
axiosRequest.headers[
'X-WSSE'
] = `UsernameToken Username="${username}", PasswordDigest="${digest}", Nonce="${nonce}", Created="${ts}"`;
}
console.log('axiosRequest', axiosRequest);
}
if (request.auth && request.auth.mode !== 'inherit') {
if (request.auth.mode === 'basic') {
axiosRequest.basicAuth = {
username: get(request, 'auth.basic.username'),
password: get(request, 'auth.basic.password')
};
}
if (request.auth.mode === 'awsv4') {
axiosRequest.awsv4config = {
accessKeyId: get(request, 'auth.awsv4.accessKeyId'),
secretAccessKey: get(request, 'auth.awsv4.secretAccessKey'),
sessionToken: get(request, 'auth.awsv4.sessionToken'),
service: get(request, 'auth.awsv4.service'),
region: get(request, 'auth.awsv4.region'),
profileName: get(request, 'auth.awsv4.profileName')
};
}
if (request.auth.mode === 'ntlm') {
axiosRequest.ntlmConfig = {
username: get(request, 'auth.ntlm.username'),
password: get(request, 'auth.ntlm.password'),
domain: get(request, 'auth.ntlm.domain')
};
}
if (request.auth.mode === 'bearer') {
axiosRequest.headers['Authorization'] = `Bearer ${get(request, 'auth.bearer.token')}`;
}
if (request.auth.mode === 'wsse') {
const username = get(request, 'auth.wsse.username', '');
const password = get(request, 'auth.wsse.password', '');
const ts = new Date().toISOString();
const nonce = crypto.randomBytes(16).toString('hex');
// Create the password digest using SHA-1 as required for WSSE
const hash = crypto.createHash('sha1');
hash.update(nonce + ts + password);
const digest = Buffer.from(hash.digest('hex').toString('utf8')).toString('base64');
// Construct the WSSE header
axiosRequest.headers[
'X-WSSE'
] = `UsernameToken Username="${username}", PasswordDigest="${digest}", Nonce="${nonce}", Created="${ts}"`;
}
if (request.auth.mode === 'digest') {
axiosRequest.digestConfig = {
username: get(request, 'auth.digest.username'),
password: get(request, 'auth.digest.password')
};
}
if (request.auth.mode === 'oauth2') {
const grantType = get(request, 'auth.oauth2.grantType');
if (grantType === 'client_credentials') {
axiosRequest.oauth2 = {
grantType,
clientId: get(request, 'auth.oauth2.clientId'),
clientSecret: get(request, 'auth.oauth2.clientSecret'),
scope: get(request, 'auth.oauth2.scope'),
accessTokenUrl: get(request, 'auth.oauth2.accessTokenUrl'),
tokenPlacement: get(request, 'auth.oauth2.tokenPlacement'),
credentialsPlacement: get(request, 'auth.oauth2.credentialsPlacement'),
tokenHeaderPrefix: get(request, 'auth.oauth2.tokenHeaderPrefix'),
tokenQueryKey: get(request, 'auth.oauth2.tokenQueryKey')
};
} else if (grantType === 'password') {
axiosRequest.oauth2 = {
grantType,
username: get(request, 'auth.oauth2.username'),
password: get(request, 'auth.oauth2.password'),
clientId: get(request, 'auth.oauth2.clientId'),
clientSecret: get(request, 'auth.oauth2.clientSecret'),
scope: get(request, 'auth.oauth2.scope'),
accessTokenUrl: get(request, 'auth.oauth2.accessTokenUrl'),
tokenPlacement: get(request, 'auth.oauth2.tokenPlacement'),
credentialsPlacement: get(request, 'auth.oauth2.credentialsPlacement'),
tokenHeaderPrefix: get(request, 'auth.oauth2.tokenHeaderPrefix'),
tokenQueryKey: get(request, 'auth.oauth2.tokenQueryKey')
};
}
}
if (request.auth.mode === 'apikey') {
if (request.auth.apikey?.placement === 'header') {
axiosRequest.headers[request.auth.apikey?.key] = request.auth.apikey?.value;
}
if (request.auth.apikey?.placement === 'queryparams') {
if (axiosRequest.url && request.auth.apikey?.key) {
try {
const urlObj = new URL(request.url);
urlObj.searchParams.set(request.auth.apikey?.key, request.auth.apikey?.value);
axiosRequest.url = urlObj.toString();
} catch (error) {
console.error('Invalid URL:', request.url, error);
}
}
}
}
}
request.body = request.body || {};
if (request.body.mode === 'json') {
if (!contentTypeDefined) {
axiosRequest.headers['content-type'] = 'application/json';
}
try {
axiosRequest.data = decomment(request?.body?.json);
} catch (error) {
axiosRequest.data = request?.body?.json;
}
}
if (request.body.mode === 'text') {
if (!contentTypeDefined) {
axiosRequest.headers['content-type'] = 'text/plain';
}
axiosRequest.data = request.body.text;
}
if (request.body.mode === 'xml') {
if (!contentTypeDefined) {
axiosRequest.headers['content-type'] = 'application/xml';
}
axiosRequest.data = request.body.xml;
}
if (request.body.mode === 'sparql') {
if (!contentTypeDefined) {
axiosRequest.headers['content-type'] = 'application/sparql-query';
}
axiosRequest.data = request.body.sparql;
}
if (request.body.mode === 'formUrlEncoded') {
axiosRequest.headers['content-type'] = 'application/x-www-form-urlencoded';
const params = {};
const enabledParams = filter(request.body.formUrlEncoded, (p) => p.enabled);
each(enabledParams, (p) => (params[p.name] = p.value));
axiosRequest.data = params;
}
if (request.body.mode === 'multipartForm') {
axiosRequest.headers['content-type'] = 'multipart/form-data';
const enabledParams = filter(request.body.multipartForm, (p) => p.enabled);
axiosRequest.data = enabledParams;
}
if (request.body.mode === 'graphql') {
const graphqlQuery = {
query: get(request, 'body.graphql.query'),
};
try {
graphqlQuery.variables = JSON.parse(decomment(get(request, 'body.graphql.variables') || '{}'));
} catch (error) {
console.error(`Error parsing GraphQL variables: ${error.message}`);
console.error(`Variables content: ${get(request, 'body.graphql.variables') || '{}'}`);
throw new Error(`Invalid GraphQL variables: ${error.message}`);
}
if (!contentTypeDefined) {
axiosRequest.headers['content-type'] = 'application/json';
}
axiosRequest.data = graphqlQuery;
}
if (request.script) {
axiosRequest.script = request.script;
}
if (request.tests) {
axiosRequest.tests = request.tests;
}
axiosRequest.vars = request.vars;
axiosRequest.collectionVariables = request.collectionVariables;
axiosRequest.folderVariables = request.folderVariables;
axiosRequest.requestVariables = request.requestVariables;
return axiosRequest;
};
module.exports = prepareRequest;