refactor(upload)!: take headers, method and body via an options object (#3613)

`upload(url, path, onProgress, { headers, method })` and
`download(url, path, onProgress, { headers, body })` replace the
positional optional arguments.

`headers` accepts both a `Map` and a plain object; previously a `Map`
was silently serialized as an empty object.
This commit is contained in:
Lucas Fernandes Nogueira
2026-09-22 06:07:43 -03:00
committed by GitHub
parent b2d7c387ef
commit 0ecb30e3cb
5 changed files with 94 additions and 25 deletions
+70 -13
View File
@@ -19,13 +19,57 @@ enum HttpMethod {
Patch = 'PATCH'
}
/**
* Options for {@linkcode upload}.
*
* @since 3.0.0
*/
interface UploadOptions {
/** Headers to send with the request. */
headers?: Map<string, string> | Record<string, string>
/** HTTP method to use. Defaults to {@linkcode HttpMethod.Post}. */
method?: HttpMethod
}
/**
* Options for {@linkcode download}.
*
* @since 3.0.0
*/
interface DownloadOptions {
/** Headers to send with the request. */
headers?: Map<string, string> | Record<string, string>
/** Body to send with the request. When set, a `POST` request is made instead of a `GET`. */
body?: string
}
function headersToRust(
headers: Map<string, string> | Record<string, string> | undefined
): Record<string, string> {
return headers instanceof Map ? Object.fromEntries(headers) : (headers ?? {})
}
/**
* Upload a file to the given url.
*
* @example
* ```typescript
* import { upload, HttpMethod } from '@tauri-apps/plugin-upload';
* const response = await upload(
* 'https://example.com/file-upload',
* './path/to/my/file.txt',
* ({ progressTotal, total }) => console.log(`Uploaded ${progressTotal} of ${total} bytes`),
* { headers: { 'Content-Type': 'text/plain' }, method: HttpMethod.Put }
* );
* ```
*
* @returns The response body.
*/
async function upload(
url: string,
filePath: string,
progressHandler?: ProgressHandler,
// TODO: V3 - Combine headers and methods into one `options` object
headers?: Map<string, string>,
method?: HttpMethod
options?: UploadOptions
): Promise<string> {
const ids = new Uint32Array(1)
window.crypto.getRandomValues(ids)
@@ -40,22 +84,34 @@ async function upload(
id,
url,
filePath,
headers: headers ?? {},
method: method ?? HttpMethod.Post,
headers: headersToRust(options?.headers),
method: options?.method ?? HttpMethod.Post,
onProgress
})
}
/// Download file from given url.
///
/// Note that `filePath` currently must include the file name.
/// Furthermore the progress events will report a total length of 0 if the server did not sent a `Content-Length` header or if the file is compressed.
/**
* Download a file from the given url.
*
* Note that `filePath` currently must include the file name.
* Furthermore the progress events will report a total length of 0 if the server did not sent a `Content-Length` header or if the file is compressed.
*
* @example
* ```typescript
* import { download } from '@tauri-apps/plugin-upload';
* await download(
* 'https://example.com/file-download-link',
* './path/to/save/my/file.txt',
* ({ progressTotal, total }) => console.log(`Downloaded ${progressTotal} of ${total} bytes`),
* { headers: { 'Content-Type': 'text/plain' } }
* );
* ```
*/
async function download(
url: string,
filePath: string,
progressHandler?: ProgressHandler,
headers?: Map<string, string>,
body?: string
options?: DownloadOptions
): Promise<void> {
const ids = new Uint32Array(1)
window.crypto.getRandomValues(ids)
@@ -70,10 +126,11 @@ async function download(
id,
url,
filePath,
headers: headers ?? {},
headers: headersToRust(options?.headers),
onProgress,
body
body: options?.body
})
}
export { download, upload, HttpMethod }
export type { ProgressPayload, ProgressHandler, UploadOptions, DownloadOptions }