ft: utils.createObjWithHashedKeys ft: curlify.extractKey test: curlify with array representation
This commit is contained in:
@@ -1,5 +1,19 @@
|
|||||||
import win from "./window"
|
import win from "./window"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* if duplicate key name existed from FormData entries,
|
||||||
|
* we mutated the key name by appending a hashIdx
|
||||||
|
* @param {String} k - possibly mutated key name
|
||||||
|
* @return {String} - src key name
|
||||||
|
*/
|
||||||
|
const extractKey = (k) => {
|
||||||
|
const hashIdx = "_**[]"
|
||||||
|
if (k.indexOf(hashIdx) < 0) {
|
||||||
|
return k
|
||||||
|
}
|
||||||
|
return k.split(hashIdx)[0].trim()
|
||||||
|
}
|
||||||
|
|
||||||
export default function curl( request ){
|
export default function curl( request ){
|
||||||
let curlified = []
|
let curlified = []
|
||||||
let type = ""
|
let type = ""
|
||||||
@@ -21,11 +35,12 @@ export default function curl( request ){
|
|||||||
|
|
||||||
if(type === "multipart/form-data" && request.get("method") === "POST") {
|
if(type === "multipart/form-data" && request.get("method") === "POST") {
|
||||||
for( let [ k,v ] of request.get("body").entrySeq()) {
|
for( let [ k,v ] of request.get("body").entrySeq()) {
|
||||||
|
let extractedKey = extractKey(k)
|
||||||
curlified.push( "-F" )
|
curlified.push( "-F" )
|
||||||
if (v instanceof win.File) {
|
if (v instanceof win.File) {
|
||||||
curlified.push( `"${k}=@${v.name}${v.type ? `;type=${v.type}` : ""}"` )
|
curlified.push(`"${extractedKey}=@${v.name}${v.type ? `;type=${v.type}` : ""}"` )
|
||||||
} else {
|
} else {
|
||||||
curlified.push( `"${k}=${v}"` )
|
curlified.push(`"${extractedKey}=${v}"` )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -67,17 +67,64 @@ export function arrayify (thing) {
|
|||||||
return normalizeArray(thing)
|
return normalizeArray(thing)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function fromJSOrdered (js) {
|
export function fromJSOrdered(js) {
|
||||||
if(isImmutable(js))
|
if (isImmutable(js)) {
|
||||||
return js // Can't do much here
|
return js // Can't do much here
|
||||||
|
}
|
||||||
if (js instanceof win.File)
|
if (js instanceof win.File) {
|
||||||
return js
|
return js
|
||||||
|
}
|
||||||
|
if (!isObject(js)) {
|
||||||
|
return js
|
||||||
|
}
|
||||||
|
if (Array.isArray(js)) {
|
||||||
|
return Im.Seq(js).map(fromJSOrdered).toList()
|
||||||
|
}
|
||||||
|
if (js.entries) {
|
||||||
|
// handle multipart/form-data
|
||||||
|
const objWithHashedKeys = createObjWithHashedKeys(js)
|
||||||
|
return Im.OrderedMap(objWithHashedKeys).map(fromJSOrdered)
|
||||||
|
}
|
||||||
|
return Im.OrderedMap(js).map(fromJSOrdered)
|
||||||
|
}
|
||||||
|
|
||||||
return !isObject(js) ? js :
|
/**
|
||||||
Array.isArray(js) ?
|
* Convert a FormData object into plain object
|
||||||
Im.Seq(js).map(fromJSOrdered).toList() :
|
* Append a hashIdx and counter to the key name, if multiple exists
|
||||||
Im.OrderedMap(js).map(fromJSOrdered)
|
* if single, key name = <original>
|
||||||
|
* if multiple, key name = <original><hashIdx><count>
|
||||||
|
* @param {FormData} fdObj - a FormData object
|
||||||
|
* @return {Object} - a plain object
|
||||||
|
*/
|
||||||
|
export function createObjWithHashedKeys (fdObj) {
|
||||||
|
if (!fdObj.entries) {
|
||||||
|
return fdObj // not a FormData object with iterable
|
||||||
|
}
|
||||||
|
const newObj = {}
|
||||||
|
const hashIdx = "_**[]" // our internal identifier
|
||||||
|
const trackKeys = {}
|
||||||
|
for (let pair of fdObj.entries()) {
|
||||||
|
if (!newObj[pair[0]] && !(trackKeys[pair[0]] && trackKeys[pair[0]].containsMultiple)) {
|
||||||
|
newObj[pair[0]] = pair[1] // first key name: no hash required
|
||||||
|
} else {
|
||||||
|
if (!trackKeys[pair[0]]) {
|
||||||
|
// initiate tracking key for multiple
|
||||||
|
trackKeys[pair[0]] = {
|
||||||
|
containsMultiple: true,
|
||||||
|
length: 1
|
||||||
|
}
|
||||||
|
// "reassign" first pair to matching hashed format for multiple
|
||||||
|
let hashedKeyFirst = `${pair[0]}${hashIdx}${trackKeys[pair[0]].length}`
|
||||||
|
newObj[hashedKeyFirst] = newObj[pair[0]]
|
||||||
|
// remove non-hashed key of multiple
|
||||||
|
delete newObj[pair[0]] // first
|
||||||
|
}
|
||||||
|
trackKeys[pair[0]].length += 1
|
||||||
|
let hashedKeyCurrent = `${pair[0]}${hashIdx}${trackKeys[pair[0]].length}`
|
||||||
|
newObj[hashedKeyCurrent] = pair[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newObj
|
||||||
}
|
}
|
||||||
|
|
||||||
export function bindToState(obj, state) {
|
export function bindToState(obj, state) {
|
||||||
|
|||||||
@@ -143,6 +143,26 @@ describe("curlify", function() {
|
|||||||
expect(curlified).toEqual("curl -X POST \"http://example.com\" -H \"content-type: multipart/form-data\" -F \"id=123\" -F \"name=Sahar\"")
|
expect(curlified).toEqual("curl -X POST \"http://example.com\" -H \"content-type: multipart/form-data\" -F \"id=123\" -F \"name=Sahar\"")
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("should print a curl with formData that extracts array representation with hashIdx", function() {
|
||||||
|
// Note: hashIdx = `_**[]${counter}`
|
||||||
|
// Usage of hashIdx is an internal SwaggerUI method to convert formData array into something curlify can handle
|
||||||
|
const req = {
|
||||||
|
url: "http://example.com",
|
||||||
|
method: "POST",
|
||||||
|
headers: { "content-type": "multipart/form-data" },
|
||||||
|
body: {
|
||||||
|
id: "123",
|
||||||
|
"fruits[]_**[]1": "apple",
|
||||||
|
"fruits[]_**[]2": "banana",
|
||||||
|
"fruits[]_**[]3": "grape"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let curlified = curl(Im.fromJS(req))
|
||||||
|
|
||||||
|
expect(curlified).toEqual("curl -X POST \"http://example.com\" -H \"content-type: multipart/form-data\" -F \"id=123\" -F \"fruits[]=apple\" -F \"fruits[]=banana\" -F \"fruits[]=grape\"")
|
||||||
|
})
|
||||||
|
|
||||||
it("should print a curl with formData and file", function() {
|
it("should print a curl with formData and file", function() {
|
||||||
var file = new win.File()
|
var file = new win.File()
|
||||||
file.name = "file.txt"
|
file.name = "file.txt"
|
||||||
|
|||||||
Reference in New Issue
Block a user