aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.toml8
-rw-r--r--Makefile.toml4
-rw-r--r--README.md2
-rw-r--r--examples/simple_async_std.rs29
-rw-r--r--examples/simple_tokio.rs29
-rw-r--r--src/lib.rs3
-rw-r--r--src/response.rs2
-rw-r--r--src/router.rs37
8 files changed, 106 insertions, 8 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 9f5bade..960224b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -18,15 +18,19 @@ categories = ["web-programming"]
logger = ["pretty_env_logger"]
auto-deduce-mime = ["tree_magic"]
response-macros = []
+tokio = ["dep:tokio", "tokio-openssl"]
+async-std = ["dep:async-std", "async-std-openssl"]
[dependencies]
# SSL
openssl = "0.10.38"
-tokio-openssl = "0.6.3"
+tokio-openssl = { version = "0.6.3", optional = true }
+async-std-openssl = { version = "0.6.3", optional = true }
# Non-blocking I/O
-tokio = { version = "1.26.0", features = ["full"] }
+tokio = { version = "1.26.0", features = ["full"], optional = true }
async-trait = "0.1.68"
+async-std = { version = "1.12.0", features = ["attributes"], optional = true }
# Logging
pretty_env_logger = { version = "0.4.0", optional = true }
diff --git a/Makefile.toml b/Makefile.toml
index 525424a..0b44382 100644
--- a/Makefile.toml
+++ b/Makefile.toml
@@ -4,12 +4,12 @@ command = "cargo"
toolchain = "nightly"
[tasks.check]
-args = ["check"]
+args = ["check", "--features", "logger,auto-deduce-mime,response-macros,${@}"]
command = "cargo"
toolchain = "nightly"
[tasks.clippy]
-args = ["clippy"]
+args = ["clippy", "--features", "logger,auto-deduce-mime,response-macros,${@}"]
command = "cargo"
toolchain = "nightly"
diff --git a/README.md b/README.md
index a01b597..efa0e51 100644
--- a/README.md
+++ b/README.md
@@ -7,6 +7,8 @@
Windmark is an elegant and highly performant, async Gemini server framework for
the modern age!
+Now supporting both [Tokio](https://github.com/tokio-rs/tokio) and [`async-std`](https://github.com/async-rs/async-std)!
+
## Usage
Check out an example starter project
diff --git a/examples/simple_async_std.rs b/examples/simple_async_std.rs
new file mode 100644
index 0000000..cc2b498
--- /dev/null
+++ b/examples/simple_async_std.rs
@@ -0,0 +1,29 @@
+// This file is part of Windmark <https://github.com/gemrest/windmark>.
+// Copyright (C) 2022-2022 Fuwn <[email protected]>
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 3.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+// Copyright (C) 2022-2022 Fuwn <[email protected]>
+// SPDX-License-Identifier: GPL-3.0-only
+
+//! `cargo run --example simple_async_std --features async-std`
+
+#[windmark::main]
+async fn main() -> Result<(), Box<dyn std::error::Error>> {
+ windmark::Router::new()
+ .set_private_key_file("windmark_private.pem")
+ .set_certificate_file("windmark_public.pem")
+ .mount("/", |_| windmark::Response::success("Hello, async-std!"))
+ .run()
+ .await
+}
diff --git a/examples/simple_tokio.rs b/examples/simple_tokio.rs
new file mode 100644
index 0000000..21b2a98
--- /dev/null
+++ b/examples/simple_tokio.rs
@@ -0,0 +1,29 @@
+// This file is part of Windmark <https://github.com/gemrest/windmark>.
+// Copyright (C) 2022-2022 Fuwn <[email protected]>
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 3.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+// Copyright (C) 2022-2022 Fuwn <[email protected]>
+// SPDX-License-Identifier: GPL-3.0-only
+
+//! `cargo run --example simple_tokio --features tokio`
+
+#[windmark::main]
+async fn main() -> Result<(), Box<dyn std::error::Error>> {
+ windmark::Router::new()
+ .set_private_key_file("windmark_private.pem")
+ .set_certificate_file("windmark_public.pem")
+ .mount("/", |_| windmark::Response::success("Hello, Tokio!"))
+ .run()
+ .await
+}
diff --git a/src/lib.rs b/src/lib.rs
index fd31430..1682da0 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -40,7 +40,10 @@ pub mod utilities;
#[macro_use]
extern crate log;
+#[cfg(feature = "async-std")]
+pub use async_std::main;
pub use module::{AsyncModule, Module};
pub use response::Response;
pub use router::Router;
+#[cfg(feature = "tokio")]
pub use tokio::main;
diff --git a/src/response.rs b/src/response.rs
index 9a8efb8..90950da 100644
--- a/src/response.rs
+++ b/src/response.rs
@@ -98,7 +98,7 @@ impl Response {
#[must_use]
pub fn binary_success_auto(content: &[u8]) -> Self {
Self::new(22, String::from_utf8_lossy(content))
- .with_mime(&tree_magic::from_u8(&*content))
+ .with_mime(&tree_magic::from_u8(content))
.clone()
}
diff --git a/src/router.rs b/src/router.rs
index 1bb295c..8df8c03 100644
--- a/src/router.rs
+++ b/src/router.rs
@@ -25,7 +25,13 @@ use std::{
time,
};
+#[cfg(feature = "async-std")]
+use async_std::{
+ io::{ReadExt, WriteExt},
+ sync::Mutex as AsyncMutex,
+};
use openssl::ssl::{self, SslAcceptor, SslMethod};
+#[cfg(feature = "tokio")]
use tokio::{
io::{AsyncReadExt, AsyncWriteExt},
sync::Mutex as AsyncMutex,
@@ -47,9 +53,12 @@ use crate::{
macro_rules! block {
($body:expr) => {
+ #[cfg(feature = "tokio")]
::tokio::task::block_in_place(|| {
::tokio::runtime::Handle::current().block_on(async { $body });
});
+ #[cfg(feature = "async-std")]
+ ::async_std::task::block_on(async { $body });
};
}
@@ -70,6 +79,11 @@ macro_rules! or_error {
};
}
+#[cfg(feature = "tokio")]
+type Stream = tokio_openssl::SslStream<tokio::net::TcpStream>;
+#[cfg(feature = "async-std")]
+type Stream = async_std_openssl::SslStream<async_std::net::TcpStream>;
+
/// A router which takes care of all tasks a Windmark server should handle:
/// response generation, panics, logging, and more.
#[derive(Clone)]
@@ -266,8 +280,13 @@ impl Router {
pretty_env_logger::init();
}
+ #[cfg(feature = "tokio")]
let listener =
tokio::net::TcpListener::bind(format!("0.0.0.0:{}", self.port)).await?;
+ #[cfg(feature = "async-std")]
+ let listener =
+ async_std::net::TcpListener::bind(format!("0.0.0.0:{}", self.port))
+ .await?;
#[cfg(feature = "logger")]
info!("windmark is listening for connections");
@@ -277,8 +296,12 @@ impl Router {
Ok((stream, _)) => {
let mut self_clone = self.clone();
let acceptor = self_clone.ssl_acceptor.clone();
+ #[cfg(feature = "tokio")]
+ let spawner = tokio::spawn;
+ #[cfg(feature = "async-std")]
+ let spawner = async_std::task::spawn;
- tokio::spawn(async move {
+ spawner(async move {
let ssl = match ssl::Ssl::new(acceptor.context()) {
Ok(ssl) => ssl,
Err(e) => {
@@ -288,7 +311,12 @@ impl Router {
}
};
- match tokio_openssl::SslStream::new(ssl, stream) {
+ #[cfg(feature = "tokio")]
+ let quick_stream = tokio_openssl::SslStream::new(ssl, stream);
+ #[cfg(feature = "async-std")]
+ let quick_stream = async_std_openssl::SslStream::new(ssl, stream);
+
+ match quick_stream {
Ok(mut stream) => {
if let Err(e) = std::pin::Pin::new(&mut stream).accept().await {
println!("stream accept error: {e:?}");
@@ -312,7 +340,7 @@ impl Router {
#[allow(clippy::too_many_lines)]
async fn handle(
&mut self,
- stream: &mut tokio_openssl::SslStream<tokio::net::TcpStream>,
+ stream: &mut Stream,
) -> Result<(), Box<dyn Error>> {
let mut buffer = [0u8; 1024];
let mut url = Url::parse("gemini://fuwn.me/")?;
@@ -473,7 +501,10 @@ impl Router {
)
.await?;
+ #[cfg(feature = "tokio")]
stream.shutdown().await?;
+ #[cfg(feature = "async-std")]
+ stream.get_mut().shutdown(std::net::Shutdown::Both)?;
Ok(())
}