Skip to content

Commit 2293771

Browse files
author
Dhwaneet Bhatt
committed
Rust reqwest code gen
1 parent 3c0f1ee commit 2293771

File tree

20 files changed

+1103
-5
lines changed

20 files changed

+1103
-5
lines changed

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,11 @@ typings/
6464
# next.js build output
6565
.next
6666

67-
out/
67+
# Cargo
68+
target/
6869

70+
# Newman test generated files
71+
out/
6972
newmanResponses.json
7073
dummyFile*.txt
7174
dummyBinaryFile

README.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,16 @@ List of supported code generators:
3636
| NodeJs | Unirest |
3737
| Objective-C| NSURLSession|
3838
| OCaml | Cohttp |
39-
|PHP | cURL |
40-
|PHP | Guzzle |
41-
|PHP | pecl_http |
42-
|PHP | HTTP_Request2 |
39+
| PHP | cURL |
40+
| PHP | Guzzle |
41+
| PHP | pecl_http |
42+
| PHP | HTTP_Request2 |
4343
| PowerShell | RestMethod |
4444
| Python | http.client |
4545
| Python | Requests |
4646
| R | httr |
4747
| R | RCurl |
48+
| Rust | Reqwest |
4849
| Ruby | Net:HTTP |
4950
| Shell | Httpie |
5051
| Shell | wget |

codegens/rust-reqwest/.gitignore

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
.DS_Store
2+
# Logs
3+
logs
4+
*.log
5+
npm-debug.log*
6+
yarn-debug.log*
7+
yarn-error.log*
8+
9+
# Runtime data
10+
pids
11+
*.pid
12+
*.seed
13+
*.pid.lock
14+
15+
# Prevent IDE stuff
16+
.idea
17+
.vscode
18+
*.sublime-*
19+
20+
# Directory for instrumented libs generated by jscoverage/JSCover
21+
lib-cov
22+
23+
# Coverage directory used by tools like istanbul
24+
.coverage
25+
26+
# nyc test coverage
27+
.nyc_output
28+
29+
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
30+
.grunt
31+
32+
# Bower dependency directory (https://bower.io/)
33+
bower_components
34+
35+
# node-waf configuration
36+
.lock-wscript
37+
38+
# Compiled binary addons (http://nodejs.org/api/addons.html)
39+
build/Release
40+
41+
# Dependency directories
42+
node_modules/
43+
jspm_packages/
44+
45+
# Typescript v1 declaration files
46+
typings/
47+
48+
# Optional npm cache directory
49+
.npm
50+
51+
# Optional eslint cache
52+
.eslintcache
53+
54+
# Optional REPL history
55+
.node_repl_history
56+
57+
# Output of 'npm pack'
58+
*.tgz
59+
60+
# Yarn Integrity file
61+
.yarn-integrity
62+
63+
# dotenv environment variables file
64+
.env
65+
66+
out/
67+
68+
# Cargo
69+
target/
70+
src/
71+
Cargo.toml
72+
Cargo.lock

codegens/rust-reqwest/README.md

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# Code-Gen: Postman SDK Request -> Rust Snippet Converter
2+
3+
This module is used to convert Postman SDK-Request object into a Rust code snippet.
4+
5+
#### Prerequisites
6+
To run this repository, ensure that you have NodeJS >= v12.
7+
8+
## Using the Module
9+
This module exposes two function `convert()` and `getOptions()`
10+
11+
### Convert
12+
13+
Convert function sanitizes the inputs, overrides options with the default ones if not provided and return the code snippet in the desired format.
14+
15+
It requires 3 mandatory parameters `request`, `callback` and `options`
16+
17+
* `request` - postman SDK-request object
18+
19+
* `options` is an object with the following properties
20+
21+
* `indentType` : can be `Tab` or `Space` (default: 'Space')
22+
* `indentCount` : Integer denoting the number of tabs/spaces required for indentation, range 0-8 (default : for indentType Tab : 2, for indentType Space : 4)
23+
* `trimRequestBody` : Trim request body fields (default: false)
24+
These plugin options will be used if no options are passed to the convert function.
25+
26+
* `callback` : callback function with `error` and `snippet` parameters where snippet is the desired output
27+
28+
#### Example
29+
```javascript
30+
const sdk = require('postman-collection');
31+
32+
const request = sdk.Request('http://www.google.com'),
33+
options = {indentType: 'Tab', indentCount: 4, trimRequestBody: true};
34+
35+
convert(request, options, function (err, snippet) {
36+
if (err) {
37+
// perform desired action of logging the error
38+
}
39+
// perform action with the snippet
40+
});
41+
```
42+
43+
### getOptions function
44+
45+
This function returns a list of options supported by this codegen.
46+
47+
#### Example
48+
```js
49+
const options = getOptions();
50+
51+
console.log(options);
52+
// output
53+
// [
54+
// {
55+
// name: 'Set indentation count',
56+
// id: 'indentCount',
57+
// type: 'positiveInteger',
58+
// default: 2,
59+
// description: 'Set the number of indentation characters to add per code level'
60+
// },
61+
// ...
62+
// ]
63+
```
64+
65+
### Notes
66+
67+
* This module supports all request types of requests which are present in the Postman App.
68+
69+
* Does not handle cookies or proxies and generates a snippet for the base request.
70+
71+
* Snippet generated is supported for Rust 1.0+ versions.
72+
73+
* Does not support if the request body is passed by means of a binary file.
74+
75+
* User ◊needs to enter the absolute path of the file in the snippet. This just picks the relative path in case of file upload in form data body.
76+
77+
### Resources
78+
79+
* [Rust](https://www.rust-lang.org/) official documentation

codegens/rust-reqwest/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = require('./lib');

codegens/rust-reqwest/lib/index.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
module.exports = {
2+
convert: require('./reqwest').convert,
3+
getOptions: require('./reqwest').getOptions
4+
};
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
const _ = require('lodash'),
2+
sanitizeOptions = require('./util/sanitize').sanitizeOptions,
3+
{ parseHeader, parseBody } = require('./util/parseRequest'),
4+
{ addDefaultContentType, formatFormData } = require('./util/formatRequest');
5+
6+
/**
7+
* Returns snippet for Rust reqwest by parsing data from Postman-SDK request object
8+
*
9+
* @param {Object} request - Postman SDK request object
10+
* @param {String} indentation - indentation required for code snippet
11+
* @param {Object} options - Options for code generation
12+
*
13+
* @returns {String} - Rust reqwest code snippet for given request object
14+
*/
15+
function makeSnippet (request, indentation, options) {
16+
// Build the client - set timeout and redirect policy
17+
let snippet = '#[tokio::main]\n';
18+
snippet += 'async fn main() -> Result<(), Box<dyn std::error::Error>> {\n';
19+
snippet += `${indentation}let client = reqwest::Client::builder()\n`;
20+
21+
// Disable redirects if option is set
22+
if (_.get(request, 'protocolProfileBehavior.followRedirects', options.followRedirect) === false) {
23+
snippet += `${indentation.repeat(2)}.redirect(reqwest::redirect::Policy::none())\n`;
24+
}
25+
26+
snippet += `${indentation.repeat(2)}.build()?;\n\n`;
27+
28+
addDefaultContentType(request);
29+
request.body && request.body.mode === 'formdata' && formatFormData(request);
30+
31+
const body = request.body && request.body.toJSON(),
32+
contentType = request.headers.get('Content-Type'),
33+
{ headerSnippet, requestHeaderSnippet } = parseHeader(request, indentation),
34+
{ bodySnippet, requestBodySnippet } = parseBody(body, options.trimRequestBody, indentation, contentType);
35+
36+
snippet += headerSnippet;
37+
snippet += bodySnippet;
38+
39+
// Create the request and add headers and body
40+
let requestSnippet = `${indentation}let method = "${request.method}";\n`;
41+
requestSnippet += `${indentation}let request = client.request(reqwest::Method::from_bytes(method.as_bytes())?, `;
42+
requestSnippet += `"${request.url.toString()}")\n`;
43+
requestSnippet += requestHeaderSnippet;
44+
requestSnippet += requestBodySnippet;
45+
46+
// Set request timeout
47+
if (options.requestTimeout !== 0) {
48+
requestSnippet += `${indentation.repeat(2)}.timeout(std::time::Duration::from_millis(${options.requestTimeout}))\n`;
49+
}
50+
51+
requestSnippet = requestSnippet.slice(0, -1) + ';\n\n';
52+
53+
snippet += requestSnippet;
54+
snippet += `${indentation}let response = request.send().await?;\n`;
55+
snippet += `${indentation}let body = response.text().await?;\n\n`;
56+
57+
snippet += `${indentation}println!("{}", body);\n\n`;
58+
snippet += `${indentation}Ok(())\n}`;
59+
60+
return snippet;
61+
}
62+
63+
const self = module.exports = {
64+
/**
65+
* Used to return options which are specific to a particular plugin
66+
*
67+
* @returns {Array}
68+
*/
69+
getOptions: function () {
70+
return [
71+
{
72+
name: 'Set indentation count',
73+
id: 'indentCount',
74+
type: 'positiveInteger',
75+
default: 4,
76+
description: 'Set the number of indentation characters to add per code level'
77+
},
78+
{
79+
name: 'Set indentation type',
80+
id: 'indentType',
81+
type: 'enum',
82+
availableOptions: ['Tab', 'Space'],
83+
default: 'Space',
84+
description: 'Select the character used to indent lines of code'
85+
},
86+
{
87+
name: 'Set request timeout',
88+
id: 'requestTimeout',
89+
type: 'positiveInteger',
90+
default: 0,
91+
description: 'Set number of milliseconds the request should wait for a response' +
92+
' before timing out (use 0 for infinity)'
93+
},
94+
{
95+
name: 'Follow redirects',
96+
id: 'followRedirect',
97+
type: 'boolean',
98+
default: true,
99+
description: 'Automatically follow HTTP redirects'
100+
},
101+
{
102+
name: 'Trim request body fields',
103+
id: 'trimRequestBody',
104+
type: 'boolean',
105+
default: false,
106+
description: 'Remove white space and additional lines that may affect the server\'s response'
107+
}];
108+
},
109+
110+
/**
111+
* Used to convert the postman sdk-request object to rust snippet
112+
*
113+
* @param {Object} request - postman SDK-request object
114+
* @param {Object} options
115+
* @param {String} options.indentType - type of indentation eg: Space / Tab (default: Space)
116+
* @param {Number} options.indentCount - frequency of indent (default: 4 for indentType: Space,
117+
default: 1 for indentType: Tab)
118+
* @param {Number} options.requestTimeout : time in milli-seconds after which request will bail out
119+
(default: 0 -> never bail out)
120+
* @param {Boolean} options.trimRequestBody : whether to trim request body fields (default: false)
121+
* @param {Boolean} options.followRedirect : whether to allow redirects of a request
122+
* @param {Function} callback - function with parameters (error, snippet)
123+
*/
124+
convert: function (request, options, callback) {
125+
if (!_.isFunction(callback)) {
126+
throw new Error('Rust~reqwest-convert: Callback is not a function');
127+
}
128+
options = sanitizeOptions(options, self.getOptions());
129+
130+
// String representing value of indentation required
131+
let indentString;
132+
133+
indentString = options.indentType === 'Tab' ? '\t' : ' ';
134+
indentString = indentString.repeat(options.indentCount);
135+
136+
return callback(null, makeSnippet(request, indentString, options));
137+
}
138+
};

0 commit comments

Comments
 (0)