Skip to content
Permalink
Browse files

Merge pull request #121 from postmanlabs/feature/php-httprequest

Added PHP-HttpRequest2 codegen
  • Loading branch information
umeshp7 committed Nov 22, 2019
2 parents e133d88 + dd77f6a commit cc6b9b4434e1b143f9217628aedc1aac0f3841bf
@@ -33,6 +33,7 @@ List of supported code generators:
| OCaml | Cohttp |
|PHP | cURL |
|PHP | pecl_http |
|PHP | HTTP_Request2 |
| PowerShell | RestMethod |
| Ruby | Net:HTTP |
| Shell | Httpie |
@@ -0,0 +1,43 @@
.DS_Store
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Coverage directory used by tools like istanbul
.coverage

# node-waf configuration
.lock-wscript


# Dependency directories
node_modules/
jspm_packages/

# Typescript v1 declaration files
typings/

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variables file
.env

out/

codesnippet.php
@@ -0,0 +1,76 @@
### NPM Specific: Disregard recursive project files
### ===============================================
/.editorconfig
/.gitmodules
/test

### Borrowed from .gitignore
### ========================

# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Prevent IDE stuff
.idea
.vscode
*.sublime-*

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
.coverage

# nyc test coverage
.nyc_output

# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# Typescript v1 declaration files
typings/

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variables file
.env

snippet.swift

out/
@@ -0,0 +1,42 @@

> Converts Postman-SDK Request into code snippet for .
#### Prerequisites
To run Code-Gen, ensure that you have NodeJS >= v8. A copy of the NodeJS installable can be downloaded from https://nodejs.org/en/download/package-manager.

## Using the Module
The module will expose an object which will have property `convert` which is the function for converting the Postman-SDK request to swift code snippet.

### convert function
Convert function takes three parameters

* `request` - Postman-SDK Request Object

* `options` - options is an object which hsa following properties
* `indentType` - String denoting type of indentation for code snippet. eg: 'Space', 'Tab'
* `indentCount` - The number of indentation characters to add per code level
* `trimRequestBody` - Whether or not request body fields should be trimmed

* `callback` - callback function with first parameter as error and second parameter as string for code snippet

##### Example:
```js
var request = new sdk.Request('www.google.com'), //using postman sdk to create request
options = {
indentCount: 3,
indentType: 'Space',
requestTimeout: 200,
trimRequestBody: true
};
convert(request, options, function(error, snippet) {
if (error) {
// handle error
}
// handle snippet
});
```
### Guidelines for using generated snippet

* Since Postman-SDK Request object doesn't provide complete path of the file, it needs to be manually inserted in case of uploading a file.

* This module doesn't support cookies.
@@ -0,0 +1 @@
module.exports = require('./lib');
@@ -0,0 +1,193 @@
var _ = require('./lodash'),
parseBody = require('./util/parseBody'),
sanitize = require('./util/sanitize').sanitize,
sanitizeOptions = require('./util/sanitize').sanitizeOptions,
addFormParam = require('./util/sanitize').addFormParam,
self;
const ALLOWED_METOHDS = [ 'OPTIONS', 'GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'TRACE', 'CONNECT'];

/**
* Used to get the headers and put them in the desired form of the language
*
* @param {Object} request - postman SDK-request object
* @param {String} indentation - used for indenting snippet's structure
* @returns {String} - request headers in the desired format
*/
function getHeaders (request, indentation) {
var headerArray = request.toJSON().header,
headerMap;

if (!_.isEmpty(headerArray)) {
headerArray = _.reject(headerArray, 'disabled');
headerMap = _.map(headerArray, function (header) {
return `${indentation}'${sanitize(header.key)}' => ` +
`'${sanitize(header.value)}'`;
});
return `$request->setHeader(array(\n${headerMap.join(',\n')}\n));\n`;
}
return '';
}
self = module.exports = {
/**
* @returns {Array} plugin specific options
*/
getOptions: function () {
return [
{
name: 'Set indentation count',
id: 'indentCount',
type: 'positiveInteger',
default: 2,
description: 'Set the number of indentation characters to add per code level'
},
{
name: 'Set indentation type',
id: 'indentType',
type: 'enum',
default: 'Space',
availableOptions: ['Tab', 'Space'],
description: 'Select the character used to indent lines of code'
},
{
name: 'Set request timeout',
id: 'requestTimeout',
type: 'positiveInteger',
default: 0,
description: 'Set number of milliseconds the request should wait for a response' +
' before timing out (use 0 for infinity)'
},
{
name: 'Trim request body fields',
id: 'trimRequestBody',
type: 'boolean',
default: false,
description: 'Remove white space and additional lines that may affect the server\'s response'
},
{
name: 'Follow redirects',
id: 'followRedirect',
type: 'boolean',
default: true,
description: 'Automatically follow HTTP redirects'
}
];
},
convert: function (request, options, callback) {
if (_.isFunction(options)) {
callback = options;
options = {};
}
if (!_.isFunction(callback)) {
throw new Error('PHP-HttpRequest2-Converter: callback is not valid function');
}
options = sanitizeOptions(options, self.getOptions());

var snippet, indentString;
indentString = options.indentType === 'Tab' ? '\t' : ' ';
indentString = indentString.repeat(options.indentCount);

snippet = '<?php\n';
snippet += 'require_once \'HTTP/Request2.php\';\n';
snippet += '$request = new HTTP_Request2();\n';
snippet += `$request->setUrl('${sanitize(request.url.toString())}');\n`;
snippet += '$request->setMethod(';
if (ALLOWED_METOHDS.includes(request.method)) {
snippet += `HTTP_Request2::METHOD_${request.method});\n`;
}
else {
snippet += `'${request.method}');\n`;
}

if (options.requestTimeout !== 0 || options.followRedirect) {
let configArray = [];

// PHP-HTTP_Request2 method accepts timeout in seconds and it must be an integer
if (options.requestTimeout !== 0 && Number.isInteger(options.requestTimeout / 1000)) {
let requestTimeout = options.requestTimeout;
requestTimeout /= 1000;
configArray.push(`${indentString}'timeout' => ${requestTimeout}`);
}
if (options.followRedirect) {
configArray.push(`${indentString}'follow_redirects' => TRUE`);
}
if (configArray.length) {
snippet += '$request->setConfig(array(\n';
snippet += configArray.join(',\n') + '\n';
}
snippet += '));\n';
}
if (request.body && !request.headers.has('Content-Type')) {
if (request.body.mode === 'file') {
request.addHeader({
key: 'Content-Type',
value: 'text/plain'
});
}
else if (request.body.mode === 'graphql') {
request.addHeader({
key: 'Content-Type',
value: 'application/json'
});
}
}
// add the headers to snippet
snippet += getHeaders(request, indentString);

// The following code handles multiple files in the same formdata param.
// It removes the form data params where the src property is an array of filepath strings
// Splits that array into different form data params with src set as a single filepath string
if (request.body && request.body.mode === 'formdata') {
let formdata = request.body.formdata,
formdataArray = [];
formdata.members.forEach((param) => {
let key = param.key,
type = param.type,
disabled = param.disabled,
contentType = param.contentType;
// check if type is file or text
if (type === 'file') {
// if src is not of type string we check for array(multiple files)
if (typeof param.src !== 'string') {
// if src is an array(not empty), iterate over it and add files as separate form fields
if (Array.isArray(param.src) && param.src.length) {
param.src.forEach((filePath) => {
addFormParam(formdataArray, key, param.type, filePath, disabled, contentType);
});
}
// if src is not an array or string, or is an empty array, add a placeholder for file path(no files case)
else {
addFormParam(formdataArray, key, param.type, '/path/to/file', disabled, contentType);
}
}
// if src is string, directly add the param with src as filepath
else {
addFormParam(formdataArray, key, param.type, param.src, disabled, contentType);
}
}
// if type is text, directly add it to formdata array
else {
addFormParam(formdataArray, key, param.type, param.value, disabled, contentType);
}
});
request.body.update({
mode: 'formdata',
formdata: formdataArray
});
}
// add the body to snippet
if (!_.isEmpty(request.body)) {
snippet += `${parseBody(request.toJSON(), indentString, options.trimRequestBody)}`;
}
snippet += 'try {\n';
snippet += `${indentString}$response = $request->send();\n`;
snippet += `${indentString}if ($response->getStatus() == 200) {\n`;
snippet += `${indentString.repeat(2)}echo $response->getBody();\n`;
snippet += `${indentString}}\n${indentString}else {\n`;
snippet += `${indentString.repeat(2)}echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .\n`;
snippet += `${indentString.repeat(2)}$response->getReasonPhrase();\n`;
snippet += `${indentString}}\n`;
snippet += '}\ncatch(HTTP_Request2_Exception $e) {\n';
snippet += `${indentString}echo 'Error: ' . $e->getMessage();\n}`;
return callback(null, snippet);
}
};

0 comments on commit cc6b9b4

Please sign in to comment.
You can’t perform that action at this time.