fix: multipart form data sorting (#2067)

* fix: multipart form data sorting

  place all the file types in multipart form data
  body in the last to avoid errors due to map key
  being placed after file type data

* refactor: fp-ify formdata file sort implementation

Co-authored-by: Liyas Thomas <liyascthomas@gmail.com>
Co-authored-by: Andrew Bastin <andrewbastin.k@gmail.com>
This commit is contained in:
kyteinsky
2022-01-22 21:00:39 +00:00
committed by GitHub
parent 3bb65f2115
commit 6205b5f163
3 changed files with 83 additions and 19 deletions

View File

@@ -1,3 +1,5 @@
import { pipe } from "fp-ts/function"
import * as A from "fp-ts/Array"
import { combineLatest, Observable } from "rxjs"
import { map } from "rxjs/operators"
import {
@@ -6,6 +8,8 @@ import {
HoppRESTRequest,
} from "@hoppscotch/data"
import { parseTemplateString, parseBodyEnvVariables } from "../templating"
import { arrayFlatMap, arraySort } from "../functional/array"
import { toFormData } from "../functional/formData"
import { Environment, getGlobalVariables } from "~/newstore/environments"
export interface EffectiveHoppRESTRequest extends HoppRESTRequest {
@@ -59,27 +63,34 @@ function getFinalBodyFromRequest(
}
if (request.body.contentType === "multipart/form-data") {
const formData = new FormData()
return pipe(
request.body.body,
A.filter((x) => x.key !== "" && x.active), // Remove empty keys
request.body.body
.filter((x) => x.key !== "" && x.active) // Remove empty keys
.map(
(x) =>
<FormDataKeyValue>{
active: x.active,
isFile: x.isFile,
key: parseTemplateString(x.key, env.variables),
value: x.isFile
? x.value
: parseTemplateString(x.value, env.variables),
}
)
.forEach((entry) => {
if (!entry.isFile) formData.append(entry.key, entry.value)
else entry.value.forEach((blob) => formData.append(entry.key, blob))
})
// Sort files down
arraySort((a, b) => {
if (a.isFile) return 1
if (b.isFile) return -1
return 0
}),
return formData
// FormData allows only a single blob in an entry,
// we split array blobs into separate entries (FormData will then join them together during exec)
arrayFlatMap((x) =>
x.isFile
? x.value.map((v) => ({
key: parseTemplateString(x.key, env.variables),
value: v as string | Blob,
}))
: [
{
key: parseTemplateString(x.key, env.variables),
value: parseTemplateString(x.value, env.variables),
},
]
),
toFormData
)
} else return parseBodyEnvVariables(request.body.body, env.variables)
}