@readme/httpsnippet 2.5.1 → 3.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/README.md +19 -9
  2. package/package.json +24 -28
  3. package/src/helpers/code-builder.js +85 -80
  4. package/src/helpers/form-data.js +27 -25
  5. package/src/helpers/headers.js +10 -19
  6. package/src/helpers/reducer.js +10 -14
  7. package/src/index.js +167 -146
  8. package/src/targets/c/index.js +3 -5
  9. package/src/targets/c/libcurl.js +18 -23
  10. package/src/targets/clojure/clj_http.js +103 -87
  11. package/src/targets/clojure/index.js +3 -5
  12. package/src/targets/csharp/httpclient.js +90 -90
  13. package/src/targets/csharp/index.js +3 -5
  14. package/src/targets/csharp/restsharp.js +20 -22
  15. package/src/targets/go/index.js +3 -5
  16. package/src/targets/go/native.js +46 -53
  17. package/src/targets/http/http1.1.js +26 -36
  18. package/src/targets/http/index.js +3 -5
  19. package/src/targets/index.js +2 -4
  20. package/src/targets/java/asynchttp.js +22 -23
  21. package/src/targets/java/index.js +3 -5
  22. package/src/targets/java/nethttp.js +20 -24
  23. package/src/targets/java/okhttp.js +31 -31
  24. package/src/targets/java/unirest.js +22 -19
  25. package/src/targets/javascript/axios.js +43 -38
  26. package/src/targets/javascript/fetch.js +66 -68
  27. package/src/targets/javascript/index.js +3 -5
  28. package/src/targets/javascript/jquery.js +46 -40
  29. package/src/targets/javascript/xhr.js +42 -38
  30. package/src/targets/kotlin/index.js +3 -5
  31. package/src/targets/kotlin/okhttp.js +31 -31
  32. package/src/targets/node/axios.js +33 -30
  33. package/src/targets/node/fetch.js +89 -83
  34. package/src/targets/node/index.js +4 -5
  35. package/src/targets/node/native.js +36 -30
  36. package/src/targets/node/request.js +64 -64
  37. package/src/targets/node/unirest.js +56 -55
  38. package/src/targets/objc/helpers.js +24 -23
  39. package/src/targets/objc/index.js +3 -5
  40. package/src/targets/objc/nsurlsession.js +73 -45
  41. package/src/targets/ocaml/cohttp.js +29 -27
  42. package/src/targets/ocaml/index.js +3 -5
  43. package/src/targets/php/curl.js +86 -82
  44. package/src/targets/php/guzzle.js +135 -0
  45. package/src/targets/php/helpers.js +29 -28
  46. package/src/targets/php/http1.js +33 -44
  47. package/src/targets/php/http2.js +70 -71
  48. package/src/targets/php/index.js +5 -5
  49. package/src/targets/powershell/common.js +35 -30
  50. package/src/targets/powershell/index.js +3 -5
  51. package/src/targets/powershell/restmethod.js +3 -5
  52. package/src/targets/powershell/webrequest.js +3 -5
  53. package/src/targets/python/helpers.js +37 -34
  54. package/src/targets/python/index.js +4 -5
  55. package/src/targets/python/python3.js +33 -44
  56. package/src/targets/python/requests.js +47 -72
  57. package/src/targets/r/httr.js +59 -70
  58. package/src/targets/r/index.js +3 -5
  59. package/src/targets/ruby/index.js +3 -5
  60. package/src/targets/ruby/native.js +39 -33
  61. package/src/targets/shell/curl.js +74 -52
  62. package/src/targets/shell/helpers.js +7 -9
  63. package/src/targets/shell/httpie.js +45 -39
  64. package/src/targets/shell/index.js +4 -5
  65. package/src/targets/shell/wget.js +20 -22
  66. package/src/targets/swift/helpers.js +35 -32
  67. package/src/targets/swift/index.js +3 -5
  68. package/src/targets/swift/nsurlsession.js +53 -39
package/README.md CHANGED
@@ -30,7 +30,7 @@ const HTTPSnippet = require('httpsnippet');
30
30
 
31
31
  const snippet = new HTTPSnippet({
32
32
  method: 'GET',
33
- url: 'http://mockbin.com/request'
33
+ url: 'https://httpbin.com/anything'
34
34
  });
35
35
  ```
36
36
 
@@ -40,7 +40,7 @@ Type: `object`
40
40
 
41
41
  Available options:
42
42
 
43
- * `escapeQueryStrings` (`boolean`): In the event of you supplying a `source` that alreay contains escaped query strings, this allows you to disable automatic of query strings and prevents them from being double-escaped.
43
+ * `harIsAlreadyEncoded` (`boolean`): In the event of you supplying a `source` HAR that already contains escaped data (query and cookie parameters)strings, this allows you to disable automatic encoding of those parameters to prevent them from being double-escaped.
44
44
 
45
45
  ### convert(target [, options])
46
46
 
@@ -62,7 +62,7 @@ const HTTPSnippet = require('httpsnippet');
62
62
 
63
63
  const snippet = new HTTPSnippet({
64
64
  method: 'GET',
65
- url: 'http://mockbin.com/request'
65
+ url: 'https://httpbin.com/anything'
66
66
  });
67
67
 
68
68
  // generate Node.js: Native output
@@ -100,7 +100,7 @@ const HTTPSnippet = require('httpsnippet');
100
100
 
101
101
  const snippet = new HTTPSnippet({
102
102
  method: 'GET',
103
- url: 'http://mockbin.com/request'
103
+ url: 'https://httpbin.com/anything'
104
104
  });
105
105
 
106
106
  // generate Shell: cURL output
@@ -147,7 +147,7 @@ HTTPSnippet.addTargetClient('node', customClient);
147
147
 
148
148
  ## Documentation
149
149
 
150
- At the heart of this module is the [HAR Format](http://www.softwareishard.com/blog/har-12-spec/#request) as the HTTP request description format, please review some of the sample JSON HAR Request objects in [test fixtures](/test/fixtures/requests), or read the [HAR Docs](http://www.softwareishard.com/blog/har-12-spec/#request) for more details.
150
+ At the heart of this module is the [HAR Format](http://www.softwareishard.com/blog/har-12-spec/#request) as the HTTP request description format, please review some of the sample JSON HAR Request objects in [test fixtures](/__tests__/__fixtures__/requests), or read the [HAR Docs](http://www.softwareishard.com/blog/har-12-spec/#request) for more details.
151
151
 
152
152
  For detailed information on each target, please review the [wiki](https://github.com/kong/httpsnippet/wiki).
153
153
 
@@ -155,10 +155,20 @@ For detailed information on each target, please review the [wiki](https://github
155
155
 
156
156
  The main difference between this library and the upstream [httpsnippet](https://github.com/Kong/httpsnippet) library are:
157
157
 
158
- * This targets Node 10+
159
- * Does not ship with a CLI component
160
- * Adds a `useObjectBody` option to the `node` and `javascript` targets. This option is a boolean flag that causes the request body to be rendered as an object literal wrapped in `JSON.stringify`. If disabled, it falls back to the original behavior of a stringified object body. This flag defaults to disabled.
161
- * Contains a `escapeQueryStrings` option on the core library to disable escaping of query strings in URLs. Helpful if the HAR being supplied already has them escaped.
158
+ * Does not ship with a CLI component.
159
+ * The `fetch` target for Node and JS both treat body payloads as an object literal and wrap it within `JSON.stringify()`. We do this to keep those targets looking nicer with those kinds of payloads.
160
+ * Contains a `harIsAlreadyEncoded` option on the core library to disable [escaping](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent) of cookies and query strings in URLs. Helpful if the HAR being supplied already has them escaped.
161
+ * PHP Guzzle snippets come with `require_once('vendor/autoload.php');` at the top of them.
162
+ * A full integration suite for testing out snippets the library creates.
163
+
164
+ ### Running the integration suite
165
+
166
+ ```
167
+ docker-compose run integration_node
168
+ docker-compose run integration_php
169
+ docker-compose run integration_python
170
+ docker-compose run integration_shell
171
+ ```
162
172
 
163
173
  ## License
164
174
 
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "2.5.1",
2
+ "version": "3.0.3",
3
3
  "name": "@readme/httpsnippet",
4
4
  "description": "HTTP Request snippet generator for *most* languages",
5
5
  "homepage": "https://github.com/readmeio/httpsnippet",
@@ -47,39 +47,35 @@
47
47
  "url": "https://github.com/readmeio/httpsnippet.git"
48
48
  },
49
49
  "scripts": {
50
- "coverage": "istanbul cover --dir coverage _mocha -- --fgrep 'Request Validation' --invert -R dot",
51
- "posttest": "npm run coverage",
52
- "pretest": "standard && echint",
53
- "quick": "mocha --no-timeouts --fgrep 'Request Validation' --invert",
54
- "test": "mocha --no-timeouts"
55
- },
56
- "standard": {
57
- "env": "mocha",
58
- "ignore": [
59
- "**/test/fixtures/**"
60
- ]
61
- },
62
- "echint": {
63
- "ignore": [
64
- "coverage/**",
65
- "**/node_modules/**",
66
- "**/fixtures/**"
67
- ]
50
+ "lint": "eslint .",
51
+ "pretest": "npm run lint",
52
+ "prettier": "prettier --list-different --write \"./**/**.js\"",
53
+ "test": "jest --coverage"
68
54
  },
69
55
  "devDependencies": {
70
- "echint": "^4.0.2",
71
- "glob": "^7.1.6",
72
- "istanbul": "^0.4.0",
73
- "mocha": "^8.2.1",
74
- "require-directory": "^2.1.1",
75
- "should": "^13.2.3",
76
- "standard": "^16.0.3"
56
+ "@readme/eslint-config": "^8.0.2",
57
+ "eslint": "^8.3.0",
58
+ "glob": "^7.1.7",
59
+ "jest": "^27.2.0",
60
+ "prettier": "^2.5.0",
61
+ "require-directory": "^2.1.1"
77
62
  },
78
63
  "dependencies": {
79
64
  "event-stream": "4.0.1",
80
- "form-data": "3.0.0",
65
+ "form-data": "^4.0.0",
81
66
  "har-validator": "^5.0.0",
82
- "qs": "^6.9.6",
67
+ "qs": "^6.10.1",
83
68
  "stringify-object": "^3.3.0"
69
+ },
70
+ "prettier": "@readme/eslint-config/prettier",
71
+ "jest": {
72
+ "coveragePathIgnorePatterns": [
73
+ "<rootDir>/__tests__/(.*)/__fixtures__/",
74
+ "<rootDir>/node_modules"
75
+ ],
76
+ "testPathIgnorePatterns": [
77
+ "<rootDir>/__tests__/__fixtures__/",
78
+ "<rootDir>/__tests__/targets/"
79
+ ]
84
80
  }
85
81
  }
@@ -1,6 +1,5 @@
1
- 'use strict'
2
-
3
- const util = require('util')
1
+ /* eslint-disable no-param-reassign */
2
+ const { format } = require('util');
4
3
 
5
4
  /**
6
5
  * Helper object to format and aggragate lines of code.
@@ -11,93 +10,99 @@ const util = require('util')
11
10
  * @param {string} indentation Desired indentation character for aggregated lines of code
12
11
  * @param {string} join Desired character to join each line of code
13
12
  */
14
- const CodeBuilder = function (indentation, join) {
15
- this.code = []
16
- this.indentation = indentation
17
- this.lineJoin = join || '\n'
18
- }
19
-
20
- /**
21
- * Add given indentation level to given string and format the string (variadic)
22
- * @param {number} [indentationLevel=0] - Desired level of indentation for this line
23
- * @param {string} line - Line of code. Can contain formatting placeholders
24
- * @param {...anyobject} - Parameter to bind to `line`'s formatting placeholders
25
- * @return {string}
26
- *
27
- * @example
28
- * var builder = CodeBuilder('\t')
29
- *
30
- * builder.buildLine('console.log("hello world")')
31
- * // returns: 'console.log("hello world")'
32
- *
33
- * builder.buildLine(2, 'console.log("hello world")')
34
- * // returns: 'console.log("\t\thello world")'
35
- *
36
- * builder.buildLine(2, 'console.log("%s %s")', 'hello', 'world')
37
- * // returns: 'console.log("\t\thello world")'
38
- */
39
- CodeBuilder.prototype.buildLine = function (indentationLevel, line) {
40
- let lineIndentation = ''
41
- let slice = 2
42
- if (Object.prototype.toString.call(indentationLevel) === '[object String]') {
43
- slice = 1
44
- line = indentationLevel
45
- indentationLevel = 0
46
- } else if (indentationLevel === null) {
47
- return null
13
+ class CodeBuilder {
14
+ constructor(indentation, join) {
15
+ this.code = [];
16
+ this.indentation = indentation;
17
+ this.lineJoin = join || '\n';
48
18
  }
49
19
 
50
- while (indentationLevel) {
51
- lineIndentation += this.indentation
52
- indentationLevel--
53
- }
20
+ /**
21
+ * Add given indentation level to given string and format the string (variadic)
22
+ * @param {number} [indentationLevel=0] - Desired level of indentation for this line
23
+ * @param {string} line - Line of code. Can contain formatting placeholders
24
+ * @param {...anyobject} - Parameter to bind to `line`'s formatting placeholders
25
+ * @return {string}
26
+ *
27
+ * @example
28
+ * var builder = CodeBuilder('\t')
29
+ *
30
+ * builder.buildLine('console.log("hello world")')
31
+ * // returns: 'console.log("hello world")'
32
+ *
33
+ * builder.buildLine(2, 'console.log("hello world")')
34
+ * // returns: 'console.log("\t\thello world")'
35
+ *
36
+ * builder.buildLine(2, 'console.log("%s %s")', 'hello', 'world')
37
+ * // returns: 'console.log("\t\thello world")'
38
+ */
39
+ buildLine(indentationLevel, line) {
40
+ let lineIndentation = '';
41
+ let slice = 2;
42
+ if (Object.prototype.toString.call(indentationLevel) === '[object String]') {
43
+ slice = 1;
44
+ line = indentationLevel;
45
+ indentationLevel = 0;
46
+ } else if (indentationLevel === null) {
47
+ return null;
48
+ }
54
49
 
55
- const format = Array.prototype.slice.call(arguments, slice, arguments.length)
56
- format.unshift(lineIndentation + line)
50
+ while (indentationLevel) {
51
+ lineIndentation += this.indentation;
52
+ // eslint-disable-next-line no-plusplus
53
+ indentationLevel--;
54
+ }
57
55
 
58
- return util.format.apply(this, format)
59
- }
56
+ // eslint-disable-next-line prefer-rest-params
57
+ const data = Array.prototype.slice.call(arguments, slice, arguments.length);
58
+ data.unshift(lineIndentation + line);
60
59
 
61
- /**
62
- * Invoke buildLine() and add the line at the top of current lines
63
- * @param {number} [indentationLevel=0] Desired level of indentation for this line
64
- * @param {string} line Line of code
65
- * @return {this}
66
- */
67
- CodeBuilder.prototype.unshift = function () {
68
- this.code.unshift(this.buildLine.apply(this, arguments))
60
+ return format.apply(this, data);
61
+ }
69
62
 
70
- return this
71
- }
63
+ /**
64
+ * Invoke buildLine() and add the line at the top of current lines
65
+ * @param {number} [indentationLevel=0] Desired level of indentation for this line
66
+ * @param {string} line Line of code
67
+ * @return {this}
68
+ */
69
+ unshift(...args) {
70
+ // eslint-disable-next-line prefer-spread
71
+ this.code.unshift(this.buildLine.apply(this, args));
72
72
 
73
- /**
74
- * Invoke buildLine() and add the line at the bottom of current lines
75
- * @param {number} [indentationLevel=0] Desired level of indentation for this line
76
- * @param {string} line Line of code
77
- * @return {this}
78
- */
79
- CodeBuilder.prototype.push = function () {
80
- this.code.push(this.buildLine.apply(this, arguments))
73
+ return this;
74
+ }
81
75
 
82
- return this
83
- }
76
+ /**
77
+ * Invoke buildLine() and add the line at the bottom of current lines
78
+ * @param {number} [indentationLevel=0] Desired level of indentation for this line
79
+ * @param {string} line Line of code
80
+ * @return {this}
81
+ */
82
+ push(...args) {
83
+ // eslint-disable-next-line prefer-spread
84
+ this.code.push(this.buildLine.apply(this, args));
84
85
 
85
- /**
86
- * Add an empty line at the end of current lines
87
- * @return {this}
88
- */
89
- CodeBuilder.prototype.blank = function () {
90
- this.code.push(null)
86
+ return this;
87
+ }
91
88
 
92
- return this
93
- }
89
+ /**
90
+ * Add an empty line at the end of current lines
91
+ * @return {this}
92
+ */
93
+ blank() {
94
+ this.code.push(null);
94
95
 
95
- /**
96
- * Concatenate all current lines using the given lineJoin
97
- * @return {string}
98
- */
99
- CodeBuilder.prototype.join = function () {
100
- return this.code.join(this.lineJoin)
96
+ return this;
97
+ }
98
+
99
+ /**
100
+ * Concatenate all current lines using the given lineJoin
101
+ * @return {string}
102
+ */
103
+ join() {
104
+ return this.code.join(this.lineJoin);
105
+ }
101
106
  }
102
107
 
103
- module.exports = CodeBuilder
108
+ module.exports = CodeBuilder;
@@ -26,10 +26,10 @@
26
26
  * Extracted from https://github.com/node-fetch/node-fetch/blob/64c5c296a0250b852010746c76144cb9e14698d9/src/utils/form-data.js
27
27
  */
28
28
 
29
- const carriage = '\r\n'
30
- const dashes = '-'.repeat(2)
29
+ const carriage = '\r\n';
30
+ const dashes = '-'.repeat(2);
31
31
 
32
- const NAME = Symbol.toStringTag
32
+ const NAME = Symbol.toStringTag;
33
33
 
34
34
  const isBlob = object => {
35
35
  return (
@@ -39,13 +39,13 @@ const isBlob = object => {
39
39
  typeof object.stream === 'function' &&
40
40
  typeof object.constructor === 'function' &&
41
41
  /^(Blob|File)$/.test(object[NAME])
42
- )
43
- }
42
+ );
43
+ };
44
44
 
45
45
  /**
46
46
  * @param {string} boundary
47
47
  */
48
- const getFooter = boundary => `${dashes}${boundary}${dashes}${carriage.repeat(2)}`
48
+ const getFooter = boundary => `${dashes}${boundary}${dashes}${carriage.repeat(2)}`;
49
49
 
50
50
  /**
51
51
  * @param {string} boundary
@@ -54,18 +54,18 @@ const getFooter = boundary => `${dashes}${boundary}${dashes}${carriage.repeat(2)
54
54
  *
55
55
  * @return {string}
56
56
  */
57
- function getHeader (boundary, name, field) {
58
- let header = ''
57
+ function getHeader(boundary, name, field) {
58
+ let header = '';
59
59
 
60
- header += `${dashes}${boundary}${carriage}`
61
- header += `Content-Disposition: form-data; name="${name}"`
60
+ header += `${dashes}${boundary}${carriage}`;
61
+ header += `Content-Disposition: form-data; name="${name}"`;
62
62
 
63
63
  if (isBlob(field)) {
64
- header += `; filename="${field.name}"${carriage}`
65
- header += `Content-Type: ${field.type || 'application/octet-stream'}`
64
+ header += `; filename="${field.name}"${carriage}`;
65
+ header += `Content-Type: ${field.type || 'application/octet-stream'}`;
66
66
  }
67
67
 
68
- return `${header}${carriage.repeat(2)}`
68
+ return `${header}${carriage.repeat(2)}`;
69
69
  }
70
70
 
71
71
  /**
@@ -74,32 +74,34 @@ function getHeader (boundary, name, field) {
74
74
  module.exports.getBoundary = () => {
75
75
  // This generates a 50 character boundary similar to those used by Firefox.
76
76
  // They are optimized for boyer-moore parsing.
77
- let boundary = '--------------------------'
77
+ let boundary = '--------------------------';
78
+ // eslint-disable-next-line no-plusplus
78
79
  for (let i = 0; i < 24; i++) {
79
- boundary += Math.floor(Math.random() * 10).toString(16)
80
+ boundary += Math.floor(Math.random() * 10).toString(16);
80
81
  }
81
82
 
82
- return boundary
83
- }
83
+ return boundary;
84
+ };
84
85
 
85
86
  /**
86
87
  * @param {FormData} form
87
88
  * @param {string} boundary
88
89
  */
89
- module.exports.formDataIterator = function * (form, boundary) {
90
+ module.exports.formDataIterator = function* (form, boundary) {
91
+ // eslint-disable-next-line no-restricted-syntax
90
92
  for (const [name, value] of form) {
91
- yield getHeader(boundary, name, value)
93
+ yield getHeader(boundary, name, value);
92
94
 
93
95
  if (isBlob(value)) {
94
- yield * value.stream()
96
+ yield* value.stream();
95
97
  } else {
96
- yield value
98
+ yield value;
97
99
  }
98
100
 
99
- yield carriage
101
+ yield carriage;
100
102
  }
101
103
 
102
- yield getFooter(boundary)
103
- }
104
+ yield getFooter(boundary);
105
+ };
104
106
 
105
- module.exports.isBlob = isBlob
107
+ module.exports.isBlob = isBlob;
@@ -7,7 +7,7 @@ module.exports = {
7
7
  * @return {string}
8
8
  */
9
9
  getHeader: (headers, name) => {
10
- return headers[Object.keys(headers).find(k => k.toLowerCase() === name.toLowerCase())]
10
+ return headers[Object.keys(headers).find(k => k.toLowerCase() === name.toLowerCase())];
11
11
  },
12
12
 
13
13
  /**
@@ -18,12 +18,9 @@ module.exports = {
18
18
  * @return {string}
19
19
  */
20
20
  getHeaderName: (headers, name) => {
21
- // eslint-disable-next-line array-callback-return
22
21
  return Object.keys(headers).find(k => {
23
- if (k.toLowerCase() === name.toLowerCase()) {
24
- return k
25
- }
26
- })
22
+ return k.toLowerCase() === name.toLowerCase();
23
+ });
27
24
  },
28
25
 
29
26
  /**
@@ -34,7 +31,7 @@ module.exports = {
34
31
  * @return {(integer|boolean)}
35
32
  */
36
33
  hasHeader: (headers, name) => {
37
- return Boolean(Object.keys(headers).find(k => k.toLowerCase() === name.toLowerCase()))
34
+ return Boolean(Object.keys(headers).find(k => k.toLowerCase() === name.toLowerCase()));
38
35
  },
39
36
 
40
37
  /**
@@ -43,15 +40,9 @@ module.exports = {
43
40
  * @param {string}} mimeType
44
41
  * @returns {boolean}
45
42
  */
46
- isMimeTypeJson: (mimeType) => {
47
- return [
48
- 'application/json',
49
- 'application/x-json',
50
- 'text/json',
51
- 'text/x-json',
52
- '+json'
53
- ].some(function (type) {
54
- return mimeType.indexOf(type) > -1
55
- })
56
- }
57
- }
43
+ isMimeTypeJson: mimeType => {
44
+ return ['application/json', 'application/x-json', 'text/json', 'text/x-json', '+json'].some(function (type) {
45
+ return mimeType.indexOf(type) > -1;
46
+ });
47
+ },
48
+ };
@@ -1,24 +1,20 @@
1
- 'use strict'
2
-
1
+ /* eslint-disable no-param-reassign */
3
2
  module.exports = function (obj, pair) {
4
3
  if (obj[pair.name] === undefined) {
5
- obj[pair.name] = pair.value
6
- return obj
4
+ obj[pair.name] = pair.value;
5
+ return obj;
7
6
  }
8
7
 
9
8
  // If we already have it as array just push the value
10
- if (obj[pair.name] instanceof Array) {
11
- obj[pair.name].push(pair.value)
12
- return obj
9
+ if (Array.isArray(obj[pair.name])) {
10
+ obj[pair.name].push(pair.value);
11
+ return obj;
13
12
  }
14
13
 
15
14
  // convert to array
16
- const arr = [
17
- obj[pair.name],
18
- pair.value
19
- ]
15
+ const arr = [obj[pair.name], pair.value];
20
16
 
21
- obj[pair.name] = arr
17
+ obj[pair.name] = arr;
22
18
 
23
- return obj
24
- }
19
+ return obj;
20
+ };