|
@@ -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,
|