跳到主要内容

tauri桌面开发跨域处理

tauri 开发过程中的跨域处理

tauri基于webview2本质上还是基于 chromium内核,所以浏览器遇到跨域问题一样存在于tauri中 ,解决方案是在tauri的后端,即src-tarui开启http服务,这样就可以绕过跨域,调用任意服务,tauri已提该api@tauri-apps/api使用方式如下

tauri.conf.json 配置

   "allowlist": {
"all":true,
"http": {
"scope": [
"http://**",
"https://**"
]
}
}

htp api使用

Post请求

// import request from '@/utils/request';
import {http} from "@tauri-apps/api";
import { invoke } from '@tauri-apps/api/tauri'

const get_token=async ()=>{

const token = await invoke('get_token');
return token;
}

export async function pageAdminAccount(body, options) {
return http.fetch(`${BASE_URL}/admin/pageAccount`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
"Cookie": await get_token()

},
body: http.Body.json(body)
}).then(res=>{
return res.data
}).catch(e=>{
console.log(e)
});
}

GET请求

export async function queryRoleList(options) {
return http.fetch(`${BASE_URL}/admin/roleList`, {
method: 'GET',
headers: {
"Cookie": await get_token()
},
}).then(res=>{
return res.data
});
}


cookie处理

cookie同样保存在后端的自定义的Storage

/** 登录接口 POST /api/login/account */
export async function fakeUserLogin(body, options) {
return http.fetch(`${BASE_URL}/user/login`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: http.Body.json(body)
}).then(res=>{
console.log(res);
//var ss = res.rawHeaders
const token = res.rawHeaders['set-cookie'][0]

invoke('save_token', { token: token }).then((e) => {
console.log(e);
}).catch((e) => {
console.log(e);

});
return res.data
});
}

后端代码



pub struct Storage {
store: Mutex<HashMap<String, String>>,
}
fn main() {
let quit = CustomMenuItem::new("quit".to_string(), "退出");
let hide = CustomMenuItem::new("hide".to_string(), "隐藏");
let tray_menu = SystemTrayMenu::new()
.add_item(quit)
.add_native_item(SystemTrayMenuItem::Separator)
.add_item(hide); //添加菜单子项

let system_tray = SystemTray::new().with_menu(tray_menu);

tauri::Builder::default()
//全局缓存
.manage(Storage {
store: Default::default(),
})
//系统托盘
//系统托盘
.system_tray(system_tray)
//系统托盘 事件
.on_system_tray_event(|app, event| match event {
SystemTrayEvent::LeftClick {
position: _,
size: _,
..
} => {
println!("system tray received a left click");
let window = app.get_window("main").unwrap();
window.show().unwrap();
}
SystemTrayEvent::RightClick {
position: _,
size: _,
..
} => {
println!("system tray received a right click");
}
SystemTrayEvent::DoubleClick {
position: _,
size: _,
..
} => {
println!("system tray received a double click");
}
SystemTrayEvent::MenuItemClick { id, .. } => match id.as_str() {
"quit" => {
std::process::exit(0);
}
"hide" => {
let window = app.get_window("main").unwrap();
window.hide().unwrap();
}
_ => {}
},
_ => {}
})
.invoke_handler(tauri::generate_handler![
cmd::cmd::save_token,
cmd::cmd::get_token,
])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}



#[tauri::command]
pub async fn save_token(
token: String,
storage: State<'_, Storage>,
window: Window,
) -> Result<String, CustomeErrors> {
{
let mut map = storage.store.lock().await;
map.insert("token".to_string(), token.clone());
}
Ok(token)
}

#[tauri::command]
pub async fn get_token(
storage: State<'_, Storage>,
window: Window,
) -> Result<String, CustomeErrors> {
let token_result = storage.store.lock().await;
let token = token_result.get("token");
match token {
Some(e) => Ok(e.to_string()),
None => Ok("".to_string()),
}
}

图片跨域处理

图片同样使用http.fetch来获取,不过要把请求回来的二进制数据转成Blob数据,然后再使用URL.createObjectURL生成url

export default async function loadImg(url) {
return http.fetch(`${BASE_URL}/${url}`, {
method: 'GET',
headers: {
"Cookie": await get_token()

},
responseType:3

}).then(res=>{
const binaryArray = new Uint8Array(res.data);
const blob= new Blob([binaryArray], {type: 'image/png'});
const imgSrc = URL.createObjectURL(blob);
// console.log(imgSrc)

return imgSrc
});
}

总结

在开发前端web项目时,将数据请求接口单独封装抽离出来一个模块,就可以以很小改动的代价打包到tarui桌面程序