Python generator: Properly quote/escape all data

This commit is contained in:
Elias Kunnas
2017-03-03 16:25:12 +02:00
parent e8074c85c7
commit bf8a4dc5f7
14 changed files with 157 additions and 154 deletions

View File

@@ -4,9 +4,9 @@ headers = {
'Authorization': 'Bearer ACCESS_TOKEN',
}
files = {
'attributes': '{"name":"tigers.jpeg", "parent":{"id":"11446498"}}',
'file': open('myfile.jpg', 'rb')
}
files = [
('attributes', '{"name":"tigers.jpeg", "parent":{"id":"11446498"}}'),
('file', open('myfile.jpg', 'rb')),
]
requests.post('https://upload.box.com/api/2.0/files/content', headers=headers, files=files)

View File

@@ -1,7 +1,7 @@
import requests
data = {
'grant_type': 'client_credentials'
}
data = [
('grant_type', 'client_credentials'),
]
requests.post('http://localhost/api/oauth/token/', data=data, auth=('foo', 'bar'))

View File

@@ -44,7 +44,7 @@ params = (
('AC', '1'),
)
data = '{"__type":"CreateItemJsonRequest:#Exchange","Header":{"__type":"JsonRequestHeaders:#Exchange","RequestServerVersion":"Exchange2013","TimeZoneContext":{"__type":"TimeZoneContext:#Exchange","TimeZoneDefinition":{"__type":"TimeZoneDefinitionType:#Exchange","Id":"France Standard Time"}}},"Body":{"__type":"CreateItemRequest:#Exchange","Items":[{"__type":"Message:#Exchange","Subject":"API","Body":{"__type":"BodyContentType:#Exchange","BodyType":"HTML","Value":"<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"><style type=\"text/css\" style=\"display:none\"><!-- p { margin-top: 0px; margin-bottom: 0px; }--></style></head><body dir=\"ltr\" style=\"font-size:12pt;color:#000000;background-color:#FFFFFF;font-family:Calibri,Arial,Helvetica,sans-serif;\"><p>API Test for NickC<br></p></body></html>"},"Importance":"Normal","From":null,"ToRecipients":[{"Name":"George LUCAS","EmailAddress":"George.LUCAS@nih.mail.edu.fr","RoutingType":"SMTP","MailboxType":"Mailbox","OriginalDisplayName":"George.LUCAS@nih.mail.edu.fr","SipUri":" "}],"CcRecipients":[],"BccRecipients":[],"Sensitivity":"Normal","IsDeliveryReceiptRequested":false,"IsReadReceiptRequested":false}],"ClientSupportsIrm":true,"OutboundCharset":"AutoDetect","MessageDisposition":"SendAndSaveCopy","ComposeOperation":"newMail"}}'
data = '{"__type":"CreateItemJsonRequest:#Exchange","Header":{"__type":"JsonRequestHeaders:#Exchange","RequestServerVersion":"Exchange2013","TimeZoneContext":{"__type":"TimeZoneContext:#Exchange","TimeZoneDefinition":{"__type":"TimeZoneDefinitionType:#Exchange","Id":"France Standard Time"}}},"Body":{"__type":"CreateItemRequest:#Exchange","Items":[{"__type":"Message:#Exchange","Subject":"API","Body":{"__type":"BodyContentType:#Exchange","BodyType":"HTML","Value":"<html><head><meta http-equiv=\\"Content-Type\\" content=\\"text/html; charset=UTF-8\\"><style type=\\"text/css\\" style=\\"display:none\\"><!-- p { margin-top: 0px; margin-bottom: 0px; }--></style></head><body dir=\\"ltr\\" style=\\"font-size:12pt;color:#000000;background-color:#FFFFFF;font-family:Calibri,Arial,Helvetica,sans-serif;\\"><p>API Test for NickC<br></p></body></html>"},"Importance":"Normal","From":null,"ToRecipients":[{"Name":"George LUCAS","EmailAddress":"George.LUCAS@nih.mail.edu.fr","RoutingType":"SMTP","MailboxType":"Mailbox","OriginalDisplayName":"George.LUCAS@nih.mail.edu.fr","SipUri":" "}],"CcRecipients":[],"BccRecipients":[],"Sensitivity":"Normal","IsDeliveryReceiptRequested":false,"IsReadReceiptRequested":false}],"ClientSupportsIrm":true,"OutboundCharset":"AutoDetect","MessageDisposition":"SendAndSaveCopy","ComposeOperation":"newMail"}}'
requests.post('https://localhost/api/service.svc', headers=headers, params=params, cookies=cookies, data=data)

View File

@@ -1,7 +1,7 @@
import requests
data = {
'foo': '\"bar\"'
}
data = [
('foo', '\\"bar\\"'),
]
requests.post('http://example.com/', data=data)

View File

@@ -1,7 +1,7 @@
import requests
data = {
'foo': '\\\'bar\\\''
}
data = [
('foo', '\\\'bar\\\''),
]
requests.post('http://example.com/', data=data)

View File

@@ -0,0 +1,7 @@
import requests
data = [
('field', 'don\'t you like quotes'),
]
requests.post('google.com', data=data)

View File

@@ -3,7 +3,7 @@ import requests
data = [
('foo', 'bar'),
('foo', ''),
('foo', 'barbar')
('foo', 'barbar'),
]
requests.post('http://example.com/', data=data)

View File

@@ -1,7 +1,7 @@
import requests
data = {
'foo': '"bar"'
}
data = [
('foo', '"bar"'),
]
requests.post('http://example.com/', data=data)

View File

@@ -1,7 +1,7 @@
import requests
data = {
'foo': '"bar"'
}
data = [
('foo', '"bar"'),
]
requests.post('http://example.com/', data=data)

View File

@@ -1,7 +1,7 @@
import requests
data = {
'foo': '\'bar\''
}
data = [
('foo', '\'bar\''),
]
requests.post('http://example.com/', data=data)

View File

@@ -12,9 +12,9 @@ headers = {
'Connection': 'keep-alive',
}
data = {
'msg1': 'wow',
'msg2': 'such'
}
data = [
('msg1', 'wow'),
('msg2', 'such'),
]
requests.post('http://fiddle.jshell.net/echo/html/', headers=headers, data=data)

View File

@@ -11,28 +11,28 @@ headers = {
'Connection': 'keep-alive',
}
data = {
'CultureId': '1',
'ApplicationId': '1',
'RecordsPerPage': '200',
'MaximumResults': '200',
'PropertyTypeId': '300',
'TransactionTypeId': '2',
'StoreyRange': '0-0',
'BuildingTypeId': '1',
'BedRange': '0-0',
'BathRange': '0-0',
'LongitudeMin': '-79.3676805496215',
'LongitudeMax': '-79.27300930023185',
'LatitudeMin': '43.660358732823845',
'LatitudeMax': '43.692390574029936',
'SortOrder': 'A',
'SortBy': '1',
'viewState': 'm',
'Longitude': '-79.4107246398925',
'Latitude': '43.6552047278685',
'ZoomLevel': '13',
'CurrentPage': '1'
}
data = [
('CultureId', '1'),
('ApplicationId', '1'),
('RecordsPerPage', '200'),
('MaximumResults', '200'),
('PropertyTypeId', '300'),
('TransactionTypeId', '2'),
('StoreyRange', '0-0'),
('BuildingTypeId', '1'),
('BedRange', '0-0'),
('BathRange', '0-0'),
('LongitudeMin', '-79.3676805496215'),
('LongitudeMax', '-79.27300930023185'),
('LatitudeMin', '43.660358732823845'),
('LatitudeMax', '43.692390574029936'),
('SortOrder', 'A'),
('SortBy', '1'),
('viewState', 'm'),
('Longitude', '-79.4107246398925'),
('Latitude', '43.6552047278685'),
('ZoomLevel', '13'),
('CurrentPage', '1'),
]
requests.post('http://www.realtor.ca/api/Listing.svc/PropertySearch_Post', headers=headers, data=data)

View File

@@ -4,22 +4,110 @@ var querystring = require('querystring')
require('string.prototype.startswith')
function pythonReprString (value) {
function repr (value) {
// In context of url parameters, don't accept nulls and such.
if (!value) {
return "''"
} else {
return "'" + value.replace('\\', '\\\\').replace("'", "\\'") + "'"
return "'" + jsesc(value, { quotes: 'single' }) + "'"
}
}
function getQueryDict (request) {
var queryDict = 'params = (\n'
for (var paramName in request.query) {
var rawValue = request.query[paramName]
var paramValue
if (Array.isArray(rawValue)) {
paramValue = rawValue.map(repr).join(', ')
} else {
paramValue = repr(rawValue)
}
queryDict += ' (' + repr(paramName) + ', ' + paramValue + '),\n'
}
queryDict += ')\n'
return queryDict
}
function getDataString (request) {
if (request.data.startsWith('@')) {
var filePath = request.data.slice(1)
if (request.isDataBinary) {
return 'data = open(\'' + filePath + '\', \'rb\').read()'
} else {
return 'data = open(\'' + filePath + '\')'
}
}
var parsedQueryString = querystring.parse(request.data)
var keyCount = Object.keys(parsedQueryString).length
var singleKeyOnly = keyCount === 1 && !parsedQueryString[Object.keys(parsedQueryString)[0]]
var singularData = request.isDataBinary || singleKeyOnly
if (singularData) {
return 'data = ' + repr(request.data) + '\n'
} else {
return getMultipleDataString(request, parsedQueryString)
}
}
function getMultipleDataString (request, parsedQueryString) {
var repeatedKey = false
for (var key in parsedQueryString) {
var value = parsedQueryString[key]
if (Array.isArray(value)) {
repeatedKey = true
}
}
var dataString
if (repeatedKey) {
dataString = 'data = [\n'
for (key in parsedQueryString) {
value = parsedQueryString[key]
if (Array.isArray(value)) {
for (var i = 0; i < value.length; i++) {
dataString += ' (' + repr(key) + ', ' + repr(value[i]) + '),\n'
}
} else {
dataString += ' (' + repr(key) + ', ' + repr(value) + '),\n'
}
}
dataString += ']\n'
} else {
dataString = 'data = [\n'
for (key in parsedQueryString) {
value = parsedQueryString[key]
dataString += ' (' + repr(key) + ', ' + repr(value) + '),\n'
}
dataString += ']\n'
}
return dataString
}
function getFilesString (request) {
// http://docs.python-requests.org/en/master/user/quickstart/#post-a-multipart-encoded-file
var filesString = 'files = [\n'
for (var multipartKey in request.multipartUploads) {
var multipartValue = request.multipartUploads[multipartKey]
if (multipartValue.startsWith('@')) {
filesString += ' (' + repr(multipartKey) + ', open(' + repr(multipartValue.slice(1)) + ", 'rb')),\n"
} else {
filesString += ' (' + repr(multipartKey) + ', ' + repr(multipartValue) + '),\n'
}
}
filesString += ']\n'
return filesString
}
var toPython = function (curlCommand) {
var request = util.parseCurlCommand(curlCommand)
var cookieDict
if (request.cookies) {
cookieDict = 'cookies = {\n'
for (var cookieName in request.cookies) {
cookieDict += " '" + cookieName + "': '" + request.cookies[cookieName] + "',\n"
cookieDict += ' ' + repr(cookieName) + ': ' + repr(request.cookies[cookieName]) + ',\n'
}
cookieDict += '}\n'
}
@@ -27,114 +115,22 @@ var toPython = function (curlCommand) {
if (request.headers) {
headerDict = 'headers = {\n'
for (var headerName in request.headers) {
headerDict += " '" + headerName + "': '" + request.headers[headerName] + "',\n"
headerDict += ' ' + repr(headerName) + ': ' + repr(request.headers[headerName]) + ',\n'
}
headerDict += '}\n'
}
var queryDict
if (request.query) {
queryDict = 'params = (\n'
for (var paramName in request.query) {
var rawValue = request.query[paramName]
var paramValue
if (Array.isArray(rawValue)) {
paramValue = rawValue.map(pythonReprString).join(', ')
} else {
paramValue = pythonReprString(rawValue)
}
queryDict += ' (' + pythonReprString(paramName) + ', ' + paramValue + '),\n'
}
queryDict += ')\n'
queryDict = getQueryDict(request)
}
var dataString
var filesString
if (request.data) {
if (request.data.startsWith('@')) {
var filePath = request.data.slice(1)
if (request.isDataBinary) {
dataString = 'data = open(\'' + filePath + '\', \'rb\').read()'
} else {
dataString = 'data = open(\'' + filePath + '\')'
}
} else {
var escapedData = request.data.replace(/'/g, "\\'")
if (escapedData.indexOf("'") > -1) {
escapedData = jsesc(request.data)
}
var parsedQueryString = querystring.parse(escapedData)
var keyCount = Object.keys(parsedQueryString).length
if (request.isDataBinary) {
dataString = "data = '" + request.data + "'\n"
} else if (keyCount === 1 && !parsedQueryString[Object.keys(parsedQueryString)[0]]) {
dataString = "data = '" + request.data + "'\n"
} else {
var dataIndex = 0
var repeatedKey = false
var valueCount = 0
for (var key in parsedQueryString) {
var value = parsedQueryString[key]
if (Array.isArray(value)) {
repeatedKey = true
valueCount += value.length
} else {
valueCount++
}
}
if (repeatedKey) {
dataString = 'data = [\n'
for (key in parsedQueryString) {
value = parsedQueryString[key]
if (Array.isArray(value)) {
for (var i = 0; i < value.length; i++) {
dataString += " ('" + key + "', '" + value[i] + "')"
if (dataIndex < valueCount - 1) {
dataString += ',\n'
}
dataIndex++
}
} else {
dataString += " ('" + key + "', '" + value + "')"
if (dataIndex < keyCount - 1) {
dataString += ',\n'
}
dataIndex++
}
}
dataString += '\n]\n'
} else {
dataString = 'data = {\n'
for (key in parsedQueryString) {
value = parsedQueryString[key]
dataString += " '" + key + "': '" + value + "'"
if (dataIndex < keyCount - 1) {
dataString += ',\n'
}
dataIndex++
}
dataString += '\n}\n'
}
}
}
dataString = getDataString(request)
} else if (request.multipartUploads) {
// http://docs.python-requests.org/en/master/user/quickstart/#post-a-multipart-encoded-file
filesString = 'files = {\n'
var filesIndex = 0
var filesCount = Object.keys(request.multipartUploads).length
for (var multipartKey in request.multipartUploads) {
var multipartValue = request.multipartUploads[multipartKey]
if (multipartValue.startsWith('@')) {
filesString += " '" + multipartKey + "': open('" + multipartValue.slice(1) + "', 'rb')"
} else {
filesString += " '" + multipartKey + "': '" + multipartValue + "'"
}
if (filesIndex < filesCount - 1) {
filesString += ',\n'
}
filesIndex++
}
filesString += '\n}\n'
filesString = getFilesString(request)
}
var requestLineWithUrlParams = 'requests.' + request.method + '(\'' + request.urlWithoutQuery + '\''
@@ -162,7 +158,7 @@ var toPython = function (curlCommand) {
var splitAuth = request.auth.split(':')
var user = splitAuth[0] || ''
var password = splitAuth[1] || ''
requestLineBody += ", auth=('" + user + "', '" + password + "')"
requestLineBody += ', auth=(' + repr(user) + ', ' + repr(password) + ')'
}
requestLineBody += ')'

View File

@@ -31,8 +31,8 @@ var parseCurlCommand = function (curlCommand) {
var cookieString
var cookies
var url = parsedArguments._[1]
// if url argument wasn't where we expected it, check other places
// it shows up
// if url argument wasn't where we expected it, check other places
// it shows up
if (!url && parsedArguments['L']) {
url = parsedArguments['L']
}
@@ -63,7 +63,7 @@ var parseCurlCommand = function (curlCommand) {
parsedArguments.F = [parsedArguments.F]
}
parsedArguments.F.forEach(function (multipartArgument) {
// input looks like key=value. value could be json or a file path prepended with an @
// input looks like key=value. value could be json or a file path prepended with an @
var splitArguments = multipartArgument.split('=', 2)
var key = splitArguments[0]
var value = splitArguments[1]