mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-03-18 15:33:52 +01:00
Connection re-use for plugin networking and beta NTLM plugin (#295)
This commit is contained in:
@@ -2,7 +2,7 @@ use crate::error::Result;
|
||||
use tauri::{command, AppHandle, Manager, Runtime, State, WebviewWindow};
|
||||
use tauri_plugin_dialog::{DialogExt, MessageDialogKind};
|
||||
use yaak_crypto::manager::EncryptionManagerExt;
|
||||
use yaak_plugins::events::{GetThemesResponse, PluginWindowContext};
|
||||
use yaak_plugins::events::{GetThemesResponse, PluginContext};
|
||||
use yaak_plugins::manager::PluginManager;
|
||||
use yaak_plugins::native_template_functions::{
|
||||
decrypt_secure_template_function, encrypt_secure_template_function,
|
||||
@@ -28,8 +28,8 @@ pub(crate) async fn cmd_decrypt_template<R: Runtime>(
|
||||
template: &str,
|
||||
) -> Result<String> {
|
||||
let app_handle = window.app_handle();
|
||||
let window_context = &PluginWindowContext::new(&window);
|
||||
Ok(decrypt_secure_template_function(&app_handle, window_context, template)?)
|
||||
let plugin_context = &PluginContext::new(&window);
|
||||
Ok(decrypt_secure_template_function(&app_handle, plugin_context, template)?)
|
||||
}
|
||||
|
||||
#[command]
|
||||
@@ -38,8 +38,8 @@ pub(crate) async fn cmd_secure_template<R: Runtime>(
|
||||
window: WebviewWindow<R>,
|
||||
template: &str,
|
||||
) -> Result<String> {
|
||||
let window_context = &PluginWindowContext::new(&window);
|
||||
Ok(encrypt_secure_template_function(&app_handle, window_context, template)?)
|
||||
let plugin_context = &PluginContext::new(&window);
|
||||
Ok(encrypt_secure_template_function(&app_handle, plugin_context, template)?)
|
||||
}
|
||||
|
||||
#[command]
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
use hyper_util::client::legacy::connect::dns::{
|
||||
GaiResolver as HyperGaiResolver, Name as HyperName,
|
||||
};
|
||||
use reqwest::dns::{Addrs, Name, Resolve, Resolving};
|
||||
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
use tower_service::Service;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct LocalhostResolver {
|
||||
fallback: HyperGaiResolver,
|
||||
}
|
||||
|
||||
impl LocalhostResolver {
|
||||
pub fn new() -> Arc<Self> {
|
||||
let resolver = HyperGaiResolver::new();
|
||||
Arc::new(Self { fallback: resolver })
|
||||
}
|
||||
}
|
||||
|
||||
impl Resolve for LocalhostResolver {
|
||||
fn resolve(&self, name: Name) -> Resolving {
|
||||
let host = name.as_str().to_lowercase();
|
||||
|
||||
let is_localhost = host.ends_with(".localhost");
|
||||
if is_localhost {
|
||||
// Port 0 is fine; reqwest replaces it with the URL's explicit
|
||||
// port or the scheme’s default (80/443, etc.).
|
||||
// (See docs note below.)
|
||||
let addrs: Vec<SocketAddr> = vec![
|
||||
SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 0),
|
||||
SocketAddr::new(IpAddr::V6(Ipv6Addr::LOCALHOST), 0),
|
||||
];
|
||||
|
||||
return Box::pin(async move {
|
||||
Ok::<Addrs, Box<dyn std::error::Error + Send + Sync>>(Box::new(addrs.into_iter()))
|
||||
});
|
||||
}
|
||||
|
||||
let mut fallback = self.fallback.clone();
|
||||
let name_str = name.as_str().to_string();
|
||||
Box::pin(async move {
|
||||
match HyperName::from_str(&name_str) {
|
||||
Ok(n) => fallback
|
||||
.call(n)
|
||||
.await
|
||||
.map(|addrs| Box::new(addrs) as Addrs)
|
||||
.map_err(|err| Box::new(err) as Box<dyn std::error::Error + Send + Sync>),
|
||||
Err(e) => Err(Box::new(e) as Box<dyn std::error::Error + Send + Sync>),
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,9 @@ pub enum Error {
|
||||
#[error(transparent)]
|
||||
CryptoError(#[from] yaak_crypto::error::Error),
|
||||
|
||||
#[error(transparent)]
|
||||
HttpError(#[from] yaak_http::error::Error),
|
||||
|
||||
#[error(transparent)]
|
||||
GitError(#[from] yaak_git::error::Error),
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ use tauri::{Manager, Runtime, WebviewWindow};
|
||||
use yaak_grpc::{KeyAndValueRef, MetadataMap};
|
||||
use yaak_models::models::GrpcRequest;
|
||||
use yaak_models::query_manager::QueryManagerExt;
|
||||
use yaak_plugins::events::{CallHttpAuthenticationRequest, HttpHeader};
|
||||
use yaak_plugins::events::{CallHttpAuthenticationRequest, HttpHeader, PluginContext};
|
||||
use yaak_plugins::manager::PluginManager;
|
||||
|
||||
pub(crate) fn metadata_to_map(metadata: MetadataMap) -> BTreeMap<String, String> {
|
||||
@@ -81,7 +81,12 @@ pub(crate) async fn build_metadata<R: Runtime>(
|
||||
.collect(),
|
||||
};
|
||||
let plugin_result = plugin_manager
|
||||
.call_http_authentication(&window, &authentication_type, plugin_req)
|
||||
.call_http_authentication(
|
||||
&window,
|
||||
&authentication_type,
|
||||
plugin_req,
|
||||
&PluginContext::new(window),
|
||||
)
|
||||
.await?;
|
||||
for header in plugin_result.set_headers.unwrap_or_default() {
|
||||
metadata.insert(header.name, header.value);
|
||||
|
||||
@@ -6,9 +6,9 @@ use http::header::{ACCEPT, USER_AGENT};
|
||||
use http::{HeaderMap, HeaderName, HeaderValue};
|
||||
use log::{debug, error, warn};
|
||||
use mime_guess::Mime;
|
||||
use reqwest::redirect::Policy;
|
||||
use reqwest::{Method, NoProxy, Response};
|
||||
use reqwest::{Proxy, Url, multipart};
|
||||
use reqwest::{Method, Response};
|
||||
use reqwest::{Url, multipart};
|
||||
use reqwest_cookie_store::{CookieStore, CookieStoreMutex};
|
||||
use serde_json::Value;
|
||||
use std::collections::BTreeMap;
|
||||
use std::path::PathBuf;
|
||||
@@ -21,6 +21,10 @@ use tokio::fs::{File, create_dir_all};
|
||||
use tokio::io::AsyncWriteExt;
|
||||
use tokio::sync::watch::Receiver;
|
||||
use tokio::sync::{Mutex, oneshot};
|
||||
use yaak_http::client::{
|
||||
HttpConnectionOptions, HttpConnectionProxySetting, HttpConnectionProxySettingAuth,
|
||||
};
|
||||
use yaak_http::manager::HttpConnectionManager;
|
||||
use yaak_models::models::{
|
||||
Cookie, CookieJar, Environment, HttpRequest, HttpResponse, HttpResponseHeader,
|
||||
HttpResponseState, ProxySetting, ProxySettingAuth,
|
||||
@@ -28,12 +32,11 @@ use yaak_models::models::{
|
||||
use yaak_models::query_manager::QueryManagerExt;
|
||||
use yaak_models::util::UpdateSource;
|
||||
use yaak_plugins::events::{
|
||||
CallHttpAuthenticationRequest, HttpHeader, PluginWindowContext, RenderPurpose,
|
||||
CallHttpAuthenticationRequest, HttpHeader, PluginContext, RenderPurpose,
|
||||
};
|
||||
use yaak_plugins::manager::PluginManager;
|
||||
use yaak_plugins::template_callback::PluginTemplateCallback;
|
||||
use yaak_templates::{RenderErrorBehavior, RenderOptions};
|
||||
use crate::dns::LocalhostResolver;
|
||||
|
||||
pub async fn send_http_request<R: Runtime>(
|
||||
window: &WebviewWindow<R>,
|
||||
@@ -42,9 +45,31 @@ pub async fn send_http_request<R: Runtime>(
|
||||
environment: Option<Environment>,
|
||||
cookie_jar: Option<CookieJar>,
|
||||
cancelled_rx: &mut Receiver<bool>,
|
||||
) -> Result<HttpResponse> {
|
||||
send_http_request_with_context(
|
||||
window,
|
||||
unrendered_request,
|
||||
og_response,
|
||||
environment,
|
||||
cookie_jar,
|
||||
cancelled_rx,
|
||||
&PluginContext::new(window),
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn send_http_request_with_context<R: Runtime>(
|
||||
window: &WebviewWindow<R>,
|
||||
unrendered_request: &HttpRequest,
|
||||
og_response: &HttpResponse,
|
||||
environment: Option<Environment>,
|
||||
cookie_jar: Option<CookieJar>,
|
||||
cancelled_rx: &mut Receiver<bool>,
|
||||
plugin_context: &PluginContext,
|
||||
) -> Result<HttpResponse> {
|
||||
let app_handle = window.app_handle().clone();
|
||||
let plugin_manager = app_handle.state::<PluginManager>();
|
||||
let connection_manager = app_handle.state::<HttpConnectionManager>();
|
||||
let settings = window.db().get_settings();
|
||||
let workspace = window.db().get_workspace(&unrendered_request.workspace_id)?;
|
||||
let environment_id = environment.map(|e| e.id);
|
||||
@@ -72,11 +97,7 @@ pub async fn send_http_request<R: Runtime>(
|
||||
}
|
||||
};
|
||||
|
||||
let cb = PluginTemplateCallback::new(
|
||||
window.app_handle(),
|
||||
&PluginWindowContext::new(window),
|
||||
RenderPurpose::Send,
|
||||
);
|
||||
let cb = PluginTemplateCallback::new(window.app_handle(), &plugin_context, RenderPurpose::Send);
|
||||
|
||||
let opt = RenderOptions {
|
||||
error_behavior: RenderErrorBehavior::Throw,
|
||||
@@ -102,65 +123,33 @@ pub async fn send_http_request<R: Runtime>(
|
||||
}
|
||||
debug!("Sending request to {} {url_string}", request.method);
|
||||
|
||||
let mut client_builder = reqwest::Client::builder()
|
||||
.redirect(match workspace.setting_follow_redirects {
|
||||
true => Policy::limited(10), // TODO: Handle redirects natively
|
||||
false => Policy::none(),
|
||||
})
|
||||
.connection_verbose(true)
|
||||
.gzip(true)
|
||||
.brotli(true)
|
||||
.deflate(true)
|
||||
.dns_resolver(LocalhostResolver::new())
|
||||
.referer(false)
|
||||
.tls_info(true);
|
||||
|
||||
let tls_config = yaak_http::tls::get_config(workspace.setting_validate_certificates, true);
|
||||
client_builder = client_builder.use_preconfigured_tls(tls_config);
|
||||
|
||||
match settings.proxy {
|
||||
Some(ProxySetting::Disabled) => client_builder = client_builder.no_proxy(),
|
||||
let proxy_setting = match settings.proxy {
|
||||
None => HttpConnectionProxySetting::System,
|
||||
Some(ProxySetting::Disabled) => HttpConnectionProxySetting::Disabled,
|
||||
Some(ProxySetting::Enabled {
|
||||
http,
|
||||
https,
|
||||
auth,
|
||||
disabled,
|
||||
bypass,
|
||||
}) if !disabled => {
|
||||
debug!("Using proxy http={http} https={https} bypass={bypass}");
|
||||
if !http.is_empty() {
|
||||
match Proxy::http(http) {
|
||||
Ok(mut proxy) => {
|
||||
if let Some(ProxySettingAuth { user, password }) = auth.clone() {
|
||||
debug!("Using http proxy auth");
|
||||
proxy = proxy.basic_auth(user.as_str(), password.as_str());
|
||||
disabled,
|
||||
}) => {
|
||||
if disabled {
|
||||
HttpConnectionProxySetting::System
|
||||
} else {
|
||||
HttpConnectionProxySetting::Enabled {
|
||||
http,
|
||||
https,
|
||||
bypass,
|
||||
auth: match auth {
|
||||
None => None,
|
||||
Some(ProxySettingAuth { user, password }) => {
|
||||
Some(HttpConnectionProxySettingAuth { user, password })
|
||||
}
|
||||
proxy = proxy.no_proxy(NoProxy::from_string(&bypass));
|
||||
client_builder = client_builder.proxy(proxy);
|
||||
}
|
||||
Err(e) => {
|
||||
warn!("Failed to apply http proxy {e:?}");
|
||||
}
|
||||
};
|
||||
}
|
||||
if !https.is_empty() {
|
||||
match Proxy::https(https) {
|
||||
Ok(mut proxy) => {
|
||||
if let Some(ProxySettingAuth { user, password }) = auth {
|
||||
debug!("Using https proxy auth");
|
||||
proxy = proxy.basic_auth(user.as_str(), password.as_str());
|
||||
}
|
||||
proxy = proxy.no_proxy(NoProxy::from_string(&bypass));
|
||||
client_builder = client_builder.proxy(proxy);
|
||||
}
|
||||
Err(e) => {
|
||||
warn!("Failed to apply https proxy {e:?}");
|
||||
}
|
||||
};
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {} // Nothing to do for this one, as it is the default
|
||||
}
|
||||
};
|
||||
|
||||
// Add cookie store if specified
|
||||
let maybe_cookie_manager = match cookie_jar.clone() {
|
||||
@@ -179,23 +168,33 @@ pub async fn send_http_request<R: Runtime>(
|
||||
.map(|c| Ok(c))
|
||||
.collect::<Vec<Result<_>>>();
|
||||
|
||||
let store = reqwest_cookie_store::CookieStore::from_cookies(cookies, true)?;
|
||||
let cookie_store = reqwest_cookie_store::CookieStoreMutex::new(store);
|
||||
let cookie_store = CookieStore::from_cookies(cookies, true)?;
|
||||
let cookie_store = CookieStoreMutex::new(cookie_store);
|
||||
let cookie_store = Arc::new(cookie_store);
|
||||
client_builder = client_builder.cookie_provider(Arc::clone(&cookie_store));
|
||||
|
||||
Some((cookie_store, cj))
|
||||
let cookie_provider = Arc::clone(&cookie_store);
|
||||
Some((cookie_provider, cj))
|
||||
}
|
||||
None => None,
|
||||
};
|
||||
|
||||
if workspace.setting_request_timeout > 0 {
|
||||
client_builder = client_builder.timeout(Duration::from_millis(
|
||||
workspace.setting_request_timeout.unsigned_abs() as u64,
|
||||
));
|
||||
}
|
||||
|
||||
let client = client_builder.build()?;
|
||||
let client = connection_manager
|
||||
.get_client(
|
||||
&plugin_context.id,
|
||||
&HttpConnectionOptions {
|
||||
follow_redirects: workspace.setting_follow_redirects,
|
||||
validate_certificates: workspace.setting_validate_certificates,
|
||||
proxy: proxy_setting,
|
||||
cookie_provider: maybe_cookie_manager.as_ref().map(|(p, _)| Arc::clone(&p)),
|
||||
timeout: if workspace.setting_request_timeout > 0 {
|
||||
Some(Duration::from_millis(
|
||||
workspace.setting_request_timeout.unsigned_abs() as u64
|
||||
))
|
||||
} else {
|
||||
None
|
||||
},
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
|
||||
// Render query parameters
|
||||
let mut query_params = Vec::new();
|
||||
@@ -469,8 +468,9 @@ pub async fn send_http_request<R: Runtime>(
|
||||
})
|
||||
.collect(),
|
||||
};
|
||||
let auth_result =
|
||||
plugin_manager.call_http_authentication(&window, &authentication_type, req).await;
|
||||
let auth_result = plugin_manager
|
||||
.call_http_authentication(&window, &authentication_type, req, plugin_context)
|
||||
.await;
|
||||
let plugin_result = match auth_result {
|
||||
Ok(r) => r,
|
||||
Err(e) => {
|
||||
|
||||
@@ -23,7 +23,7 @@ use tauri::{Listener, Runtime};
|
||||
use tauri::{Manager, WindowEvent};
|
||||
use tauri_plugin_deep_link::DeepLinkExt;
|
||||
use tauri_plugin_log::fern::colors::ColoredLevelConfig;
|
||||
use tauri_plugin_log::{Builder, Target, TargetKind};
|
||||
use tauri_plugin_log::{Builder, Target, TargetKind, log};
|
||||
use tauri_plugin_window_state::{AppHandleExt, StateFlags};
|
||||
use tokio::sync::Mutex;
|
||||
use tokio::task::block_in_place;
|
||||
@@ -44,7 +44,7 @@ use yaak_plugins::events::{
|
||||
GetHttpAuthenticationConfigResponse, GetHttpAuthenticationSummaryResponse,
|
||||
GetHttpRequestActionsResponse, GetTemplateFunctionConfigResponse,
|
||||
GetTemplateFunctionSummaryResponse, InternalEvent, InternalEventPayload, JsonPrimitive,
|
||||
PluginWindowContext, RenderPurpose, ShowToastRequest,
|
||||
PluginContext, RenderPurpose, ShowToastRequest,
|
||||
};
|
||||
use yaak_plugins::manager::PluginManager;
|
||||
use yaak_plugins::plugin_meta::PluginMetadata;
|
||||
@@ -54,7 +54,6 @@ use yaak_templates::format_json::format_json;
|
||||
use yaak_templates::{RenderErrorBehavior, RenderOptions, Tokens, transform_args};
|
||||
|
||||
mod commands;
|
||||
mod dns;
|
||||
mod encoding;
|
||||
mod error;
|
||||
mod grpc;
|
||||
@@ -104,7 +103,7 @@ async fn cmd_template_tokens_to_string<R: Runtime>(
|
||||
) -> YaakResult<String> {
|
||||
let cb = PluginTemplateCallback::new(
|
||||
&app_handle,
|
||||
&PluginWindowContext::new(&window),
|
||||
&PluginContext::new(&window),
|
||||
RenderPurpose::Preview,
|
||||
);
|
||||
let new_tokens = transform_args(tokens, &cb)?;
|
||||
@@ -126,7 +125,7 @@ async fn cmd_render_template<R: Runtime>(
|
||||
environment_chain,
|
||||
&PluginTemplateCallback::new(
|
||||
&app_handle,
|
||||
&PluginWindowContext::new(&window),
|
||||
&PluginContext::new(&window),
|
||||
RenderPurpose::Preview,
|
||||
),
|
||||
&RenderOptions {
|
||||
@@ -170,7 +169,7 @@ async fn cmd_grpc_reflect<R: Runtime>(
|
||||
environment_chain,
|
||||
&PluginTemplateCallback::new(
|
||||
&app_handle,
|
||||
&PluginWindowContext::new(&window),
|
||||
&PluginContext::new(&window),
|
||||
RenderPurpose::Send,
|
||||
),
|
||||
&RenderOptions {
|
||||
@@ -219,7 +218,7 @@ async fn cmd_grpc_go<R: Runtime>(
|
||||
environment_chain.clone(),
|
||||
&PluginTemplateCallback::new(
|
||||
&app_handle,
|
||||
&PluginWindowContext::new(&window),
|
||||
&PluginContext::new(&window),
|
||||
RenderPurpose::Send,
|
||||
),
|
||||
&RenderOptions {
|
||||
@@ -344,7 +343,7 @@ async fn cmd_grpc_go<R: Runtime>(
|
||||
environment_chain,
|
||||
&PluginTemplateCallback::new(
|
||||
&app_handle,
|
||||
&PluginWindowContext::new(&window),
|
||||
&PluginContext::new(&window),
|
||||
RenderPurpose::Send,
|
||||
),
|
||||
&RenderOptions {
|
||||
@@ -416,7 +415,7 @@ async fn cmd_grpc_go<R: Runtime>(
|
||||
environment_chain,
|
||||
&PluginTemplateCallback::new(
|
||||
&app_handle,
|
||||
&PluginWindowContext::new(&window),
|
||||
&PluginContext::new(&window),
|
||||
RenderPurpose::Send,
|
||||
),
|
||||
&RenderOptions {
|
||||
@@ -1162,7 +1161,7 @@ async fn cmd_install_plugin<R: Runtime>(
|
||||
app_handle: AppHandle<R>,
|
||||
window: WebviewWindow<R>,
|
||||
) -> YaakResult<Plugin> {
|
||||
plugin_manager.add_plugin_by_dir(&PluginWindowContext::new(&window), &directory).await?;
|
||||
plugin_manager.add_plugin_by_dir(&PluginContext::new(&window), &directory).await?;
|
||||
|
||||
Ok(app_handle.db().upsert_plugin(
|
||||
&Plugin {
|
||||
@@ -1201,7 +1200,7 @@ async fn cmd_reload_plugins<R: Runtime>(
|
||||
window: WebviewWindow<R>,
|
||||
plugin_manager: State<'_, PluginManager>,
|
||||
) -> YaakResult<()> {
|
||||
plugin_manager.initialize_all_plugins(&app_handle, &PluginWindowContext::new(&window)).await?;
|
||||
plugin_manager.initialize_all_plugins(&app_handle, &PluginContext::new(&window)).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1351,6 +1350,7 @@ pub fn run() {
|
||||
.plugin(yaak_crypto::init())
|
||||
.plugin(yaak_fonts::init())
|
||||
.plugin(yaak_git::init())
|
||||
.plugin(yaak_http::init())
|
||||
.plugin(yaak_ws::init())
|
||||
.plugin(yaak_sync::init());
|
||||
|
||||
@@ -1621,13 +1621,13 @@ async fn call_frontend<R: Runtime>(
|
||||
v.to_owned()
|
||||
}
|
||||
|
||||
fn get_window_from_window_context<R: Runtime>(
|
||||
fn get_window_from_plugin_context<R: Runtime>(
|
||||
app_handle: &AppHandle<R>,
|
||||
window_context: &PluginWindowContext,
|
||||
plugin_context: &PluginContext,
|
||||
) -> Result<WebviewWindow<R>> {
|
||||
let label = match window_context {
|
||||
PluginWindowContext::Label { label, .. } => label,
|
||||
PluginWindowContext::None => {
|
||||
let label = match &plugin_context.label {
|
||||
Some(label) => label,
|
||||
None => {
|
||||
return app_handle
|
||||
.webview_windows()
|
||||
.iter()
|
||||
@@ -1643,7 +1643,7 @@ fn get_window_from_window_context<R: Runtime>(
|
||||
.find_map(|(_, w)| if w.label() == label { Some(w.to_owned()) } else { None });
|
||||
|
||||
if window.is_none() {
|
||||
error!("Failed to find window by {window_context:?}");
|
||||
error!("Failed to find window by {plugin_context:?}");
|
||||
}
|
||||
|
||||
Ok(window.ok_or(GenericError(format!("Failed to find window for {}", label)))?)
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
use crate::error::Result;
|
||||
use crate::http_request::send_http_request;
|
||||
use crate::http_request::send_http_request_with_context;
|
||||
use crate::render::{render_grpc_request, render_http_request, render_json_value};
|
||||
use crate::window::{CreateWindowConfig, create_window};
|
||||
use crate::{
|
||||
call_frontend, cookie_jar_from_window, environment_from_window, get_window_from_window_context,
|
||||
call_frontend, cookie_jar_from_window, environment_from_window, get_window_from_plugin_context,
|
||||
workspace_from_window,
|
||||
};
|
||||
use chrono::Utc;
|
||||
use cookie::Cookie;
|
||||
use log::error;
|
||||
use log::{debug, error};
|
||||
use tauri::{AppHandle, Emitter, Manager, Runtime};
|
||||
use tauri_plugin_clipboard_manager::ClipboardExt;
|
||||
use yaak_common::window::WorkspaceWindowTrait;
|
||||
@@ -19,7 +19,7 @@ use yaak_models::util::UpdateSource;
|
||||
use yaak_plugins::events::{
|
||||
Color, DeleteKeyValueResponse, EmptyPayload, ErrorResponse, FindHttpResponsesResponse,
|
||||
GetCookieValueResponse, GetHttpRequestByIdResponse, GetKeyValueResponse, Icon, InternalEvent,
|
||||
InternalEventPayload, ListCookieNamesResponse, PluginWindowContext, RenderGrpcRequestResponse,
|
||||
InternalEventPayload, ListCookieNamesResponse, RenderGrpcRequestResponse,
|
||||
RenderHttpRequestResponse, SendHttpRequestResponse, SetKeyValueResponse, ShowToastRequest,
|
||||
TemplateRenderResponse, WindowNavigateEvent,
|
||||
};
|
||||
@@ -33,23 +33,21 @@ pub(crate) async fn handle_plugin_event<R: Runtime>(
|
||||
plugin_handle: &PluginHandle,
|
||||
) -> Result<Option<InternalEventPayload>> {
|
||||
// debug!("Got event to app {event:?}");
|
||||
let window_context = event.window_context.to_owned();
|
||||
let plugin_context = event.context.to_owned();
|
||||
match event.clone().payload {
|
||||
InternalEventPayload::CopyTextRequest(req) => {
|
||||
app_handle.clipboard().write_text(req.text.as_str())?;
|
||||
Ok(Some(InternalEventPayload::CopyTextResponse(EmptyPayload {})))
|
||||
}
|
||||
InternalEventPayload::ShowToastRequest(req) => {
|
||||
match window_context {
|
||||
PluginWindowContext::Label { label, .. } => {
|
||||
app_handle.emit_to(label, "show_toast", req)?
|
||||
}
|
||||
_ => app_handle.emit("show_toast", req)?,
|
||||
match plugin_context.label {
|
||||
Some(label) => app_handle.emit_to(label, "show_toast", req)?,
|
||||
None => app_handle.emit("show_toast", req)?,
|
||||
};
|
||||
Ok(Some(InternalEventPayload::ShowToastResponse(EmptyPayload {})))
|
||||
}
|
||||
InternalEventPayload::PromptTextRequest(_) => {
|
||||
let window = get_window_from_window_context(app_handle, &window_context)?;
|
||||
let window = get_window_from_plugin_context(app_handle, &plugin_context)?;
|
||||
Ok(call_frontend(&window, event).await)
|
||||
}
|
||||
InternalEventPayload::FindHttpResponsesRequest(req) => {
|
||||
@@ -68,7 +66,7 @@ pub(crate) async fn handle_plugin_event<R: Runtime>(
|
||||
})))
|
||||
}
|
||||
InternalEventPayload::RenderGrpcRequestRequest(req) => {
|
||||
let window = get_window_from_window_context(app_handle, &window_context)?;
|
||||
let window = get_window_from_plugin_context(app_handle, &plugin_context)?;
|
||||
|
||||
let workspace =
|
||||
workspace_from_window(&window).expect("Failed to get workspace_id from window URL");
|
||||
@@ -78,7 +76,7 @@ pub(crate) async fn handle_plugin_event<R: Runtime>(
|
||||
req.grpc_request.folder_id.as_deref(),
|
||||
environment_id.as_deref(),
|
||||
)?;
|
||||
let cb = PluginTemplateCallback::new(app_handle, &window_context, req.purpose);
|
||||
let cb = PluginTemplateCallback::new(app_handle, &plugin_context, req.purpose);
|
||||
let opt = RenderOptions {
|
||||
error_behavior: RenderErrorBehavior::Throw,
|
||||
};
|
||||
@@ -89,7 +87,7 @@ pub(crate) async fn handle_plugin_event<R: Runtime>(
|
||||
})))
|
||||
}
|
||||
InternalEventPayload::RenderHttpRequestRequest(req) => {
|
||||
let window = get_window_from_window_context(app_handle, &window_context)?;
|
||||
let window = get_window_from_plugin_context(app_handle, &plugin_context)?;
|
||||
|
||||
let workspace =
|
||||
workspace_from_window(&window).expect("Failed to get workspace_id from window URL");
|
||||
@@ -99,7 +97,7 @@ pub(crate) async fn handle_plugin_event<R: Runtime>(
|
||||
req.http_request.folder_id.as_deref(),
|
||||
environment_id.as_deref(),
|
||||
)?;
|
||||
let cb = PluginTemplateCallback::new(app_handle, &window_context, req.purpose);
|
||||
let cb = PluginTemplateCallback::new(app_handle, &plugin_context, req.purpose);
|
||||
let opt = &RenderOptions {
|
||||
error_behavior: RenderErrorBehavior::Throw,
|
||||
};
|
||||
@@ -110,7 +108,7 @@ pub(crate) async fn handle_plugin_event<R: Runtime>(
|
||||
})))
|
||||
}
|
||||
InternalEventPayload::TemplateRenderRequest(req) => {
|
||||
let window = get_window_from_window_context(app_handle, &window_context)?;
|
||||
let window = get_window_from_plugin_context(app_handle, &plugin_context)?;
|
||||
|
||||
let workspace =
|
||||
workspace_from_window(&window).expect("Failed to get workspace_id from window URL");
|
||||
@@ -130,7 +128,7 @@ pub(crate) async fn handle_plugin_event<R: Runtime>(
|
||||
folder_id.as_deref(),
|
||||
environment_id.as_deref(),
|
||||
)?;
|
||||
let cb = PluginTemplateCallback::new(app_handle, &window_context, req.purpose);
|
||||
let cb = PluginTemplateCallback::new(app_handle, &plugin_context, req.purpose);
|
||||
let opt = RenderOptions {
|
||||
error_behavior: RenderErrorBehavior::Throw,
|
||||
};
|
||||
@@ -140,7 +138,7 @@ pub(crate) async fn handle_plugin_event<R: Runtime>(
|
||||
InternalEventPayload::ErrorResponse(resp) => {
|
||||
error!("Plugin error: {}: {:?}", resp.error, resp);
|
||||
let toast_event = plugin_handle.build_event_to_send(
|
||||
&window_context,
|
||||
&plugin_context,
|
||||
&InternalEventPayload::ShowToastRequest(ShowToastRequest {
|
||||
message: format!(
|
||||
"Plugin error from {}: {}",
|
||||
@@ -172,7 +170,7 @@ pub(crate) async fn handle_plugin_event<R: Runtime>(
|
||||
if !req.silent {
|
||||
let info = plugin_handle.info();
|
||||
let toast_event = plugin_handle.build_event_to_send(
|
||||
&window_context,
|
||||
&plugin_context,
|
||||
&InternalEventPayload::ShowToastRequest(ShowToastRequest {
|
||||
message: format!("Reloaded plugin {}@{}", info.name, info.version),
|
||||
icon: Some(Icon::Info),
|
||||
@@ -187,7 +185,7 @@ pub(crate) async fn handle_plugin_event<R: Runtime>(
|
||||
}
|
||||
}
|
||||
InternalEventPayload::SendHttpRequestRequest(req) => {
|
||||
let window = get_window_from_window_context(app_handle, &window_context)?;
|
||||
let window = get_window_from_plugin_context(app_handle, &plugin_context)?;
|
||||
let mut http_request = req.http_request;
|
||||
let workspace =
|
||||
workspace_from_window(&window).expect("Failed to get workspace_id from window URL");
|
||||
@@ -211,13 +209,14 @@ pub(crate) async fn handle_plugin_event<R: Runtime>(
|
||||
)?
|
||||
};
|
||||
|
||||
let http_response = send_http_request(
|
||||
let http_response = send_http_request_with_context(
|
||||
&window,
|
||||
&http_request,
|
||||
&http_response,
|
||||
environment,
|
||||
cookie_jar,
|
||||
&mut tokio::sync::watch::channel(false).1, // No-op cancel channel
|
||||
&plugin_context,
|
||||
)
|
||||
.await?;
|
||||
|
||||
@@ -240,7 +239,7 @@ pub(crate) async fn handle_plugin_event<R: Runtime>(
|
||||
};
|
||||
if let Err(e) = create_window(app_handle, win_config) {
|
||||
let error_event = plugin_handle.build_event_to_send(
|
||||
&window_context,
|
||||
&plugin_context,
|
||||
&InternalEventPayload::ErrorResponse(ErrorResponse {
|
||||
error: format!("Failed to create window: {:?}", e),
|
||||
}),
|
||||
@@ -253,12 +252,12 @@ pub(crate) async fn handle_plugin_event<R: Runtime>(
|
||||
{
|
||||
let event_id = event.id.clone();
|
||||
let plugin_handle = plugin_handle.clone();
|
||||
let window_context = window_context.clone();
|
||||
let plugin_context = plugin_context.clone();
|
||||
tauri::async_runtime::spawn(async move {
|
||||
while let Some(url) = navigation_rx.recv().await {
|
||||
let url = url.to_string();
|
||||
let event_to_send = plugin_handle.build_event_to_send(
|
||||
&window_context, // NOTE: Sending existing context on purpose here
|
||||
&plugin_context, // NOTE: Sending existing context on purpose here
|
||||
&InternalEventPayload::WindowNavigateEvent(WindowNavigateEvent { url }),
|
||||
Some(event_id.clone()),
|
||||
);
|
||||
@@ -270,11 +269,11 @@ pub(crate) async fn handle_plugin_event<R: Runtime>(
|
||||
{
|
||||
let event_id = event.id.clone();
|
||||
let plugin_handle = plugin_handle.clone();
|
||||
let window_context = window_context.clone();
|
||||
let plugin_context = plugin_context.clone();
|
||||
tauri::async_runtime::spawn(async move {
|
||||
while let Some(_) = close_rx.recv().await {
|
||||
let event_to_send = plugin_handle.build_event_to_send(
|
||||
&window_context,
|
||||
&plugin_context,
|
||||
&InternalEventPayload::WindowCloseEvent,
|
||||
Some(event_id.clone()),
|
||||
);
|
||||
@@ -309,7 +308,7 @@ pub(crate) async fn handle_plugin_event<R: Runtime>(
|
||||
})))
|
||||
}
|
||||
InternalEventPayload::ListCookieNamesRequest(_req) => {
|
||||
let window = get_window_from_window_context(app_handle, &window_context)?;
|
||||
let window = get_window_from_plugin_context(app_handle, &plugin_context)?;
|
||||
let names = match cookie_jar_from_window(&window) {
|
||||
None => Vec::new(),
|
||||
Some(j) => j
|
||||
@@ -323,7 +322,7 @@ pub(crate) async fn handle_plugin_event<R: Runtime>(
|
||||
})))
|
||||
}
|
||||
InternalEventPayload::GetCookieValueRequest(req) => {
|
||||
let window = get_window_from_window_context(app_handle, &window_context)?;
|
||||
let window = get_window_from_plugin_context(app_handle, &plugin_context)?;
|
||||
let value = match cookie_jar_from_window(&window) {
|
||||
None => None,
|
||||
Some(j) => j.cookies.into_iter().find_map(|c| match Cookie::parse(c.raw_cookie) {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
use serde_json::Value;
|
||||
use std::collections::BTreeMap;
|
||||
use yaak_http::apply_path_placeholders;
|
||||
use yaak_http::path_placeholders::apply_path_placeholders;
|
||||
use yaak_models::models::{
|
||||
Environment, GrpcRequest, HttpRequest, HttpRequestHeader, HttpUrlParameter,
|
||||
};
|
||||
use yaak_models::render::make_vars_hashmap;
|
||||
use yaak_templates::{RenderOptions, TemplateCallback, parse_and_render, render_json_value_raw};
|
||||
use yaak_templates::{parse_and_render, render_json_value_raw, RenderOptions, TemplateCallback};
|
||||
|
||||
pub async fn render_template<T: TemplateCallback>(
|
||||
template: &str,
|
||||
|
||||
Reference in New Issue
Block a user