Repository: postmanlabs/postman-code-generators
Pull request #96 (2019-09-09 11:33:29)

Added logic to trim header keys and not trim header values
Postman-App’s behavior:

- It doesn’t allow sending request which have whitespaces before or after header keys, i.e. throws an error in postman console stating invalid token in header key. Hence to stay in aligned with the app, we will be trimming header keys

- Postman allows sending whitespaces before or after header values. Confirmed after looking at the request in postman console as well as wireshark. Hence won’t be manipulating anything with header values, and remove everywhere where trimRequestBody option was used to trim header values also.


Patch:
diff --git a/codegens/csharp-restsharp/lib/parseRequest.js b/codegens/csharp-restsharp/lib/parseRequest.js
index 54ce674..5998b76 100644
--- a/codegens/csharp-restsharp/lib/parseRequest.js
+++ b/codegens/csharp-restsharp/lib/parseRequest.js
@@ -84,7 +84,7 @@ function parseHeader (requestJson) {
 
   return requestJson.header.reduce((headerSnippet, header) => {
     if (!header.disabled) {
-      headerSnippet += `request.AddHeader("${sanitize(header.key)}", "${sanitize(header.value)}");\n`;
+      headerSnippet += `request.AddHeader("${sanitize(header.key, true)}", "${sanitize(header.value)}");\n`;
     }
     return headerSnippet;
   }, '');
diff --git a/codegens/curl/lib/index.js b/codegens/curl/lib/index.js
index 21811f8..2c6eb9b 100644
--- a/codegens/curl/lib/index.js
+++ b/codegens/curl/lib/index.js
@@ -53,7 +53,7 @@ self = module.exports = {
     }
     headersData = request.getHeaders({ enabled: true });
     _.forEach(headersData, function (value, key) {
-      snippet += indent + `${form('-H', format)} "${sanitize(key, trim)}: ${sanitize(value, trim)}"`;
+      snippet += indent + `${form('-H', format)} "${sanitize(key, true)}: ${sanitize(value)}"`;
     });
 
     if (request.body) {
diff --git a/codegens/golang/lib/index.js b/codegens/golang/lib/index.js
index c681d71..6730399 100644
--- a/codegens/golang/lib/index.js
+++ b/codegens/golang/lib/index.js
@@ -118,7 +118,7 @@ function parseHeaders (headers, indent) {
   var headerSnippet = '';
   if (!_.isEmpty(headers)) {
     _.forEach(headers, function (value, key) {
-      headerSnippet += `${indent}req.Header.Add("${sanitize(key)}", "${sanitize(value)}")\n`;
+      headerSnippet += `${indent}req.Header.Add("${sanitize(key, true)}", "${sanitize(value)}")\n`;
     });
   }
   return headerSnippet;
diff --git a/codegens/http/lib/util.js b/codegens/http/lib/util.js
index 37ff248..24aef63 100644
--- a/codegens/http/lib/util.js
+++ b/codegens/http/lib/util.js
@@ -173,6 +173,9 @@ function getHeaders (request) {
     }
   }
 
+  _.forEach(request.headers.members, (header) => {
+    header.key = header.key.trim();
+  });
   headers = convertPropertyListToString(request.headers, '\n', false);
   if (request.body.mode === 'formdata' && contentTypeIndex < 0) {
     headers += `Content-Type: ${formDataHeader}`;
diff --git a/codegens/java-okhttp/lib/parseRequest.js b/codegens/java-okhttp/lib/parseRequest.js
index d116a0c..1733e5c 100644
--- a/codegens/java-okhttp/lib/parseRequest.js
+++ b/codegens/java-okhttp/lib/parseRequest.js
@@ -99,7 +99,7 @@ function parseHeader (request, indentString) {
 
   if (!_.isEmpty(headerObject)) {
     headerSnippet += _.reduce(Object.keys(headerObject), function (accumalator, key) {
-      accumalator += indentString + `.addHeader("${sanitize(key)}", ` +
+      accumalator += indentString + `.addHeader("${sanitize(key, true)}", ` +
                            `"${sanitize(headerObject[key])}")\n`;
       return accumalator;
     }, '');
diff --git a/codegens/java-unirest/lib/parseRequest.js b/codegens/java-unirest/lib/parseRequest.js
index c9577ae..85d1be5 100644
--- a/codegens/java-unirest/lib/parseRequest.js
+++ b/codegens/java-unirest/lib/parseRequest.js
@@ -5,7 +5,7 @@ var _ = require('./lodash'),
 /**
  *
  * @param {*} urlObject The request sdk request.url object
- * @returns {String} The final string after parsing all the parameters of the url including 
+ * @returns {String} The final string after parsing all the parameters of the url including
  * protocol, auth, host, port, path, query, hash
  * This will be used because the url.toString() method returned the URL with non encoded query string
  * and hence a manual call is made to getQueryString() method with encode option set as true.
@@ -107,7 +107,7 @@ function parseHeader (request, indentString) {
     headerSnippet = '';
   if (!_.isEmpty(headerObject)) {
     headerSnippet += Object.keys(headerObject).reduce(function (accumlator, key) {
-      accumlator += indentString + `.header("${sanitize(key)}", "${sanitize(headerObject[key])}")\n`;
+      accumlator += indentString + `.header("${sanitize(key, true)}", "${sanitize(headerObject[key])}")\n`;
       return accumlator;
     }, '');
   }
diff --git a/codegens/js-fetch/lib/index.js b/codegens/js-fetch/lib/index.js
index ab46e59..03dc0bf 100644
--- a/codegens/js-fetch/lib/index.js
+++ b/codegens/js-fetch/lib/index.js
@@ -111,7 +111,7 @@ function parseHeaders (headers) {
   if (!_.isEmpty(headers)) {
     headerSnippet = 'var myHeaders = new Headers();\n';
     _.forEach(headers, function (value, key) {
-      headerSnippet += `myHeaders.append("${sanitize(key)}", "${sanitize(value)}");\n`;
+      headerSnippet += `myHeaders.append("${sanitize(key, true)}", "${sanitize(value)}");\n`;
     });
   }
   else {
diff --git a/codegens/js-jquery/lib/js-jquery.js b/codegens/js-jquery/lib/js-jquery.js
index 587ab6d..53a61b4 100644
--- a/codegens/js-jquery/lib/js-jquery.js
+++ b/codegens/js-jquery/lib/js-jquery.js
@@ -18,7 +18,7 @@ function getHeaders (request, indent) {
 
   if (!_.isEmpty(header)) {
     headerMap = _.map(Object.keys(header), function (key) {
-      return `${indent.repeat(2)}"${sanitize(key, 'header')}": ` +
+      return `${indent.repeat(2)}"${sanitize(key, 'header', true)}": ` +
           `"${sanitize(header[key], 'header')}"`;
     });
     return `${indent}"headers": {\n${headerMap.join(',\n')}\n${indent}},\n`;
diff --git a/codegens/js-xhr/lib/index.js b/codegens/js-xhr/lib/index.js
index 3f60b11..cf3990f 100644
--- a/codegens/js-xhr/lib/index.js
+++ b/codegens/js-xhr/lib/index.js
@@ -104,7 +104,7 @@ function parseHeaders (headers) {
   var headerSnippet = '';
   if (!_.isEmpty(headers)) {
     _.forEach(headers, function (value, key) {
-      headerSnippet += `xhr.setRequestHeader("${sanitize(key)}", "${sanitize(value)}");\n`;
+      headerSnippet += `xhr.setRequestHeader("${sanitize(key, true)}", "${sanitize(value)}");\n`;
     });
   }
   return headerSnippet;
diff --git a/codegens/libcurl/lib/index.js b/codegens/libcurl/lib/index.js
index 0dc0cb7..d56da41 100644
--- a/codegens/libcurl/lib/index.js
+++ b/codegens/libcurl/lib/index.js
@@ -50,7 +50,7 @@ self = module.exports = {
       });
     }
     _.forEach(headersData, function (value, key) {
-      snippet += indentString + `headers = curl_slist_append(headers, "${sanitize(key)}: ${sanitize(value)}");\n`;
+      snippet += indentString + `headers = curl_slist_append(headers, "${sanitize(key, true)}: ${sanitize(value)}");\n`;
     });
     body = request.body ? request.body.toJSON() : {};
     if (body.mode && body.mode === 'formdata' && !options.useMimeType) {
diff --git a/codegens/nodejs-native/lib/parseRequest.js b/codegens/nodejs-native/lib/parseRequest.js
index 8b04076..e65e5de 100644
--- a/codegens/nodejs-native/lib/parseRequest.js
+++ b/codegens/nodejs-native/lib/parseRequest.js
@@ -104,7 +104,7 @@ function parseHeader (request, indentString) {
   if (headerObject) {
     headerSnippet += _.reduce(Object.keys(headerObject), function (accumalator, key) {
       accumalator.push(
-        indentString.repeat(2) + `'${sanitize(key)}': '${sanitize(headerObject[key])}'`
+        indentString.repeat(2) + `'${sanitize(key, true)}': '${sanitize(headerObject[key])}'`
       );
       return accumalator;
     }, []).join(',\n');
diff --git a/codegens/nodejs-request/lib/parseRequest.js b/codegens/nodejs-request/lib/parseRequest.js
index f2f6c41..f894176 100644
--- a/codegens/nodejs-request/lib/parseRequest.js
+++ b/codegens/nodejs-request/lib/parseRequest.js
@@ -101,7 +101,7 @@ function parseHeader (request, indentString) {
   if (!_.isEmpty(headerObject)) {
     headerSnippet += _.reduce(Object.keys(headerObject), function (accumalator, key) {
       accumalator.push(
-        indentString.repeat(2) + `'${sanitize(key)}': '${sanitize(headerObject[key])}'`
+        indentString.repeat(2) + `'${sanitize(key, true)}': '${sanitize(headerObject[key])}'`
       );
       return accumalator;
     }, []).join(',\n') + '\n';
diff --git a/codegens/nodejs-unirest/lib/parseRequest.js b/codegens/nodejs-unirest/lib/parseRequest.js
index 44c5fc8..8386f04 100644
--- a/codegens/nodejs-unirest/lib/parseRequest.js
+++ b/codegens/nodejs-unirest/lib/parseRequest.js
@@ -89,7 +89,7 @@ function parseHeader (request, indentString) {
     headerSnippet += indentString + '.headers({\n';
 
     headerSnippet += _.reduce(Object.keys(headerObject), function (accumalator, key) {
-      accumalator.push(indentString.repeat(2) + `'${sanitize(key)}': '${sanitize(headerObject[key])}'`);
+      accumalator.push(indentString.repeat(2) + `'${sanitize(key, true)}': '${sanitize(headerObject[key])}'`);
       return accumalator;
     }, []).join(',\n') + '\n';
 
diff --git a/codegens/ocaml-cohttp/lib/ocaml.js b/codegens/ocaml-cohttp/lib/ocaml.js
index c5044ed..1184d72 100644
--- a/codegens/ocaml-cohttp/lib/ocaml.js
+++ b/codegens/ocaml-cohttp/lib/ocaml.js
@@ -150,7 +150,7 @@ function parseHeaders (bodyMode, headers, indent) {
   if (!_.isEmpty(headers)) {
     headerSnippet += `${indent}let headers = Header.init ()\n`;
     _.forEach(headers, function (value, key) {
-      headerSnippet += `${indent.repeat(2)}|> fun h -> Header.add h "${sanitize(key, 'header')}" `;
+      headerSnippet += `${indent.repeat(2)}|> fun h -> Header.add h "${sanitize(key, 'header', true)}" `;
       headerSnippet += `"${sanitize(value, 'header')}"\n`;
     });
   }
diff --git a/codegens/php-curl/lib/php-curl.js b/codegens/php-curl/lib/php-curl.js
index 7cc5c75..6f5e80b 100644
--- a/codegens/php-curl/lib/php-curl.js
+++ b/codegens/php-curl/lib/php-curl.js
@@ -17,7 +17,7 @@ function getHeaders (request, indentation) {
 
   if (!_.isEmpty(headerObject)) {
     headerMap = _.map(Object.keys(headerObject), function (key) {
-      return `${indentation.repeat(2)}"${sanitize(key, 'header')}: ` +
+      return `${indentation.repeat(2)}"${sanitize(key, 'header', true)}: ` +
             `${sanitize(headerObject[key], 'header')}"`;
     });
     return `${indentation}CURLOPT_HTTPHEADER => array(\n${headerMap.join(',\n')}\n${indentation}),\n`;
diff --git a/codegens/php-pecl-http/lib/phpPecl.js b/codegens/php-pecl-http/lib/phpPecl.js
index d120660..acfc27b 100644
--- a/codegens/php-pecl-http/lib/phpPecl.js
+++ b/codegens/php-pecl-http/lib/phpPecl.js
@@ -17,7 +17,7 @@ function getHeaders (request, indentation) {
 
   if (!_.isEmpty(headerObject)) {
     headerMap = _.map(Object.keys(headerObject), function (key) {
-      return `${indentation}'${sanitize(key)}' => ` +
+      return `${indentation}'${sanitize(key, true)}' => ` +
             `'${sanitize(headerObject[key])}'`;
     });
     return `$request->setHeaders(array(\n${headerMap.join(',\n')}\n));`;
diff --git a/codegens/powershell-restmethod/lib/index.js b/codegens/powershell-restmethod/lib/index.js
index 4804dc0..fdfe730 100644
--- a/codegens/powershell-restmethod/lib/index.js
+++ b/codegens/powershell-restmethod/lib/index.js
@@ -124,7 +124,7 @@ function parseHeaders (headers) {
   if (!_.isEmpty(headers)) {
     headerSnippet = '$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"\n';
     _.forEach(headers, function (value, key) {
-      headerSnippet += `$headers.Add("${sanitize(key)}", "${sanitize(value)}")\n`;
+      headerSnippet += `$headers.Add("${sanitize(key, true)}", "${sanitize(value)}")\n`;
     });
   }
   else {
diff --git a/codegens/python-http.client/lib/python-httpclient.js b/codegens/python-http.client/lib/python-httpclient.js
index 0c8c207..0418f9c 100644
--- a/codegens/python-http.client/lib/python-httpclient.js
+++ b/codegens/python-http.client/lib/python-httpclient.js
@@ -18,7 +18,7 @@ function getheaders (request, indentation) {
 
   if (!_.isEmpty(headerObject)) {
     headerMap = _.map(Object.keys(headerObject), function (key) {
-      return `${indentation}'${sanitize(key, 'header')}': ` +
+      return `${indentation}'${sanitize(key, 'header', true)}': ` +
             `'${sanitize(headerObject[key], 'header')}'`;
     });
     if (requestBodyMode === 'formdata') {
diff --git a/codegens/python-requests/lib/python-requests.js b/codegens/python-requests/lib/python-requests.js
index 3418cde..81c299c 100644
--- a/codegens/python-requests/lib/python-requests.js
+++ b/codegens/python-requests/lib/python-requests.js
@@ -17,7 +17,7 @@ function getheaders (request, indentation) {
 
   if (!_.isEmpty(headerObject)) {
     headerMap = _.map(Object.keys(headerObject), function (key) {
-      return `${indentation}'${sanitize(key, 'header')}': ` +
+      return `${indentation}'${sanitize(key, 'header', true)}': ` +
             `'${sanitize(headerObject[key], 'header')}'`;
     });
     return `headers = {\n${headerMap.join(',\n')}\n}\n`;
diff --git a/codegens/ruby/lib/ruby.js b/codegens/ruby/lib/ruby.js
index 13cd98a..0703ee7 100644
--- a/codegens/ruby/lib/ruby.js
+++ b/codegens/ruby/lib/ruby.js
@@ -14,7 +14,7 @@ function parseHeaders (headers) {
   var headerSnippet = '';
   if (!_.isEmpty(headers)) {
     _.forEach(headers, function (value, key) {
-      headerSnippet += `request["${key}"] = "${sanitize(value, 'header')}"\n`;
+      headerSnippet += `request["${sanitize(key, 'header', true)}"] = "${sanitize(value, 'header')}"\n`;
     });
   }
   return headerSnippet;
diff --git a/codegens/shell-httpie/lib/util/helpers.js b/codegens/shell-httpie/lib/util/helpers.js
index 64c3ea9..bca78f1 100644
--- a/codegens/shell-httpie/lib/util/helpers.js
+++ b/codegens/shell-httpie/lib/util/helpers.js
@@ -31,7 +31,7 @@ module.exports = {
       if (Array.isArray(request.headers.members) && request.headers.members.length) {
         request.headers.members = _.reject(request.headers.members, 'disabled');
         headerString = request.headers.members.map((header) => {
-          return ' ' + header.key + ':' + Sanitize.quote(header.value);
+          return ' ' + header.key.trim() + ':' + Sanitize.quote(header.value);
         }).join(' \\\n');
       }
       else {
diff --git a/codegens/shell-wget/lib/shell-wget.js b/codegens/shell-wget/lib/shell-wget.js
index 2fd7441..911c22b 100644
--- a/codegens/shell-wget/lib/shell-wget.js
+++ b/codegens/shell-wget/lib/shell-wget.js
@@ -17,7 +17,7 @@ function getHeaders (request, indentation) {
 
   if (!_.isEmpty(headerObject)) {
     headerMap = _.map(Object.keys(headerObject), function (key) {
-      return `${indentation}--header '${sanitize(key, 'header')}: ` +
+      return `${indentation}--header '${sanitize(key, 'header', true)}: ` +
             `${sanitize(headerObject[key], 'header')}' \\`;
     });
     return headerMap.join('\n');
diff --git a/codegens/swift/lib/swift.js b/codegens/swift/lib/swift.js
index ac68a5c..6827b3a 100644
--- a/codegens/swift/lib/swift.js
+++ b/codegens/swift/lib/swift.js
@@ -154,7 +154,7 @@ function parseHeaders (headers, mode) {
   if (!_.isEmpty(headers)) {
     _.forEach(headers, function (value, key) {
       headerSnippet += `request.addValue("${sanitize(value, 'header')}", `;
-      headerSnippet += `forHTTPHeaderField: "${sanitize(key, 'header')}")\n`;
+      headerSnippet += `forHTTPHeaderField: "${sanitize(key, 'header', true)}")\n`;
     });
   }
   if (mode === 'formdata') {


Test patch:
diff --git a/codegens/csharp-restsharp/test/unit/convert.test.js b/codegens/csharp-restsharp/test/unit/convert.test.js
index 06d66a8..26d122a 100644
--- a/codegens/csharp-restsharp/test/unit/convert.test.js
+++ b/codegens/csharp-restsharp/test/unit/convert.test.js
@@ -251,6 +251,34 @@ describe('csharp restsharp function', function () {
       });
     });
 
+    it('should trim header keys and not trim header values', function () {
+      var request = new sdk.Request({
+        'method': 'GET',
+        'header': [
+          {
+            'key': '  key_containing_whitespaces  ',
+            'value': '  value_containing_whitespaces  '
+          }
+        ],
+        'url': {
+          'raw': 'https://google.com',
+          'protocol': 'https',
+          'host': [
+            'google',
+            'com'
+          ]
+        }
+      });
+      convert(request, {}, function (error, snippet) {
+        if (error) {
+          expect.fail(null, null, error);
+        }
+        expect(snippet).to.be.a('string');
+        expect(snippet).to.include('request.AddHeader("key_containing_whitespaces", ' +
+        '"  value_containing_whitespaces  ")');
+      });
+    });
+
   });
 
   describe('getOptions function', function () {
diff --git a/codegens/curl/test/unit/convert.test.js b/codegens/curl/test/unit/convert.test.js
index d42c5f1..e7814eb 100644
--- a/codegens/curl/test/unit/convert.test.js
+++ b/codegens/curl/test/unit/convert.test.js
@@ -321,6 +321,34 @@ describe('curl convert function', function () {
       });
     });
 
+    it('should trim header keys and not trim header values', function () {
+      var request = new sdk.Request({
+        'method': 'GET',
+        'header': [
+          {
+            'key': '  key_containing_whitespaces  ',
+            'value': '  value_containing_whitespaces  '
+          }
+        ],
+        'url': {
+          'raw': 'https://google.com',
+          'protocol': 'https',
+          'host': [
+            'google',
+            'com'
+          ]
+        }
+      });
+      convert(request, { longFormat: true }, function (error, snippet) {
+        if (error) {
+          expect.fail(null, null, error);
+        }
+        expect(snippet).to.be.a('string');
+        // one extra space in matching the output because we add key:<space>value in the snippet
+        expect(snippet).to.include('--header "key_containing_whitespaces:   value_containing_whitespaces  "');
+      });
+    });
+
     describe('getUrlStringfromUrlObject function', function () {
       var rawUrl, urlObject, outputUrlString;
 
diff --git a/codegens/golang/test/unit/convert.test.js b/codegens/golang/test/unit/convert.test.js
index aac1652..054cf13 100644
--- a/codegens/golang/test/unit/convert.test.js
+++ b/codegens/golang/test/unit/convert.test.js
@@ -226,5 +226,32 @@ describe('Golang convert function', function () {
         expect(snippet).to.include('timeout := time.Duration(0.003 * time.Second)');
       });
     });
+
+    it('should trim header keys and not trim header values', function () {
+      var request = new sdk.Request({
+        'method': 'GET',
+        'header': [
+          {
+            'key': '  key_containing_whitespaces  ',
+            'value': '  value_containing_whitespaces  '
+          }
+        ],
+        'url': {
+          'raw': 'https://google.com',
+          'protocol': 'https',
+          'host': [
+            'google',
+            'com'
+          ]
+        }
+      });
+      convert(request, {}, function (error, snippet) {
+        if (error) {
+          expect.fail(null, null, error);
+        }
+        expect(snippet).to.be.a('string');
+        expect(snippet).to.include('req.Header.Add("key_containing_whitespaces", "  value_containing_whitespaces  ")');
+      });
+    });
   });
 });
diff --git a/codegens/http/test/unit/converter.test.js b/codegens/http/test/unit/converter.test.js
index 6ef8030..1fdba1c 100644
--- a/codegens/http/test/unit/converter.test.js
+++ b/codegens/http/test/unit/converter.test.js
@@ -20,6 +20,38 @@ describe('Converter test', function () {
       });
     });
   });
+
+  it('should trim header keys and not trim header values', function () {
+    var request = new Request({
+      'method': 'GET',
+      'header': [
+        {
+          'key': '  key_containing_whitespaces  ',
+          'value': '  value_containing_whitespaces  '
+        }
+      ],
+      'body': {
+        'mode': 'raw',
+        'raw': ''
+      },
+      'url': {
+        'raw': 'https://google.com',
+        'protocol': 'https',
+        'host': [
+          'google',
+          'com'
+        ]
+      }
+    });
+    convert(request, {}, function (error, snippet) {
+      if (error) {
+        expect.fail(null, null, error);
+      }
+      expect(snippet).to.be.a('string');
+      // one extra space in matching the output because we add key:<space>value in the snippet
+      expect(snippet).to.include('key_containing_whitespaces:   value_containing_whitespaces  ');
+    });
+  });
 });
 
 describe('Converter test using options.trimRequestBody', function () {
diff --git a/codegens/java-okhttp/test/unit/convert.test.js b/codegens/java-okhttp/test/unit/convert.test.js
index 0be789b..e2c646f 100644
--- a/codegens/java-okhttp/test/unit/convert.test.js
+++ b/codegens/java-okhttp/test/unit/convert.test.js
@@ -19,7 +19,7 @@ var expect = require('chai').expect,
 function runSnippet (codeSnippet, collection, done) {
   fs.writeFileSync('main.java', codeSnippet);
 
-  //  classpath of external libararies for java to compile 
+  //  classpath of external libararies for java to compile
   var compile = 'javac -cp *: main.java',
 
     //  bash command stirng for run compiled java file
@@ -227,6 +227,33 @@ describe('okhttp convert function', function () {
         }
       });
     });
+
+    it('should trim header keys and not trim header values', function () {
+      var request = new sdk.Request({
+        'method': 'GET',
+        'header': [
+          {
+            'key': '  key_containing_whitespaces  ',
+            'value': '  value_containing_whitespaces  '
+          }
+        ],
+        'url': {
+          'raw': 'https://google.com',
+          'protocol': 'https',
+          'host': [
+            'google',
+            'com'
+          ]
+        }
+      });
+      convert(request, {}, function (error, snippet) {
+        if (error) {
+          expect.fail(null, null, error);
+        }
+        expect(snippet).to.be.a('string');
+        expect(snippet).to.include('.addHeader("key_containing_whitespaces", "  value_containing_whitespaces  ")');
+      });
+    });
   });
 
   describe('getOptions function', function () {
diff --git a/codegens/java-unirest/test/unit/convert.test.js b/codegens/java-unirest/test/unit/convert.test.js
index a8b326f..86dfb02 100644
--- a/codegens/java-unirest/test/unit/convert.test.js
+++ b/codegens/java-unirest/test/unit/convert.test.js
@@ -364,6 +364,33 @@ describe('java unirest convert function for test collection', function () {
         expect(snippet).to.not.include('http://postman-echo.com/post?a=b c');
       });
     });
+
+    it('should trim header keys and not trim header values', function () {
+      var request = new sdk.Request({
+        'method': 'GET',
+        'header': [
+          {
+            'key': '  key_containing_whitespaces  ',
+            'value': '  value_containing_whitespaces  '
+          }
+        ],
+        'url': {
+          'raw': 'https://google.com',
+          'protocol': 'https',
+          'host': [
+            'google',
+            'com'
+          ]
+        }
+      });
+      convert(request, {}, function (error, snippet) {
+        if (error) {
+          expect.fail(null, null, error);
+        }
+        expect(snippet).to.be.a('string');
+        expect(snippet).to.include('.header("key_containing_whitespaces", "  value_containing_whitespaces  ")');
+      });
+    });
   });
   describe('getUrlStringfromUrlObject function', function () {
     var rawUrl, urlObject, outputUrlString;
diff --git a/codegens/js-fetch/test/unit/convert.test.js b/codegens/js-fetch/test/unit/convert.test.js
index bcd1a56..51a7c99 100644
--- a/codegens/js-fetch/test/unit/convert.test.js
+++ b/codegens/js-fetch/test/unit/convert.test.js
@@ -256,6 +256,34 @@ describe('js-fetch convert function for test collection', function () {
         expect(snippet).to.be.a('string');
       });
     });
+
+    it('should trim header keys and not trim header values', function () {
+      var request = new sdk.Request({
+        'method': 'GET',
+        'header': [
+          {
+            'key': '  key_containing_whitespaces  ',
+            'value': '  value_containing_whitespaces  '
+          }
+        ],
+        'url': {
+          'raw': 'https://google.com',
+          'protocol': 'https',
+          'host': [
+            'google',
+            'com'
+          ]
+        }
+      });
+      convert(request, {}, function (error, snippet) {
+        if (error) {
+          expect.fail(null, null, error);
+        }
+        expect(snippet).to.be.a('string');
+        expect(snippet).to.include('myHeaders.append("key_containing_whitespaces", ' +
+        '"  value_containing_whitespaces  ");');
+      });
+    });
   });
 
   describe('getOptions function', function () {
diff --git a/codegens/js-jquery/test/unit/converter.test.js b/codegens/js-jquery/test/unit/converter.test.js
index da974a0..62bc939 100644
--- a/codegens/js-jquery/test/unit/converter.test.js
+++ b/codegens/js-jquery/test/unit/converter.test.js
@@ -72,4 +72,31 @@ describe('jQuery converter', function () {
       expect(snippet).to.include('"method": "GET"');
     });
   });
+
+  it('should trim header keys and not trim header values', function () {
+    var request = new sdk.Request({
+      'method': 'GET',
+      'header': [
+        {
+          'key': '   key_containing_whitespaces  ',
+          'value': '  value_containing_whitespaces  '
+        }
+      ],
+      'url': {
+        'raw': 'https://google.com',
+        'protocol': 'https',
+        'host': [
+          'google',
+          'com'
+        ]
+      }
+    });
+    convert(request, {}, function (error, snippet) {
+      if (error) {
+        expect.fail(null, null, error);
+      }
+      expect(snippet).to.be.a('string');
+      expect(snippet).to.include('"key_containing_whitespaces": "  value_containing_whitespaces  "');
+    });
+  });
 });
diff --git a/codegens/js-xhr/test/unit/convert.test.js b/codegens/js-xhr/test/unit/convert.test.js
index 60258c0..050d882 100644
--- a/codegens/js-xhr/test/unit/convert.test.js
+++ b/codegens/js-xhr/test/unit/convert.test.js
@@ -142,6 +142,34 @@ describe('js-xhr convert function', function () {
         });
       });
     });
+
+    it('should trim header keys and not trim header values', function () {
+      var request = new sdk.Request({
+        'method': 'GET',
+        'header': [
+          {
+            'key': '   key_containing_whitespaces  ',
+            'value': '  value_containing_whitespaces  '
+          }
+        ],
+        'url': {
+          'raw': 'https://google.com',
+          'protocol': 'https',
+          'host': [
+            'google',
+            'com'
+          ]
+        }
+      });
+      convert(request, {}, function (error, snippet) {
+        if (error) {
+          expect.fail(null, null, error);
+        }
+        expect(snippet).to.be.a('string');
+        expect(snippet).to.include('xhr.setRequestHeader("key_containing_whitespaces", ' +
+        '"  value_containing_whitespaces  ")');
+      });
+    });
   });
 
   describe('Sanitize function', function () {
diff --git a/codegens/libcurl/test/unit/convert.test.js b/codegens/libcurl/test/unit/convert.test.js
index 78fde21..fcb00e1 100644
--- a/codegens/libcurl/test/unit/convert.test.js
+++ b/codegens/libcurl/test/unit/convert.test.js
@@ -195,6 +195,34 @@ describe('libcurl convert function', function () {
         expect(snippet).to.include('curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 3000L);');
       });
     });
+
+    it('should trim header keys and not trim header values', function () {
+      var request = new sdk.Request({
+        'method': 'GET',
+        'header': [
+          {
+            'key': '   key_containing_whitespaces  ',
+            'value': '  value_containing_whitespaces  '
+          }
+        ],
+        'url': {
+          'raw': 'https://google.com',
+          'protocol': 'https',
+          'host': [
+            'google',
+            'com'
+          ]
+        }
+      });
+      convert(request, {}, function (error, snippet) {
+        if (error) {
+          expect.fail(null, null, error);
+        }
+        expect(snippet).to.be.a('string');
+        expect(snippet).to.include('headers, "key_containing_whitespaces: ' +
+        '  value_containing_whitespaces  "');
+      });
+    });
   });
 
   describe('getOptions function', function () {
diff --git a/codegens/nodejs-native/test/unit/snippet.test.js b/codegens/nodejs-native/test/unit/snippet.test.js
index f1aa346..72d8b13 100644
--- a/codegens/nodejs-native/test/unit/snippet.test.js
+++ b/codegens/nodejs-native/test/unit/snippet.test.js
@@ -206,4 +206,31 @@ describe('nodejs-native convert function', function () {
       expect(snippet).to.include('\'port\': 3000');
     });
   });
+
+  it('should trim header keys and not trim header values', function () {
+    var request = new sdk.Request({
+      'method': 'GET',
+      'header': [
+        {
+          'key': '   key_containing_whitespaces  ',
+          'value': '  value_containing_whitespaces  '
+        }
+      ],
+      'url': {
+        'raw': 'https://google.com',
+        'protocol': 'https',
+        'host': [
+          'google',
+          'com'
+        ]
+      }
+    });
+    convert(request, {}, function (error, snippet) {
+      if (error) {
+        expect.fail(null, null, error);
+      }
+      expect(snippet).to.be.a('string');
+      expect(snippet).to.include('\'key_containing_whitespaces\': \'  value_containing_whitespaces  \'');
+    });
+  });
 });
diff --git a/codegens/nodejs-request/test/unit/snippet.test.js b/codegens/nodejs-request/test/unit/snippet.test.js
index 86c5269..fc19728 100644
--- a/codegens/nodejs-request/test/unit/snippet.test.js
+++ b/codegens/nodejs-request/test/unit/snippet.test.js
@@ -383,6 +383,33 @@ describe('nodejs-request convert function', function () {
       });
     });
 
+    it('should trim header keys and not trim header values', function () {
+      var request = new sdk.Request({
+        'method': 'GET',
+        'header': [
+          {
+            'key': '   key_containing_whitespaces  ',
+            'value': '  value_containing_whitespaces  '
+          }
+        ],
+        'url': {
+          'raw': 'https://google.com',
+          'protocol': 'https',
+          'host': [
+            'google',
+            'com'
+          ]
+        }
+      });
+      convert(request, {}, function (error, snippet) {
+        if (error) {
+          expect.fail(null, null, error);
+        }
+        expect(snippet).to.be.a('string');
+        expect(snippet).to.include('\'key_containing_whitespaces\': \'  value_containing_whitespaces  \'');
+      });
+    });
+
     describe('getOptions function', function () {
 
       it('should return an array of specific options', function () {
diff --git a/codegens/nodejs-unirest/test/unit/snippet.test.js b/codegens/nodejs-unirest/test/unit/snippet.test.js
index f8ef2f7..64a2257 100644
--- a/codegens/nodejs-unirest/test/unit/snippet.test.js
+++ b/codegens/nodejs-unirest/test/unit/snippet.test.js
@@ -218,6 +218,33 @@ describe('nodejs unirest convert function', function () {
         expect(snippet).to.not.include('.send');
       });
     });
+
+    it('should trim header keys and not trim header values', function () {
+      var request = new sdk.Request({
+        'method': 'GET',
+        'header': [
+          {
+            'key': '  key_containing_whitespaces  ',
+            'value': '  value_containing_whitespaces  '
+          }
+        ],
+        'url': {
+          'raw': 'https://google.com',
+          'protocol': 'https',
+          'host': [
+            'google',
+            'com'
+          ]
+        }
+      });
+      convert(request, {}, function (error, snippet) {
+        if (error) {
+          expect.fail(null, null, error);
+        }
+        expect(snippet).to.be.a('string');
+        expect(snippet).to.include('\'key_containing_whitespaces\': \'  value_containing_whitespaces  \'');
+      });
+    });
   });
 
   describe('getOptions function', function () {
diff --git a/codegens/ocaml-cohttp/test/unit/convert.test.js b/codegens/ocaml-cohttp/test/unit/convert.test.js
index dd41631..ffc4caa 100644
--- a/codegens/ocaml-cohttp/test/unit/convert.test.js
+++ b/codegens/ocaml-cohttp/test/unit/convert.test.js
@@ -212,6 +212,33 @@ describe('Ocaml convert function', function () {
         }
       });
     });
+
+    it('should trim header keys and not trim header values', function () {
+      var request = new sdk.Request({
+        'method': 'GET',
+        'header': [
+          {
+            'key': '   key_containing_whitespaces  ',
+            'value': '  value_containing_whitespaces  '
+          }
+        ],
+        'url': {
+          'raw': 'https://google.com',
+          'protocol': 'https',
+          'host': [
+            'google',
+            'com'
+          ]
+        }
+      });
+      convert(request, {}, function (error, snippet) {
+        if (error) {
+          expect.fail(null, null, error);
+        }
+        expect(snippet).to.be.a('string');
+        expect(snippet).to.include('Header.add h "key_containing_whitespaces" "  value_containing_whitespaces  "');
+      });
+    });
   });
 
   describe('getOptions function', function () {
diff --git a/codegens/php-curl/test/unit/converter.test.js b/codegens/php-curl/test/unit/converter.test.js
index 4d44616..ca120ae 100644
--- a/codegens/php-curl/test/unit/converter.test.js
+++ b/codegens/php-curl/test/unit/converter.test.js
@@ -151,4 +151,32 @@ describe('Curl converter', function () {
       .to.throw('Php-Curl~convert: Callback is not a function');
   });
 
+  it('should trim header keys and not trim header values', function () {
+    var request = new sdk.Request({
+      'method': 'GET',
+      'header': [
+        {
+          'key': '   key_containing_whitespaces  ',
+          'value': '  value_containing_whitespaces  '
+        }
+      ],
+      'url': {
+        'raw': 'https://google.com',
+        'protocol': 'https',
+        'host': [
+          'google',
+          'com'
+        ]
+      }
+    });
+    convert(request, {}, function (error, snippet) {
+      if (error) {
+        expect.fail(null, null, error);
+      }
+      expect(snippet).to.be.a('string');
+      // one extra space in matching the output because we add key:<space>value in the snippet
+      expect(snippet).to.include('"key_containing_whitespaces:   value_containing_whitespaces  "');
+    });
+  });
+
 });
diff --git a/codegens/php-pecl-http/test/unit/converter.test.js b/codegens/php-pecl-http/test/unit/converter.test.js
index d8eda85..dc6aadf 100644
--- a/codegens/php-pecl-http/test/unit/converter.test.js
+++ b/codegens/php-pecl-http/test/unit/converter.test.js
@@ -468,6 +468,33 @@ describe('Request Snippet', function () {
     });
   });
 
+  it('should trim header keys and not trim header values', function () {
+    var request = new sdk.Request({
+      'method': 'GET',
+      'header': [
+        {
+          'key': '   key_containing_whitespaces  ',
+          'value': '  value_containing_whitespaces  '
+        }
+      ],
+      'url': {
+        'raw': 'https://google.com',
+        'protocol': 'https',
+        'host': [
+          'google',
+          'com'
+        ]
+      }
+    });
+    convert(request, {}, function (error, snippet) {
+      if (error) {
+        expect.fail(null, null, error);
+      }
+      expect(snippet).to.be.a('string');
+      expect(snippet).to.include('\'key_containing_whitespaces\' => \'  value_containing_whitespaces  \'');
+    });
+  });
+
   describe('parseBody function', function () {
     it('should return empty string if request body is an empty string', function (done) {
       var request = {
diff --git a/codegens/powershell-restmethod/test/unit/convert.test.js b/codegens/powershell-restmethod/test/unit/convert.test.js
index cc5dda2..3d3de27 100644
--- a/codegens/powershell-restmethod/test/unit/convert.test.js
+++ b/codegens/powershell-restmethod/test/unit/convert.test.js
@@ -292,6 +292,33 @@ describe('Powershell-restmethod converter', function () {
         expect(snippet).to.not.equal('');
       });
     });
+
+    it('should trim header keys and not trim header values', function () {
+      var request = new sdk.Request({
+        'method': 'GET',
+        'header': [
+          {
+            'key': '   key_containing_whitespaces  ',
+            'value': '  value_containing_whitespaces  '
+          }
+        ],
+        'url': {
+          'raw': 'https://google.com',
+          'protocol': 'https',
+          'host': [
+            'google',
+            'com'
+          ]
+        }
+      });
+      convert(request, {}, function (error, snippet) {
+        if (error) {
+          expect.fail(null, null, error);
+        }
+        expect(snippet).to.be.a('string');
+        expect(snippet).to.include('$headers.Add("key_containing_whitespaces", "  value_containing_whitespaces  ")');
+      });
+    });
   });
 
   describe('getOptions function', function () {
diff --git a/codegens/python-http.client/test/unit/converter.test.js b/codegens/python-http.client/test/unit/converter.test.js
index 0122bd5..c01c64b 100644
--- a/codegens/python-http.client/test/unit/converter.test.js
+++ b/codegens/python-http.client/test/unit/converter.test.js
@@ -284,6 +284,33 @@ describe('Python-http.client converter', function () {
       });
     });
 
+    it('should trim header keys and not trim header values', function () {
+      var request = new sdk.Request({
+        'method': 'GET',
+        'header': [
+          {
+            'key': '   key_containing_whitespaces  ',
+            'value': '  value_containing_whitespaces  '
+          }
+        ],
+        'url': {
+          'raw': 'https://google.com',
+          'protocol': 'https',
+          'host': [
+            'google',
+            'com'
+          ]
+        }
+      });
+      convert(request, {}, function (error, snippet) {
+        if (error) {
+          expect.fail(null, null, error);
+        }
+        expect(snippet).to.be.a('string');
+        expect(snippet).to.include('\'key_containing_whitespaces\': \'  value_containing_whitespaces  \'');
+      });
+    });
+
   });
 
   describe('parseBody function', function () {
diff --git a/codegens/python-requests/test/unit/converter.test.js b/codegens/python-requests/test/unit/converter.test.js
index 687df3a..3dacd48 100644
--- a/codegens/python-requests/test/unit/converter.test.js
+++ b/codegens/python-requests/test/unit/converter.test.js
@@ -180,4 +180,31 @@ describe('Python- Requests converter', function () {
     });
   });
 
+  it('should trim header keys and not trim header values', function () {
+    var request = new sdk.Request({
+      'method': 'GET',
+      'header': [
+        {
+          'key': '   key_containing_whitespaces  ',
+          'value': '  value_containing_whitespaces  '
+        }
+      ],
+      'url': {
+        'raw': 'https://google.com',
+        'protocol': 'https',
+        'host': [
+          'google',
+          'com'
+        ]
+      }
+    });
+    convert(request, {}, function (error, snippet) {
+      if (error) {
+        expect.fail(null, null, error);
+      }
+      expect(snippet).to.be.a('string');
+      expect(snippet).to.include('\'key_containing_whitespaces\': \'  value_containing_whitespaces  \'');
+    });
+  });
+
 });
diff --git a/codegens/ruby/test/unit/converter.test.js b/codegens/ruby/test/unit/converter.test.js
index 1462b68..a9012fd 100644
--- a/codegens/ruby/test/unit/converter.test.js
+++ b/codegens/ruby/test/unit/converter.test.js
@@ -175,4 +175,31 @@ describe('Ruby converter', function () {
     });
   });
 
+  it('should trim header keys and not trim header values', function () {
+    var request = new sdk.Request({
+      'method': 'GET',
+      'header': [
+        {
+          'key': '   key_containing_whitespaces  ',
+          'value': '  value_containing_whitespaces  '
+        }
+      ],
+      'url': {
+        'raw': 'https://google.com',
+        'protocol': 'https',
+        'host': [
+          'google',
+          'com'
+        ]
+      }
+    });
+    convert(request, {}, function (error, snippet) {
+      if (error) {
+        expect.fail(null, null, error);
+      }
+      expect(snippet).to.be.a('string');
+      expect(snippet).to.include('request["key_containing_whitespaces"] = "  value_containing_whitespaces  "');
+    });
+  });
+
 });
diff --git a/codegens/shell-httpie/test/unit/converter.test.js b/codegens/shell-httpie/test/unit/converter.test.js
index 07ade3a..017c3e9 100644
--- a/codegens/shell-httpie/test/unit/converter.test.js
+++ b/codegens/shell-httpie/test/unit/converter.test.js
@@ -195,6 +195,33 @@ describe('Shell-Httpie convert function', function () {
       expect(snippet).to.include('GET localhost:3000/getSelfBody');
     });
   });
+
+  it('should trim header keys and not trim header values', function () {
+    var request = new sdk.Request({
+      'method': 'GET',
+      'header': [
+        {
+          'key': '   key_containing_whitespaces  ',
+          'value': '  value_containing_whitespaces  '
+        }
+      ],
+      'url': {
+        'raw': 'https://google.com',
+        'protocol': 'https',
+        'host': [
+          'google',
+          'com'
+        ]
+      }
+    });
+    convert(request, {}, function (error, snippet) {
+      if (error) {
+        expect.fail(null, null, error);
+      }
+      expect(snippet).to.be.a('string');
+      expect(snippet).to.include('key_containing_whitespaces:\'  value_containing_whitespaces  \'');
+    });
+  });
 });
 
 describe('Sanitize function', function () {
diff --git a/codegens/shell-wget/test/unit/converter.test.js b/codegens/shell-wget/test/unit/converter.test.js
index 673d73d..472ac64 100644
--- a/codegens/shell-wget/test/unit/converter.test.js
+++ b/codegens/shell-wget/test/unit/converter.test.js
@@ -212,6 +212,34 @@ describe('Shell-Wget converter', function () {
         expect(snippet).to.include('--timeout=0');
       });
     });
+
+    it('should trim header keys and not trim header values', function () {
+      var request = new sdk.Request({
+        'method': 'GET',
+        'header': [
+          {
+            'key': '   key_containing_whitespaces  ',
+            'value': '  value_containing_whitespaces  '
+          }
+        ],
+        'url': {
+          'raw': 'https://google.com',
+          'protocol': 'https',
+          'host': [
+            'google',
+            'com'
+          ]
+        }
+      });
+      convert(request, {}, function (error, snippet) {
+        if (error) {
+          expect.fail(null, null, error);
+        }
+        expect(snippet).to.be.a('string');
+        // one extra space in matching the output because we add key:<space>value in the snippet
+        expect(snippet).to.include('--header \'key_containing_whitespaces:   value_containing_whitespaces  \'');
+      });
+    });
   });
 
   describe('getOptions function', function () {
diff --git a/codegens/swift/test/unit/convert.test.js b/codegens/swift/test/unit/convert.test.js
index 48fad0f..59dbadf 100644
--- a/codegens/swift/test/unit/convert.test.js
+++ b/codegens/swift/test/unit/convert.test.js
@@ -255,6 +255,34 @@ describe('Swift Converter', function () {
         expect(snippet).to.not.include('http://postman-echo.com/post?a=b c');
       });
     });
+
+    it('should trim header keys and not trim header values', function () {
+      var request = new sdk.Request({
+        'method': 'GET',
+        'header': [
+          {
+            'key': '   key_containing_whitespaces  ',
+            'value': '  value_containing_whitespaces  '
+          }
+        ],
+        'url': {
+          'raw': 'https://google.com',
+          'protocol': 'https',
+          'host': [
+            'google',
+            'com'
+          ]
+        }
+      });
+      convert(request, {}, function (error, snippet) {
+        if (error) {
+          expect.fail(null, null, error);
+        }
+        expect(snippet).to.be.a('string');
+        expect(snippet).to.include('request.addValue("  value_containing_whitespaces  ", ' +
+        'forHTTPHeaderField: "key_containing_whitespaces")');
+      });
+    });
   });
 
   describe('getUrlStringfromUrlObject function', function () {