Przeglądaj źródła

feat(api/http): properly handle Files in Body.form, closes #7390 (#7394)

Co-authored-by: Lucas Nogueira <lucas@tauri.studio>
closes #7390
Amr Bashir 2 lat temu
rodzic
commit
2eab150563

+ 5 - 0
.changes/api-formAsync.md

@@ -0,0 +1,5 @@
+---
+'@tauri-apps/api': 'patch:bug'
+---
+
+Fix `Body.form` static not reading and sending entries of type `Blob` (including subclasses such as `File`)

Plik diff jest za duży
+ 0 - 0
core/tauri/scripts/bundle.global.js


Plik diff jest za duży
+ 0 - 0
examples/api/dist/assets/index.css


Plik diff jest za duży
+ 0 - 0
examples/api/dist/assets/index.js


+ 7 - 7
examples/api/src-tauri/Cargo.lock

@@ -3575,7 +3575,7 @@ dependencies = [
 
 [[package]]
 name = "tauri"
-version = "1.3.0"
+version = "1.4.1"
 dependencies = [
  "anyhow",
  "base64 0.21.0",
@@ -3637,7 +3637,7 @@ dependencies = [
 
 [[package]]
 name = "tauri-build"
-version = "1.3.0"
+version = "1.4.0"
 dependencies = [
  "anyhow",
  "cargo_toml",
@@ -3654,7 +3654,7 @@ dependencies = [
 
 [[package]]
 name = "tauri-codegen"
-version = "1.3.0"
+version = "1.4.0"
 dependencies = [
  "base64 0.21.0",
  "brotli",
@@ -3678,7 +3678,7 @@ dependencies = [
 
 [[package]]
 name = "tauri-macros"
-version = "1.3.0"
+version = "1.4.0"
 dependencies = [
  "heck 0.4.0",
  "proc-macro2",
@@ -3690,7 +3690,7 @@ dependencies = [
 
 [[package]]
 name = "tauri-runtime"
-version = "0.13.0"
+version = "0.14.0"
 dependencies = [
  "gtk",
  "http",
@@ -3709,7 +3709,7 @@ dependencies = [
 
 [[package]]
 name = "tauri-runtime-wry"
-version = "0.13.0"
+version = "0.14.0"
 dependencies = [
  "cocoa",
  "gtk",
@@ -3727,7 +3727,7 @@ dependencies = [
 
 [[package]]
 name = "tauri-utils"
-version = "1.3.0"
+version = "1.4.0"
 dependencies = [
  "aes-gcm",
  "brotli",

Plik diff jest za duży
+ 0 - 0
tooling/api/docs/js-api.json


+ 53 - 34
tooling/api/src/http.ts

@@ -85,6 +85,50 @@ interface FilePart<T> {
 
 type Part = string | Uint8Array | FilePart<Uint8Array>
 
+type FormInput = Record<string, Part> | FormData
+type FormBody = Record<string, string | number[] | FilePart<number[]>>
+
+async function formBody(data: FormInput): Promise<FormBody> {
+  const form: FormBody = {}
+
+  const append = async (
+    key: string,
+    v: string | Uint8Array | FilePart<Uint8Array> | File
+  ): Promise<void> => {
+    if (v !== null) {
+      let r
+      if (typeof v === 'string') {
+        r = v
+      } else if (v instanceof Uint8Array || Array.isArray(v)) {
+        r = Array.from(v)
+      } else if (v instanceof File) {
+        r = {
+          file: Array.from(new Uint8Array(await v.arrayBuffer())),
+          mime: v.type,
+          fileName: v.name
+        }
+      } else if (typeof v.file === 'string') {
+        r = { file: v.file, mime: v.mime, fileName: v.fileName }
+      } else {
+        r = { file: Array.from(v.file), mime: v.mime, fileName: v.fileName }
+      }
+      form[String(key)] = r
+    }
+  }
+
+  if (data instanceof FormData) {
+    for (const [key, value] of data) {
+      await append(key, value)
+    }
+  } else {
+    for (const [key, value] of Object.entries(data)) {
+      await append(key, value)
+    }
+  }
+
+  return form
+}
+
 /**
  * The body object to be used on POST and PUT requests.
  *
@@ -108,6 +152,7 @@ class Body {
    * but you can set it to `multipart/form-data` if the Cargo feature `http-multipart` is enabled.
    *
    * Note that a file path must be allowed in the `fs` allowlist scope.
+   *
    * @example
    * ```typescript
    * import { Body } from "@tauri-apps/api/http"
@@ -131,40 +176,8 @@ class Body {
    *
    * @returns The body object ready to be used on the POST and PUT requests.
    */
-  static form(data: Record<string, Part> | FormData): Body {
-    const form: Record<string, string | number[] | FilePart<number[]>> = {}
-
-    const append = (
-      key: string,
-      v: string | Uint8Array | FilePart<Uint8Array> | File
-    ): void => {
-      if (v !== null) {
-        let r
-        if (typeof v === 'string') {
-          r = v
-        } else if (v instanceof Uint8Array || Array.isArray(v)) {
-          r = Array.from(v)
-        } else if (v instanceof File) {
-          r = { file: v.name, mime: v.type, fileName: v.name }
-        } else if (typeof v.file === 'string') {
-          r = { file: v.file, mime: v.mime, fileName: v.fileName }
-        } else {
-          r = { file: Array.from(v.file), mime: v.mime, fileName: v.fileName }
-        }
-        form[String(key)] = r
-      }
-    }
-
-    if (data instanceof FormData) {
-      for (const [key, value] of data) {
-        append(key, value)
-      }
-    } else {
-      for (const [key, value] of Object.entries(data)) {
-        append(key, value)
-      }
-    }
-    return new Body('Form', form)
+  static form(data: FormInput): Body {
+    return new Body('Form', data)
   }
 
   /**
@@ -343,6 +356,11 @@ class Client {
     if (jsonResponse) {
       options.responseType = ResponseType.Text
     }
+
+    if (options.body?.type === 'Form') {
+      options.body.payload = await formBody(options.body.payload as FormInput)
+    }
+
     return invokeTauriCommand<IResponse<T>>({
       __tauriModule: 'Http',
       message: {
@@ -546,6 +564,7 @@ export type {
   Duration,
   ClientOptions,
   Part,
+  FormInput,
   HttpVerb,
   HttpOptions,
   RequestOptions,

Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików