From f913899ad5e0c884abbea53dc5a42da5bcccddec Mon Sep 17 00:00:00 2001 From: Dmitry Date: Mon, 22 Jul 2024 20:03:38 +0700 Subject: [PATCH] fix: fix issue for multipart/form-data and cookie header (#4172) * fix(multipart-formdata): fix type for data variable * fix(multipart-formdata): fix parameter filter for unsetted file * fix(multipart-formdata): add mime type for sending file * fix(multipart-formdata): add application/octet-stream by default mimetype * fix(multipart-formdata): remove content-type: multipart/form-data header * fix(multipart-formdata): remove cookie cookie header if not present * fix(multipart-formdata): fix content-type filter --------- Co-authored-by: Dmitry Mukovkin --- .../src/helpers/utils/EffectiveURL.ts | 8 +++++++- .../src-tauri/src/interceptor.rs | 6 ++++-- .../src/platform/interceptors/native/index.ts | 19 +++++++++++++------ 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/packages/hoppscotch-common/src/helpers/utils/EffectiveURL.ts b/packages/hoppscotch-common/src/helpers/utils/EffectiveURL.ts index 491d268ec..7b2aed2bd 100644 --- a/packages/hoppscotch-common/src/helpers/utils/EffectiveURL.ts +++ b/packages/hoppscotch-common/src/helpers/utils/EffectiveURL.ts @@ -320,7 +320,13 @@ function getFinalBodyFromRequest( if (request.body.contentType === "multipart/form-data") { return pipe( request.body.body ?? [], - A.filter((x) => (x.key !== "" || x.isFile) && x.active), // Remove empty keys + A.filter( + (x) => + x.key !== "" && + x.active && + (typeof x.value === "string" || + (x.value.length > 0 && x.value[0] instanceof File)) + ), // Remove empty keys and unsetted file // Sort files down arraySort((a, b) => { diff --git a/packages/hoppscotch-selfhost-desktop/src-tauri/src/interceptor.rs b/packages/hoppscotch-selfhost-desktop/src-tauri/src/interceptor.rs index 0528dccef..f733d52e5 100644 --- a/packages/hoppscotch-selfhost-desktop/src-tauri/src/interceptor.rs +++ b/packages/hoppscotch-selfhost-desktop/src-tauri/src/interceptor.rs @@ -20,7 +20,8 @@ enum FormDataValue { Text(String), File { filename: String, - data: Vec + data: Vec, + mime: String } } @@ -112,11 +113,12 @@ fn convert_bodydef_to_req_action(req: &RequestDef) -> Option { for entry in entries { form = match &entry.value { FormDataValue::Text(value) => form.text(entry.key.clone(), value.clone()), - FormDataValue::File { filename, data } => + FormDataValue::File { filename, data, mime } => form.part( entry.key.clone(), reqwest::multipart::Part::bytes(data.clone()) .file_name(filename.clone()) + .mime_str(mime.as_str()).expect("Error while setting File enum") ), } } diff --git a/packages/hoppscotch-selfhost-desktop/src/platform/interceptors/native/index.ts b/packages/hoppscotch-selfhost-desktop/src/platform/interceptors/native/index.ts index 1bc271f36..6a069f72b 100644 --- a/packages/hoppscotch-selfhost-desktop/src/platform/interceptors/native/index.ts +++ b/packages/hoppscotch-selfhost-desktop/src/platform/interceptors/native/index.ts @@ -1,5 +1,5 @@ import { CookieJarService } from "@hoppscotch/common/services/cookie-jar.service" -import { Interceptor, InterceptorError, NetworkResponse, RequestRunResult } from "@hoppscotch/common/services/interceptor.service" +import { Interceptor, InterceptorError, RequestRunResult } from "@hoppscotch/common/services/interceptor.service" import { Service } from "dioc" import { cloneDeep } from "lodash-es" import { invoke } from "@tauri-apps/api/tauri" @@ -21,7 +21,8 @@ type FormDataValue = | { File: { filename: string, - data: Uint8Array + data: number[], + mime: string } } @@ -124,12 +125,15 @@ async function processBody(axiosReq: AxiosRequestConfig): Promise !(key.toLowerCase() === "content-type" && value.toLowerCase() === "multipart/form-data")) // Removing header, because this header will be set by reqwest .map(([key, value]): KeyValuePair => ({ key, value })), parameters: Object.entries(axiosReq.params as Record ?? {}) .map(([key, value]): KeyValuePair => ({ key, value })), @@ -394,9 +399,11 @@ export class NativeInterceptorService extends Service implements Interceptor { new URL(processedReq.url!) ) - processedReq.headers["Cookie"] = relevantCookies - .map((cookie) => `${cookie.name!}=${cookie.value!}`) - .join(";") + if (relevantCookies.length > 0) { + processedReq.headers["Cookie"] = relevantCookies + .map((cookie) => `${cookie.name!}=${cookie.value!}`) + .join(";") + } const reqID = this.reqIDTicker++;