Skip to content

Commit fa9ef51

Browse files
committed
Merge branch 'master' into refactor/objc/nsurlsession
Conflicts: src/targets/objc/native.js
2 parents 834a919 + 4998fe3 commit fa9ef51

24 files changed

Lines changed: 679 additions & 28 deletions

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,13 @@ Currently the following output [targets](/src/targets) are supported:
4747
- [Requests](http://docs.python-requests.org/en/latest/api/#requests.request)
4848
- Objective-C
4949
- [NSURLSession](https://developer.apple.com/library/mac/documentation/Foundation/Reference/NSURLSession_class/index.html)
50+
- Swift
51+
- [NSURLSession](https://developer.apple.com/library/mac/documentation/Foundation/Reference/NSURLSession_class/index.html)
5052
- Go
5153
- [Native](http://golang.org/pkg/net/http/#NewRequest)
5254
- OCaml
5355
- [CoHTTP](https://github.com/mirage/ocaml-cohttp)
56+
- [Go](http://golang.org/pkg/net/http/#NewRequest)
5457

5558
## Installation
5659

src/targets/objc/helpers.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ module.exports = {
1414
},
1515

1616
/**
17-
* Create a string corresponding to a valid declaration and initialization of an Objective-C object litteral.
17+
* Create a string corresponding to a valid declaration and initialization of an Objective-C object literal.
1818
*
1919
* @param {string} nsClass Class of the litteral
2020
* @param {string} name Desired name of the instance

src/targets/python/requests.js

Lines changed: 42 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/**
22
* @description
3-
* HTTP code snippet generator for Requests
3+
* HTTP code snippet generator for Python using Requests
44
*
55
* @author
66
* @montanaflynn
@@ -11,32 +11,31 @@
1111
'use strict'
1212

1313
var util = require('util')
14+
var CodeBuilder = require('../../helpers/code-builder')
1415

1516
module.exports = function (source, options) {
1617
// Start snippet
17-
var code = []
18+
var code = new CodeBuilder(' ')
1819

1920
// Import requests
20-
code.push('import requests\n')
21+
code.push('import requests')
22+
.blank()
2123

2224
// Set URL
23-
code.push(util.format('url = "%s"\n', source.url))
25+
code.push(util.format('url = "%s"', source.url))
26+
.blank()
2427

2528
// Construct query string
2629
if (source.queryString.length) {
27-
var qs = 'querystring = {'
28-
for (var i = 0; i < source.queryString.length; i++) {
29-
for (var key in source.queryString[i]) {
30-
qs += "'" + key + "':" + "'" + source.queryString[i][key] + "',"
31-
}
32-
}
33-
qs = qs.substring(0, qs.length - 1)
34-
qs += '}\n'
30+
var qs = 'querystring = ' + JSON.stringify(source.queryObj)
31+
3532
code.push(qs)
33+
.blank()
3634
}
3735

3836
// Construct payload
3937
var payload = JSON.stringify(source.postData.text)
38+
4039
if (payload) {
4140
code.push(util.format('payload = %s', payload))
4241
}
@@ -45,39 +44,57 @@ module.exports = function (source, options) {
4544
var header
4645
var headers = source.allHeaders
4746
var headerCount = Object.keys(headers).length
47+
4848
if (headerCount === 1) {
4949
for (header in headers) {
50-
code.push(util.format('headers = {\'%s\': \'%s\'}\n', header, headers[header]))
50+
code.push(util.format('headers = {\'%s\': \'%s\'}', header, headers[header]))
51+
.blank()
5152
}
5253
} else if (headerCount > 1) {
5354
var headerLine
5455
var count = 1
56+
5557
code.push('headers = {')
58+
5659
for (header in headers) {
5760
if (count++ !== headerCount) {
58-
headerLine = util.format(' \'%s\': "%s",', header, headers[header])
61+
headerLine = util.format('\'%s\': "%s",', header, headers[header])
5962
} else {
60-
headerLine = util.format(' \'%s\': "%s"', header, headers[header])
63+
headerLine = util.format('\'%s\': "%s"', header, headers[header])
6164
}
62-
code.push(headerLine)
65+
66+
code.push(1, headerLine)
6367
}
64-
code.push(' }\n')
68+
69+
code.push(1, '}')
70+
.blank()
6571
}
6672

6773
// Construct request
6874
var method = source.method
6975
var request = util.format('response = requests.request("%s", url', method)
70-
if (payload) request += ', data=payload'
71-
if (headerCount > 0) request += ', headers=headers'
72-
if (qs) request += ', params=querystring'
73-
request += ')\n'
76+
77+
if (payload) {
78+
request += ', data=payload'
79+
}
80+
81+
if (headerCount > 0) {
82+
request += ', headers=headers'
83+
}
84+
85+
if (qs) {
86+
request += ', params=querystring'
87+
}
88+
89+
request += ')'
90+
7491
code.push(request)
92+
.blank()
7593

76-
// Print response
77-
code.push('print(response.text)')
94+
// Print response
95+
.push('print(response.text)')
7896

79-
console.log(code.join('\n'))
80-
return code.join('\n')
97+
return code.join()
8198
}
8299

83100
module.exports.info = {

src/targets/swift/helpers.js

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
'use strict'
2+
3+
var util = require('util')
4+
5+
/**
6+
* Create an string of given length filled with blank spaces
7+
*
8+
* @param {number} length Length of the array to return
9+
* @return {string}
10+
*/
11+
function buildString (length, str) {
12+
return Array.apply(null, new Array(length)).map(String.prototype.valueOf, str).join('')
13+
}
14+
15+
/**
16+
* Create a string corresponding to a Dictionary or Array literal representation with pretty option
17+
* and indentation.
18+
*/
19+
function concatArray (arr, pretty, indentation, indentLevel) {
20+
var currentIndent = buildString(indentLevel, indentation)
21+
var closingBraceIndent = buildString(indentLevel - 1, indentation)
22+
var join = pretty ? ',\n' + currentIndent : ', '
23+
24+
if (pretty) {
25+
return '[\n' + currentIndent + arr.join(join) + '\n' + closingBraceIndent + ']'
26+
} else {
27+
return '[' + arr.join(join) + ']'
28+
}
29+
}
30+
31+
module.exports = {
32+
/**
33+
* Create a string corresponding to a valid declaration and initialization of a Swift array or dictionary literal
34+
*
35+
* @param {string} name Desired name of the instance
36+
* @param {Object} parameters Key-value object of parameters to translate to a Swift object litearal
37+
* @param {Object} opts Target options
38+
* @return {string}
39+
*/
40+
literalDeclaration: function (name, parameters, opts) {
41+
return util.format('let %s = %s', name, this.literalRepresentation(parameters, opts))
42+
},
43+
44+
/**
45+
* Create a valid Swift string of a literal value according to its type.
46+
*
47+
* @param {*} value Any JavaScript literal
48+
* @param {Object} opts Target options
49+
* @return {string}
50+
*/
51+
literalRepresentation: function (value, opts, indentLevel) {
52+
indentLevel = indentLevel === undefined ? 1 : indentLevel + 1
53+
54+
switch (Object.prototype.toString.call(value)) {
55+
case '[object Number]':
56+
return value
57+
case '[object Array]':
58+
// Don't prettify arrays nto not take too much space
59+
var pretty = false
60+
var valuesRepresentation = value.map(function (v) {
61+
// Switch to prettify if the value is a dictionary with multiple keys
62+
if (Object.prototype.toString.call(v) === '[object Object]') {
63+
pretty = Object.keys(v).length > 1
64+
}
65+
return this.literalRepresentation(v, opts, indentLevel)
66+
}.bind(this))
67+
return concatArray(valuesRepresentation, pretty, opts.indent, indentLevel)
68+
case '[object Object]':
69+
var keyValuePairs = []
70+
for (var k in value) {
71+
keyValuePairs.push(util.format('"%s": %s', k, this.literalRepresentation(value[k], opts, indentLevel)))
72+
}
73+
return concatArray(keyValuePairs, opts.pretty && keyValuePairs.length > 1, opts.indent, indentLevel)
74+
default:
75+
return '"' + value.replace(/"/g, '\\"') + '"'
76+
}
77+
}
78+
}

src/targets/swift/index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
'use strict'
2+
3+
module.exports = require('require-directory')(module)

src/targets/swift/info.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
'use strict'
2+
3+
module.exports = {
4+
key: 'swift',
5+
title: 'Swift',
6+
extname: '.swift',
7+
default: 'nsurlsession'
8+
}

src/targets/swift/nsurlsession.js

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
/**
2+
* @description
3+
* HTTP code snippet generator for Swift using NSURLSession.
4+
*
5+
* @author
6+
* @thibaultCha
7+
*
8+
* for any questions or issues regarding the generated code snippet, please open an issue mentioning the author.
9+
*/
10+
11+
'use strict'
12+
13+
var util = require('util')
14+
var helpers = require('./helpers')
15+
var CodeBuilder = require('../../helpers/code-builder')
16+
17+
module.exports = function (source, options) {
18+
var opts = util._extend({
19+
timeout: '10',
20+
indent: ' ',
21+
pretty: true
22+
}, options)
23+
24+
var code = new CodeBuilder(opts.indent)
25+
26+
// Markers for headers to be created as litteral objects and later be set on the NSURLRequest if exist
27+
var req = {
28+
hasHeaders: false,
29+
hasBody: false
30+
}
31+
32+
// We just want to make sure people understand that is the only dependency
33+
code.push('import Foundation')
34+
35+
if (Object.keys(source.allHeaders).length) {
36+
req.hasHeaders = true
37+
code.blank()
38+
.push(helpers.literalDeclaration('headers', source.allHeaders, opts))
39+
}
40+
41+
if (source.postData.text || source.postData.jsonObj || source.postData.params) {
42+
req.hasBody = true
43+
44+
switch (source.postData.mimeType) {
45+
case 'application/x-www-form-urlencoded':
46+
// By appending parameters one by one in the resulting snippet,
47+
// we make it easier for the user to edit it according to his or her needs after pasting.
48+
// The user can just add/remove lines adding/removing body parameters.
49+
code.blank()
50+
.push(util.format('var postData = NSMutableData(data: "%s=%s".dataUsingEncoding(NSUTF8StringEncoding)!)', source.postData.params[0].name, source.postData.params[0].value))
51+
for (var i = 1, len = source.postData.params.length; i < len; i++) {
52+
code.push(util.format('postData.appendData("&%s=%s".dataUsingEncoding(NSUTF8StringEncoding)!)', source.postData.params[i].name, source.postData.params[i].value))
53+
}
54+
break
55+
56+
case 'application/json':
57+
if (source.postData.jsonObj) {
58+
code.push(helpers.literalDeclaration('parameters', source.postData.jsonObj, opts))
59+
.blank()
60+
.push('let postData = NSJSONSerialization.dataWithJSONObject(parameters, options: nil, error: nil)')
61+
}
62+
break
63+
64+
case 'multipart/form-data':
65+
/**
66+
* By appending multipart parameters one by one in the resulting snippet,
67+
* we make it easier for the user to edit it according to his or her needs after pasting.
68+
* The user can just edit the parameters NSDictionary or put this part of a snippet in a multipart builder method.
69+
*/
70+
code.push(helpers.literalDeclaration('parameters', source.postData.params, opts))
71+
.blank()
72+
.push(util.format('let boundary = "%s"', source.postData.boundary))
73+
.blank()
74+
.push('var body = ""')
75+
.push('var error: NSError? = nil')
76+
.push('for param in parameters {')
77+
.push(1, 'let paramName = param["name"]!')
78+
.push(1, 'body += "--\\(boundary)\\r\\n"')
79+
.push(1, 'body += "Content-Disposition:form-data; name=\\"\\(paramName)\\""')
80+
.push(1, 'if let filename = param["fileName"] {')
81+
.push(2, 'let contentType = param["content-type"]!')
82+
.push(2, 'let fileContent = String(contentsOfFile: filename, encoding: NSUTF8StringEncoding, error: &error)')
83+
.push(2, 'if (error != nil) {')
84+
.push(3, 'println(error)')
85+
.push(2, '}')
86+
.push(2, 'body += "; filename=\\"\\(filename)\\"\\r\\n"')
87+
.push(2, 'body += "Content-Type: \\(contentType)\\r\\n\\r\\n"')
88+
.push(2, 'body += fileContent!')
89+
.push(1, '} else if let paramValue = param["value"] {')
90+
.push(2, 'body += "\\r\\n\\r\\n\\(paramValue)"')
91+
.push(1, '}')
92+
.push('}')
93+
break
94+
95+
default:
96+
code.blank()
97+
.push(util.format('let postData = NSData(data: "%s".dataUsingEncoding(NSUTF8StringEncoding)!)', source.postData.text))
98+
}
99+
}
100+
101+
code.blank()
102+
// NSURLRequestUseProtocolCachePolicy is the default policy, let's just always set it to avoid confusion.
103+
.push(util.format('var request = NSMutableURLRequest(URL: NSURL(string: "%s")!,', source.fullUrl))
104+
.push(' cachePolicy: .UseProtocolCachePolicy,')
105+
.push(util.format(' timeoutInterval: %s)', parseInt(opts.timeout, 10).toFixed(1)))
106+
.push(util.format('request.HTTPMethod = "%s"', source.method))
107+
108+
if (req.hasHeaders) {
109+
code.push('request.allHTTPHeaderFields = headers')
110+
}
111+
112+
if (req.hasBody) {
113+
code.push('request.HTTPBody = postData')
114+
}
115+
116+
code.blank()
117+
// Retrieving the shared session will be less verbose than creating a new one.
118+
.push('let session = NSURLSession.sharedSession()')
119+
.push('let dataTask = session.dataTaskWithRequest(request, completionHandler: { (data, response, error) -> Void in')
120+
.push(1, 'if (error != nil) {')
121+
.push(2, 'println(error)')
122+
.push(1, '} else {')
123+
// Casting the NSURLResponse to NSHTTPURLResponse so the user can see the status .
124+
.push(2, 'let httpResponse = response as? NSHTTPURLResponse')
125+
.push(2, 'println(httpResponse)')
126+
.push(1, '}')
127+
.push('})')
128+
.blank()
129+
.push('dataTask.resume()')
130+
131+
return code.join()
132+
}
133+
134+
module.exports.info = {
135+
key: 'nsurlsession',
136+
title: 'NSURLSession',
137+
link: 'https://developer.apple.com/library/mac/documentation/Foundation/Reference/NSURLSession_class/index.html',
138+
description: 'Foundation\'s NSURLSession request'
139+
}

test/fixtures/available-targets.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,20 @@
145145
}
146146
]
147147
},
148+
{
149+
"key": "swift",
150+
"title": "Swift",
151+
"extname": ".swift",
152+
"default": "nsurlsession",
153+
"clients": [
154+
{
155+
"key": "nsurlsession",
156+
"title": "NSURLSession",
157+
"link": "https://developer.apple.com/library/mac/documentation/Foundation/Reference/NSURLSession_class/index.html",
158+
"description": "Foundation's NSURLSession request"
159+
}
160+
]
161+
},
148162
{
149163
"key": "go",
150164
"title": "Go",

0 commit comments

Comments
 (0)