Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ target/

# dotenv environment variables file
.env
.envrc
.direnv

# .vscode workspace settings file
.vscode/settings.json
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ This repo and all plugins require a Rust version of at least **1.77.2**
| [stronghold](plugins/stronghold) | Encrypted, secure database. | ✅ | ✅ | ✅ | ? | ? |
| [updater](plugins/updater) | In-app updates for Tauri applications. | ✅ | ✅ | ✅ | ❌ | ❌ |
| [upload](plugins/upload) | Tauri plugin for file uploads through HTTP. | ✅ | ✅ | ✅ | ✅ | ✅ |
| [websocket](plugins/websocket) | Open a WebSocket connection using a Rust client in JS. | ✅ | ✅ | ✅ | ? | ? |
| [websocket](plugins/websocket) | Open a WebSocket connection using a Rust client in JS. | ✅ | ✅ | ✅ | ✅ | ✅ |
| [window-state](plugins/window-state) | Persist window sizes and positions. | ✅ | ✅ | ✅ | ❌ | ❌ |

- ✅: (Partially) Supported
Expand Down
100 changes: 100 additions & 0 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

66 changes: 66 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
flake-utils.url = "github:numtide/flake-utils";
fenix.url = "github:nix-community/fenix";
fenix.inputs.nixpkgs.follows = "nixpkgs";
};

outputs =
{
self,
nixpkgs,
flake-utils,
fenix,
}:
flake-utils.lib.eachDefaultSystem (
system:
let
pkgs = import nixpkgs {
system = system;
};

packages = with pkgs; [
curl
wget
pkg-config

cargo-tauri
cargo-info
cargo-udeps

(
with fenix.packages.${system};
combine [
complete.rustc
complete.rust-src
complete.cargo
complete.clippy
complete.rustfmt
complete.rust-analyzer
]
)
];

libraries = with pkgs; [
gtk3
libsoup_3
webkitgtk_4_1
cairo
gdk-pixbuf
glib
dbus
openssl
librsvg
];
in
{
devShell = pkgs.mkShell {
buildInputs = packages ++ libraries;

LD_LIBRARY_PATH = "${pkgs.lib.makeLibraryPath libraries}:$LD_LIBRARY_PATH";
XDG_DATA_DIRS = "${pkgs.gsettings-desktop-schemas}/share/gsettings-schemas/${pkgs.gsettings-desktop-schemas.name}:${pkgs.gtk3}/share/gsettings-schemas/${pkgs.gtk3.name}:$XDG_DATA_DIRS";
};
}
);
}
6 changes: 3 additions & 3 deletions plugins/http/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@

pub use reqwest;
use tauri::{
plugin::{Builder, TauriPlugin},
Manager, Runtime,
plugin::{Builder, TauriPlugin},
};

pub use error::{Error, Result};
Expand All @@ -21,9 +21,9 @@ mod scope;
#[cfg(feature = "cookies")]
const COOKIES_FILENAME: &str = ".cookies";

pub(crate) struct Http {
pub struct Http {
#[cfg(feature = "cookies")]
cookies_jar: std::sync::Arc<crate::reqwest_cookie_store::CookieStoreMutex>,
pub cookies_jar: std::sync::Arc<crate::reqwest_cookie_store::CookieStoreMutex>,
}

pub fn init<R: Runtime>() -> TauriPlugin<R> {
Expand Down
54 changes: 42 additions & 12 deletions plugins/websocket/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,29 @@
html_favicon_url = "https://github.com/tauri-apps/tauri/raw/dev/app-icon.png"
)]

use futures_util::{stream::SplitSink, SinkExt, StreamExt};
use http::header::{HeaderName, HeaderValue};
use serde::{ser::Serializer, Deserialize, Serialize};
use futures_util::{SinkExt, StreamExt, stream::SplitSink};
use http::{
HeaderMap,
header::{HeaderName, HeaderValue},
};
use serde::{Deserialize, Serialize, ser::Serializer};
use tauri::{
AppHandle, Manager, Runtime, State, Window,
ipc::Channel,
plugin::{Builder as PluginBuilder, TauriPlugin},
Manager, Runtime, State, Window,
};
use tokio::{net::TcpStream, sync::Mutex};
#[cfg(any(feature = "rustls-tls", feature = "native-tls"))]
use tokio_tungstenite::connect_async_tls_with_config;
#[cfg(not(any(feature = "rustls-tls", feature = "native-tls")))]
use tokio_tungstenite::connect_async_with_config;
use tokio_tungstenite::{
Connector, MaybeTlsStream, WebSocketStream,
tungstenite::{
Message,
client::IntoClientRequest,
protocol::{CloseFrame as ProtocolCloseFrame, WebSocketConfig},
Message,
},
Connector, MaybeTlsStream, WebSocketStream,
};

use std::collections::HashMap;
Expand Down Expand Up @@ -147,7 +150,7 @@ async fn connect<R: Runtime>(
config: Option<ConnectionConfig>,
) -> Result<Id> {
let id = rand::random();
let mut request = url.into_client_request()?;
let mut request = url.as_str().into_client_request()?;

if let Some(headers) = config.as_ref().and_then(|c| c.headers.as_ref()) {
for (k, v) in headers {
Expand All @@ -157,6 +160,10 @@ async fn connect<R: Runtime>(
}
}

if let Some(state) = window.app_handle().try_state::<RequestCallback<R>>() {
(state.inner().0)(url, request.headers_mut(), window.app_handle());
}

#[cfg(any(feature = "rustls-tls", feature = "native-tls"))]
let tls_connector = match window.try_state::<TlsConnector>() {
Some(tls_connector) => tls_connector.0.lock().await.clone(),
Expand Down Expand Up @@ -242,31 +249,54 @@ async fn send(
}

pub fn init<R: Runtime>() -> TauriPlugin<R> {
Builder::default().build()
Builder::new().build()
}

#[derive(Default)]
pub struct Builder {
type RqCb<R> =
Box<dyn Fn(String, &mut HeaderMap<HeaderValue>, &AppHandle<R>) + Send + Sync + 'static>;

/// Struct to provide concrete type for the manager
struct RequestCallback<R: Runtime>(RqCb<R>);

pub struct Builder<R: Runtime> {
tls_connector: Option<Connector>,
merge_headers: Option<RequestCallback<R>>,
}

impl Builder {
impl<R> Builder<R>
where
R: Runtime,
{
pub fn new() -> Self {
Self {
tls_connector: None,
merge_headers: None,
}
}

/// add a callback which is able to modify the initial headers of the http upgrade request.
/// This is useful for scenarios where the frontend may not know all the required headers that must be sent.
/// e.g. in the scenario of http-only cookies
pub fn merge_header_callback(mut self, cb: RqCb<R>) -> Self {
self.merge_headers.replace(RequestCallback(cb));
self
}

pub fn tls_connector(mut self, connector: Connector) -> Self {
self.tls_connector.replace(connector);
self
}

pub fn build<R: Runtime>(self) -> TauriPlugin<R> {
pub fn build(self) -> TauriPlugin<R> {
PluginBuilder::new("websocket")
.invoke_handler(tauri::generate_handler![connect, send])
.setup(|app, _api| {
app.manage(ConnectionManager::default());

if let Some(cb) = self.merge_headers {
app.manage(cb);
}

#[cfg(any(feature = "rustls-tls", feature = "native-tls"))]
app.manage(TlsConnector(Mutex::new(self.tls_connector)));
Ok(())
Expand Down