diff --git a/plugins/http/guest-js/index.ts b/plugins/http/guest-js/index.ts index b76db724a..023552f08 100644 --- a/plugins/http/guest-js/index.ts +++ b/plugins/http/guest-js/index.ts @@ -30,56 +30,6 @@ declare global { } } -async function readBody(rid: number, kind: "blob" | "text"): Promise { - return await window.__TAURI_INVOKE__("plugin:http|fetch_read_body", { - rid, - kind, - }); -} - -class TauriResponse extends Response { - _rid: number = 0; - - blob(): Promise { - return readBody(this._rid, "blob").then( - (bytes) => - new Blob([bytes], { - type: this.headers.get("content-type") || "application/octet-stream", - }), - ); - } - - json(): Promise { - return readBody(this._rid, "text").then((data) => { - try { - return JSON.parse(data); - } catch (e) { - if (this.ok && data === "") { - return {}; - } else if (this.ok) { - throw Error(`Failed to parse response \`${data}\` as JSON: ${e}`); - } - } - }); - } - - formData(): Promise { - return this.json().then((json) => { - const form = new FormData(); - for (const [key, value] of Object.entries( - json as Record, - )) { - form.append(key, value); - } - return form; - }); - } - - text(): Promise { - return readBody(this._rid, "text"); - } -} - /** * Options to configure the Rust client used to make fetch requests * @@ -112,7 +62,7 @@ export interface ClientOptions { export async function fetch( input: URL | Request | string, init?: RequestInit & ClientOptions, -): Promise { +): Promise { const maxRedirections = init?.maxRedirections; const connectTimeout = init?.maxRedirections; @@ -154,12 +104,16 @@ export async function fetch( rid, }); - const res = new TauriResponse(null, { + const body = await window.__TAURI_INVOKE__("plugin:http|fetch_read_body", { + rid, + }); + + const res = new Response(Uint8Array.from(body), { headers, status, statusText, }); - res._rid = rid; + // url is read only but seems like we can do this Object.defineProperty(res, "url", { value: url }); diff --git a/plugins/http/src/api-iife.js b/plugins/http/src/api-iife.js index a975f8696..18db71722 100644 --- a/plugins/http/src/api-iife.js +++ b/plugins/http/src/api-iife.js @@ -1 +1 @@ -if("__TAURI__"in window){var __TAURI_HTTP__=function(t){"use strict";async function e(t,e){return await window.__TAURI_INVOKE__("plugin:http|fetch_read_body",{rid:t,kind:e})}class r extends Response{constructor(){super(...arguments),this._rid=0}blob(){return e(this._rid,"blob").then((t=>new Blob([t],{type:this.headers.get("content-type")||"application/octet-stream"})))}json(){return e(this._rid,"text").then((t=>{try{return JSON.parse(t)}catch(e){if(this.ok&&""===t)return{};if(this.ok)throw Error(`Failed to parse response \`${t}\` as JSON: ${e}`)}}))}formData(){return this.json().then((t=>{const e=new FormData;for(const[r,n]of Object.entries(t))e.append(r,n);return e}))}text(){return e(this._rid,"text")}}return t.fetch=async function(t,e){const n=null==e?void 0:e.maxRedirections,i=null==e?void 0:e.maxRedirections;e&&(delete e.maxRedirections,delete e.connectTimeout);const s=new Request(t,e),o=await s.arrayBuffer(),a=o.byteLength?Array.from(new Uint8Array(o)):null,_=await window.__TAURI_INVOKE__("plugin:http|fetch",{cmd:"fetch",method:s.method,url:s.url,headers:Array.from(s.headers.entries()),data:a,maxRedirections:n,connectTimeout:i});s.signal.addEventListener("abort",(()=>{window.__TAURI_INVOKE__("plugin:http|fetch_cancel",{rid:_})}));const{status:d,statusText:c,url:u,headers:h}=await window.__TAURI_INVOKE__("plugin:http|fetch_send",{rid:_}),l=new r(null,{headers:h,status:d,statusText:c});return l._rid=_,Object.defineProperty(l,"url",{value:u}),l},t}({});Object.defineProperty(window.__TAURI__,"http",{value:__TAURI_HTTP__})} +if("__TAURI__"in window){var __TAURI_HTTP__=function(e){"use strict";return e.fetch=async function(e,t){const n=null==t?void 0:t.maxRedirections,r=null==t?void 0:t.maxRedirections;t&&(delete t.maxRedirections,delete t.connectTimeout);const _=new Request(e,t),i=await _.arrayBuffer(),a=i.byteLength?Array.from(new Uint8Array(i)):null,d=await window.__TAURI_INVOKE__("plugin:http|fetch",{cmd:"fetch",method:_.method,url:_.url,headers:Array.from(_.headers.entries()),data:a,maxRedirections:n,connectTimeout:r});_.signal.addEventListener("abort",(()=>{window.__TAURI_INVOKE__("plugin:http|fetch_cancel",{rid:d})}));const{status:o,statusText:s,url:c,headers:u}=await window.__TAURI_INVOKE__("plugin:http|fetch_send",{rid:d}),l=await window.__TAURI_INVOKE__("plugin:http|fetch_read_body",{rid:d}),w=new Response(Uint8Array.from(l),{headers:u,status:o,statusText:s});return Object.defineProperty(w,"url",{value:c}),w},e}({});Object.defineProperty(window.__TAURI__,"http",{value:__TAURI_HTTP__})} diff --git a/plugins/http/src/commands.rs b/plugins/http/src/commands.rs index adac0458d..833b4e7f0 100644 --- a/plugins/http/src/commands.rs +++ b/plugins/http/src/commands.rs @@ -2,11 +2,11 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT -use std::{collections::HashMap, str::FromStr, time::Duration}; +use std::{collections::HashMap, time::Duration}; use http::{header, HeaderName, HeaderValue, Method, StatusCode}; use reqwest::redirect::Policy; -use serde::{de::Deserializer, Deserialize, Serialize}; +use serde::Serialize; use tauri::{command, AppHandle, Runtime}; use crate::{Error, FetchRequest, HttpExt, RequestId}; @@ -20,40 +20,6 @@ pub struct FetchResponse { url: String, } -#[derive(Serialize)] -#[serde(untagged)] -pub enum ResponseBody { - Blob(Vec), - Text(String), -} - -pub enum BodyKind { - Blob, - Text, -} - -impl FromStr for BodyKind { - type Err = &'static str; - - fn from_str(s: &str) -> Result { - match s.to_lowercase().as_str() { - "blob" => Ok(Self::Blob), - "text" => Ok(Self::Text), - _ => Err("unknown body kind"), - } - } -} - -impl<'de> Deserialize<'de> for BodyKind { - fn deserialize(deserializer: D) -> std::result::Result - where - D: Deserializer<'de>, - { - let kind = String::deserialize(deserializer)?; - kind.parse().map_err(serde::de::Error::custom) - } -} - #[command] pub async fn fetch( app: AppHandle, @@ -202,15 +168,11 @@ pub async fn fetch_send( pub(crate) async fn fetch_read_body( app: AppHandle, rid: RequestId, - kind: BodyKind, -) -> crate::Result { +) -> crate::Result> { let mut response_table = app.http().responses.lock().await; let res = response_table .remove(&rid) .ok_or(Error::InvalidRequestId(rid))?; - match kind { - BodyKind::Blob => Ok(ResponseBody::Blob(res.bytes().await?.to_vec())), - BodyKind::Text => Ok(ResponseBody::Text(res.text().await?)), - } + Ok(res.bytes().await?.to_vec()) }