[d24f17c] | 1 | // This function runs after the common function,
|
---|
| 2 | // `src/execute/index.js#buildRequest`
|
---|
| 3 | import { isPlainObject } from 'is-plain-object';
|
---|
| 4 | import btoa from '../../helpers/btoa.node.js';
|
---|
| 5 | export default function buildRequest(options, req) {
|
---|
| 6 | const {
|
---|
| 7 | operation,
|
---|
| 8 | requestBody,
|
---|
| 9 | securities,
|
---|
| 10 | spec,
|
---|
| 11 | attachContentTypeForEmptyPayload
|
---|
| 12 | } = options;
|
---|
| 13 | let {
|
---|
| 14 | requestContentType
|
---|
| 15 | } = options;
|
---|
| 16 | req = applySecurities({
|
---|
| 17 | request: req,
|
---|
| 18 | securities,
|
---|
| 19 | operation,
|
---|
| 20 | spec
|
---|
| 21 | });
|
---|
| 22 | const requestBodyDef = operation.requestBody || {};
|
---|
| 23 | const requestBodyMediaTypes = Object.keys(requestBodyDef.content || {});
|
---|
| 24 | const isExplicitContentTypeValid = requestContentType && requestBodyMediaTypes.indexOf(requestContentType) > -1;
|
---|
| 25 |
|
---|
| 26 | // for OAS3: set the Content-Type
|
---|
| 27 | if (requestBody || attachContentTypeForEmptyPayload) {
|
---|
| 28 | // does the passed requestContentType appear in the requestBody definition?
|
---|
| 29 |
|
---|
| 30 | if (requestContentType && isExplicitContentTypeValid) {
|
---|
| 31 | req.headers['Content-Type'] = requestContentType;
|
---|
| 32 | } else if (!requestContentType) {
|
---|
| 33 | const firstMediaType = requestBodyMediaTypes[0];
|
---|
| 34 | if (firstMediaType) {
|
---|
| 35 | req.headers['Content-Type'] = firstMediaType;
|
---|
| 36 | requestContentType = firstMediaType;
|
---|
| 37 | }
|
---|
| 38 | }
|
---|
| 39 | } else if (requestContentType && isExplicitContentTypeValid) {
|
---|
| 40 | req.headers['Content-Type'] = requestContentType;
|
---|
| 41 | }
|
---|
| 42 | if (!options.responseContentType && operation.responses) {
|
---|
| 43 | const mediaTypes = Object.entries(operation.responses).filter(([key, value]) => {
|
---|
| 44 | const code = parseInt(key, 10);
|
---|
| 45 | return code >= 200 && code < 300 && isPlainObject(value.content);
|
---|
| 46 | }).reduce((acc, [, value]) => acc.concat(Object.keys(value.content)), []);
|
---|
| 47 | if (mediaTypes.length > 0) {
|
---|
| 48 | req.headers.accept = mediaTypes.join(', ');
|
---|
| 49 | }
|
---|
| 50 | }
|
---|
| 51 |
|
---|
| 52 | // for OAS3: add requestBody to request
|
---|
| 53 | if (requestBody) {
|
---|
| 54 | if (requestContentType) {
|
---|
| 55 | if (requestBodyMediaTypes.indexOf(requestContentType) > -1) {
|
---|
| 56 | // only attach body if the requestBody has a definition for the
|
---|
| 57 | // contentType that has been explicitly set
|
---|
| 58 | if (requestContentType === 'application/x-www-form-urlencoded' || requestContentType === 'multipart/form-data') {
|
---|
| 59 | if (typeof requestBody === 'object') {
|
---|
| 60 | var _requestBodyDef$conte, _requestBodyDef$conte2;
|
---|
| 61 | const encoding = (_requestBodyDef$conte = (_requestBodyDef$conte2 = requestBodyDef.content[requestContentType]) === null || _requestBodyDef$conte2 === void 0 ? void 0 : _requestBodyDef$conte2.encoding) !== null && _requestBodyDef$conte !== void 0 ? _requestBodyDef$conte : {};
|
---|
| 62 | req.form = {};
|
---|
| 63 | Object.keys(requestBody).forEach(k => {
|
---|
| 64 | req.form[k] = {
|
---|
| 65 | value: requestBody[k],
|
---|
| 66 | encoding: encoding[k] || {}
|
---|
| 67 | };
|
---|
| 68 | });
|
---|
| 69 | } else {
|
---|
| 70 | req.form = requestBody;
|
---|
| 71 | }
|
---|
| 72 | } else {
|
---|
| 73 | req.body = requestBody;
|
---|
| 74 | }
|
---|
| 75 | }
|
---|
| 76 | } else {
|
---|
| 77 | req.body = requestBody;
|
---|
| 78 | }
|
---|
| 79 | }
|
---|
| 80 | return req;
|
---|
| 81 | }
|
---|
| 82 |
|
---|
| 83 | // Add security values, to operations - that declare their need on them
|
---|
| 84 | // Adapted from the Swagger2 implementation
|
---|
| 85 | export function applySecurities({
|
---|
| 86 | request,
|
---|
| 87 | securities = {},
|
---|
| 88 | operation = {},
|
---|
| 89 | spec
|
---|
| 90 | }) {
|
---|
| 91 | var _spec$components;
|
---|
| 92 | const result = {
|
---|
| 93 | ...request
|
---|
| 94 | };
|
---|
| 95 | const {
|
---|
| 96 | authorized = {}
|
---|
| 97 | } = securities;
|
---|
| 98 | const security = operation.security || spec.security || [];
|
---|
| 99 | const isAuthorized = authorized && !!Object.keys(authorized).length;
|
---|
| 100 | const securityDef = (spec === null || spec === void 0 || (_spec$components = spec.components) === null || _spec$components === void 0 ? void 0 : _spec$components.securitySchemes) || {};
|
---|
| 101 | result.headers = result.headers || {};
|
---|
| 102 | result.query = result.query || {};
|
---|
| 103 | if (!Object.keys(securities).length || !isAuthorized || !security || Array.isArray(operation.security) && !operation.security.length) {
|
---|
| 104 | return request;
|
---|
| 105 | }
|
---|
| 106 | security.forEach(securityObj => {
|
---|
| 107 | Object.keys(securityObj).forEach(key => {
|
---|
| 108 | const auth = authorized[key];
|
---|
| 109 | const schema = securityDef[key];
|
---|
| 110 | if (!auth) {
|
---|
| 111 | return;
|
---|
| 112 | }
|
---|
| 113 | const value = auth.value || auth;
|
---|
| 114 | const {
|
---|
| 115 | type
|
---|
| 116 | } = schema;
|
---|
| 117 | if (auth) {
|
---|
| 118 | if (type === 'apiKey') {
|
---|
| 119 | if (schema.in === 'query') {
|
---|
| 120 | result.query[schema.name] = value;
|
---|
| 121 | }
|
---|
| 122 | if (schema.in === 'header') {
|
---|
| 123 | result.headers[schema.name] = value;
|
---|
| 124 | }
|
---|
| 125 | if (schema.in === 'cookie') {
|
---|
| 126 | result.cookies[schema.name] = value;
|
---|
| 127 | }
|
---|
| 128 | } else if (type === 'http') {
|
---|
| 129 | if (/^basic$/i.test(schema.scheme)) {
|
---|
| 130 | const username = value.username || '';
|
---|
| 131 | const password = value.password || '';
|
---|
| 132 | const encoded = btoa(`${username}:${password}`);
|
---|
| 133 | result.headers.Authorization = `Basic ${encoded}`;
|
---|
| 134 | }
|
---|
| 135 | if (/^bearer$/i.test(schema.scheme)) {
|
---|
| 136 | result.headers.Authorization = `Bearer ${value}`;
|
---|
| 137 | }
|
---|
| 138 | } else if (type === 'oauth2' || type === 'openIdConnect') {
|
---|
| 139 | const token = auth.token || {};
|
---|
| 140 | const tokenName = schema['x-tokenName'] || 'access_token';
|
---|
| 141 | const tokenValue = token[tokenName];
|
---|
| 142 | let tokenType = token.token_type;
|
---|
| 143 | if (!tokenType || tokenType.toLowerCase() === 'bearer') {
|
---|
| 144 | tokenType = 'Bearer';
|
---|
| 145 | }
|
---|
| 146 | result.headers.Authorization = `${tokenType} ${tokenValue}`;
|
---|
| 147 | }
|
---|
| 148 | }
|
---|
| 149 | });
|
---|
| 150 | });
|
---|
| 151 | return result;
|
---|
| 152 | } |
---|