aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFuwn <[email protected]>2023-03-31 22:10:02 +0000
committerFuwn <[email protected]>2023-03-31 22:10:02 +0000
commit30622ece082a951a975133f02a26a4709a9610e0 (patch)
treedc06366cd07f1795fc9f2bf93a9d52b2b9f7bfea
parentfeat(carg): bump 0.2.2 -> 0.2.3 (diff)
downloadwindmark-30622ece082a951a975133f02a26a4709a9610e0.tar.xz
windmark-30622ece082a951a975133f02a26a4709a9610e0.zip
feat(response): macro-based responses
-rw-r--r--Cargo.toml2
-rw-r--r--README.md14
-rw-r--r--examples/windmark.rs91
-rw-r--r--src/response.rs2
-rw-r--r--src/response/macros.rs69
5 files changed, 116 insertions, 62 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 860d7eb..95b8dbb 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -2,7 +2,7 @@
[package]
name = "windmark"
-version = "0.2.3"
+version = "0.2.4"
authors = ["Fuwn <[email protected]>"]
edition = "2021"
description = "An elegant and highly performant async Gemini server framework"
diff --git a/README.md b/README.md
index 47c18ab..cfa5808 100644
--- a/README.md
+++ b/README.md
@@ -18,15 +18,15 @@ Check out an example starter project
# Cargo.toml
[dependencies]
-windmark = "0.2.3"
+windmark = "0.2.4"
tokio = { version = "0.2.4", features = ["full"] }
# If you would like to use the built-in logger (recommended)
-# windmark = { version = "0.2.3", features = ["logger"] }
+# windmark = { version = "0.2.4", features = ["logger"] }
# If you would like to use the built-in MIME dedection when `Success`-ing a file
# (recommended)
-# windmark = { version = "0.2.3", features = ["auto-deduce-mime"] }
+# windmark = { version = "0.2.4", features = ["auto-deduce-mime"] }
```
### Implement a Windmark server
@@ -41,10 +41,10 @@ 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("/", Box::new(|_| Response::success("Hello, World!")))
- .set_error_handler(Box::new(|_| {
- Response::permanent_failure("This route does not exist!")
- }))
+ .mount("/", windmark::success!("Hello, World!"))
+ .set_error_handler(
+ windmark::permanent_failure!("This route does not exist!")
+ )
.run()
.await
}
diff --git a/examples/windmark.rs b/examples/windmark.rs
index 8b7839c..4507048 100644
--- a/examples/windmark.rs
+++ b/examples/windmark.rs
@@ -21,7 +21,12 @@
#[macro_use]
extern crate log;
-use windmark::{response::Response, returnable::CallbackContext, Router};
+use windmark::{
+ response::Response,
+ returnable::CallbackContext,
+ success,
+ Router,
+};
#[derive(Default)]
struct Clicker {
@@ -69,10 +74,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
}));
router.set_fix_path(true);
router.attach_stateless(|r| {
- r.mount(
- "/module",
- Box::new(|_| Response::success("This is a module!")),
- );
+ r.mount("/module", success!("This is a module!"));
});
router.attach(Clicker::default());
router.set_pre_route_callback(Box::new(|context| {
@@ -97,11 +99,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
}));
router.mount(
"/",
- Box::new(|_| {
- Response::success(
- "# INDEX\n\nWelcome!\n\n=> /test Test Page\n=> /time Unix Epoch",
- )
- }),
+ success!("# INDEX\n\nWelcome!\n\n=> /test Test Page\n=> /time Unix Epoch"),
);
router.mount(
"/specific-mime",
@@ -113,60 +111,51 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
);
router.mount(
"/ip",
- Box::new(|context| {
- Response::success(format!(
- "Hello, {}",
- context.tcp.peer_addr().unwrap().ip()
- ))
- }),
- );
- router.mount(
- "/test",
- Box::new(|_| Response::success("hi there\n=> / back")),
+ success!(
+ context,
+ format!("Hello, {}", context.tcp.peer_addr().unwrap().ip())
+ ),
);
+ router.mount("/test", success!("hi there\n=> / back"));
router.mount(
"/temporary-failure",
- Box::new(|_| Response::temporary_failure("Woops, temporarily...")),
+ windmark::temporary_failure!("Woops, temporarily..."),
);
router.mount(
"/time",
- Box::new(|_| {
- Response::success(
- std::time::UNIX_EPOCH
- .elapsed()
- .unwrap()
- .as_nanos()
- .to_string(),
- )
- }),
+ success!(std::time::UNIX_EPOCH
+ .elapsed()
+ .unwrap()
+ .as_nanos()
+ .to_string()),
);
router.mount(
"/query",
- Box::new(|context| {
- Response::success(format!(
+ success!(
+ context,
+ format!(
"queries: {:?}",
windmark::utilities::queries_from_url(&context.url)
- ))
- }),
+ )
+ ),
);
router.mount(
"/param/:lang",
- Box::new(|context| {
- Response::success(format!(
- "Parameter lang is {}",
- context.params.get("lang").unwrap()
- ))
- }),
+ success!(
+ context,
+ format!("Parameter lang is {}", context.params.get("lang").unwrap())
+ ),
);
router.mount(
"/names/:first/:last",
- Box::new(|context| {
- Response::success(format!(
+ success!(
+ context,
+ format!(
"{} {}",
context.params.get("first").unwrap(),
context.params.get("last").unwrap()
- ))
- }),
+ )
+ ),
);
router.mount(
"/input",
@@ -188,23 +177,17 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
}
}),
);
- router.mount(
- "/error",
- Box::new(|_| Response::certificate_not_valid("no")),
- );
+ router.mount("/error", windmark::certificate_not_valid!("no"));
router.mount(
"/redirect",
- Box::new(|_| Response::permanent_redirect("gemini://localhost/test")),
+ windmark::permanent_redirect!("gemini://localhost/test"),
);
#[cfg(feature = "auto-deduce-mime")]
router.mount("/auto-file", {
- Box::new(|_| Response::binary_success_auto(include_bytes!("../LICENSE")))
+ windmark::binary_success_auto!(include_bytes!("../LICENSE"))
});
router.mount("/file", {
- Box::new(|_| {
- Response::binary_success(include_bytes!("../LICENSE"), "text/plain")
- .clone()
- })
+ windmark::binary_success!(include_bytes!("../LICENSE"), "text/plain")
});
router.mount(
"/secret",
diff --git a/src/response.rs b/src/response.rs
index 2da020f..455bf42 100644
--- a/src/response.rs
+++ b/src/response.rs
@@ -18,6 +18,8 @@
//! Content and response handlers
+mod macros;
+
macro_rules! response {
($name:ident, $status:expr) => {
pub fn $name<S>(content: S) -> Self
diff --git a/src/response/macros.rs b/src/response/macros.rs
new file mode 100644
index 0000000..e04b0ee
--- /dev/null
+++ b/src/response/macros.rs
@@ -0,0 +1,69 @@
+// 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
+
+macro_rules! response {
+ ($($name:tt),*) => {
+ $(
+ /// Trailing commas are not supported at the moment!
+ #[macro_export]
+ macro_rules! $name {
+ ($body:expr /* $(,)? */) => {
+ ::std::boxed::Box::new(|_| windmark::Response::$name($body))
+ };
+ ($context:ident, $body:expr /* $(,)? */) => {
+ ::std::boxed::Box::new(|$context| windmark::Response::$name($body))
+ };
+ }
+ )*
+ };
+}
+
+response!(input);
+response!(sensitive_input);
+response!(success);
+#[cfg(feature = "auto-deduce-mime")]
+response!(binary_success_auto);
+response!(temporary_redirect);
+response!(permanent_redirect);
+response!(temporary_failure);
+response!(server_unavailable);
+response!(cgi_error);
+response!(proxy_error);
+response!(slow_down);
+response!(permanent_failure);
+response!(not_found);
+response!(gone);
+response!(proxy_refused);
+response!(bad_request);
+response!(client_certificate_required);
+response!(certificate_not_valid);
+
+/// Trailing commas are not supported at the moment!
+#[macro_export]
+macro_rules! binary_success {
+ ($body:expr, $mime:expr) => {
+ ::std::boxed::Box::new(|_| {
+ ::windmark::Response::binary_success($body, $mime)
+ })
+ };
+ ($context:ident, $body:expr, $mime:expr) => {
+ ::std::boxed::Box::new(|$context| {
+ ::windmark::Response::binary_success($body, $mime)
+ })
+ };
+}