Skip to content

Commit

Permalink
add asynchronous custom protocol support (#2535)
Browse files Browse the repository at this point in the history
Added asynchronous custom protocol handling
  • Loading branch information
d3rpp authored Jun 18, 2024
1 parent 07e6799 commit 5e3bb4f
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 2 deletions.
47 changes: 45 additions & 2 deletions packages/desktop/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use std::borrow::Cow;
use std::path::PathBuf;
use tao::window::{Icon, WindowBuilder};
use wry::http::{Request as HttpRequest, Response as HttpResponse};
use wry::RequestAsyncResponder;

use crate::menubar::{default_menu_bar, DioxusMenu};

Expand All @@ -22,6 +23,7 @@ pub struct Config {
pub(crate) window: WindowBuilder,
pub(crate) menu: Option<DioxusMenu>,
pub(crate) protocols: Vec<WryProtocol>,
pub(crate) asynchronous_protocols: Vec<AsyncWryProtocol>,
pub(crate) pre_rendered: Option<String>,
pub(crate) disable_context_menu: bool,
pub(crate) resource_dir: Option<PathBuf>,
Expand All @@ -38,6 +40,11 @@ pub(crate) type WryProtocol = (
Box<dyn Fn(HttpRequest<Vec<u8>>) -> HttpResponse<Cow<'static, [u8]>> + 'static>,
);

pub(crate) type AsyncWryProtocol = (
String,
Box<dyn Fn(HttpRequest<Vec<u8>>, RequestAsyncResponder) + 'static>,
);

impl Config {
/// Initializes a new `WindowBuilder` with default values.
#[inline]
Expand All @@ -56,6 +63,7 @@ impl Config {
window,
menu: Some(default_menu_bar()),
protocols: Vec::new(),
asynchronous_protocols: Vec::new(),
pre_rendered: None,
disable_context_menu: !cfg!(debug_assertions),
resource_dir: None,
Expand Down Expand Up @@ -109,11 +117,46 @@ impl Config {
}

/// Set a custom protocol
pub fn with_custom_protocol<F>(mut self, name: String, handler: F) -> Self
pub fn with_custom_protocol<F>(mut self, name: impl ToString, handler: F) -> Self
where
F: Fn(HttpRequest<Vec<u8>>) -> HttpResponse<Cow<'static, [u8]>> + 'static,
{
self.protocols.push((name, Box::new(handler)));
self.protocols.push((name.to_string(), Box::new(handler)));
self
}

/// Set an asynchronous custom protocol
///
/// **Example Usage**
/// ```rust
/// # use wry::http::response::Response as HTTPResponse;
/// # use std::borrow::Cow;
/// # use dioxus_desktop::Config;
/// #
/// # fn main() {
/// let cfg = Config::new()
/// .with_asynchronous_custom_protocol("asset", |request, responder| {
/// tokio::spawn(async move {
/// responder.respond(
/// HTTPResponse::builder()
/// .status(404)
/// .body(Cow::Borrowed("404 - Not Found".as_bytes()))
/// .unwrap()
/// );
/// });
/// });
/// # }
/// ```
/// note a key difference between Dioxus and Wry, the protocol name doesn't explicitly need to be a
/// [`String`], but needs to implement [`ToString`].
///
/// See [`wry`](wry::WebViewBuilder::with_asynchronous_custom_protocol) for more details on implementation
pub fn with_asynchronous_custom_protocol<F>(mut self, name: impl ToString, handler: F) -> Self
where
F: Fn(HttpRequest<Vec<u8>>, RequestAsyncResponder) + 'static,
{
self.asynchronous_protocols
.push((name.to_string(), Box::new(handler)));
self
}

Expand Down
4 changes: 4 additions & 0 deletions packages/desktop/src/webview.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,10 @@ impl WebviewInstance {
webview = webview.with_custom_protocol(name, handler);
}

for (name, handler) in cfg.asynchronous_protocols.drain(..) {
webview = webview.with_asynchronous_custom_protocol(name, handler);
}

const INITIALIZATION_SCRIPT: &str = r#"
if (document.addEventListener) {
document.addEventListener('contextmenu', function(e) {
Expand Down

0 comments on commit 5e3bb4f

Please sign in to comment.