Skip to content

Commit

Permalink
Add sync_route extension
Browse files Browse the repository at this point in the history
  • Loading branch information
connorslade committed Oct 15, 2023
1 parent 0f2f323 commit 31a5fdf
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 12 deletions.
1 change: 1 addition & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ Coming Soon
- Add is_informational, is_success, is_redirect, is_client_error, and is_server_error methods on status codes.
- Use a Cow in HeaderName::Custom
- Don't store whole stream to get its length in Head ext
- Added sync_route extension

# 2.2.1

Expand Down
6 changes: 1 addition & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,10 @@ For more examples see the examples directory [here](https://github.com/Basicprog
Below is a super simple example so you can see the basics of afire syntax.

```rust no_run
// Import Lib
use afire::{Server, Method, Response, Header, Content};
use afire::prelude::*;

// Create Server
let mut server = Server::<()>::new("localhost", 8080);

// Add a route
server.route(Method::GET, "/greet/{name}", |ctx| {
let name = ctx.param("name");

Expand All @@ -49,7 +46,6 @@ server.route(Method::GET, "/greet/{name}", |ctx| {
Ok(())
});

// Start the server
server.run().unwrap();
```

Expand Down
8 changes: 7 additions & 1 deletion examples/tmp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ use std::{
};

use afire::{
extensions::{Date, Head, Logger, RedirectResponse, RouteShorthands, ServeStatic, Trace},
extensions::{
Date, Head, Logger, RedirectResponse, RouteShorthands, ServeStatic, SyncRoute, Trace,
},
internal::sync::{ForceLockMutex, ForceLockRwLock},
multipart::MultipartData,
prelude::*,
Expand Down Expand Up @@ -315,6 +317,10 @@ fn main() -> Result<(), Box<dyn Error>> {
Ok(())
});

server.sync_route(Method::GET, "/sync-test", |ctx| {
Ok(Response::new().text("Heyyyy"))
});

Test.attach(&mut server);
Date.attach(&mut server);
Trace::new().attach(&mut server);
Expand Down
3 changes: 3 additions & 0 deletions lib/extensions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
//! | [`RequestId`] | Add a Request-Id header to all requests. |
//! | [`RouteShorthands`] | Shorthands for defining routes (`server.get(...)`). |
//! | [`ServeStatic`] | Serve static files from a dir. |
//! | [`SyncRoute`] | Lets you make routes that return responses synchronously. |
//! | [`Trace`] | Add support for the HTTP `TRACE` method. |

pub mod date;
Expand All @@ -26,6 +27,7 @@ pub mod redirect;
pub mod request_id;
pub mod route_shorthands;
pub mod serve_static;
pub mod sync_route;
pub mod trace;

#[doc(inline)]
Expand All @@ -40,5 +42,6 @@ pub use self::{
request_id::RequestId,
route_shorthands::RouteShorthands,
serve_static::ServeStatic,
sync_route::SyncRoute,
trace::Trace,
};
48 changes: 48 additions & 0 deletions lib/extensions/sync_route.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
//! Lets you make routes that return responses synchronously.
//! This is similar to how routes used to work in pre 3.0.0 versions of afire.

use crate::{error::AnyResult, route::Route, trace::emoji, Context, Method, Response, Server};

/// Lets you make routes that return responses synchronously.
pub trait SyncRoute<State> {
/// Creates a new route on the server.
/// Unlike [`Server::route`], you send your response by returning a Result<Response, Error> from your handler.
/// Because of this, you should refrain from using [`Context::send`] in your handler as it will throw an error when trying to send a response twice.]
///
/// Refer to the [`Server::route`] docs for more information on making routes.
///
/// ## Example
/// ```rust
/// # use afire::{Server, AnyResult, Context, Response, Method};
/// # fn test(server: &mut Server<()>) {
/// server.sync_route(Method::GET, "/hello/{name}", |ctx| {
/// let name = ctx.param("name");
/// Ok(Response::new().text(format!("Hello, {name}!")))
/// });
/// # }
/// ```
fn sync_route(
&mut self,
method: Method,
path: impl AsRef<str>,
handler: impl Fn(&Context<State>) -> AnyResult<Response> + Send + Sync + 'static,
) -> &mut Self;
}

impl<State: Send + Sync> SyncRoute<State> for Server<State> {
fn sync_route(
&mut self,
method: Method,
path: impl AsRef<str>,
handler: impl Fn(&Context<State>) -> AnyResult<Response> + Send + Sync + 'static,
) -> &mut Self {
trace!("{}Adding Route {} {}", emoji("🚗"), method, path.as_ref());

let handler = move |ctx: &Context<State>| Ok(ctx.with_response(handler(ctx)?).send()?);

self.routes.push(
Route::new(method, path.as_ref(), Box::new(handler)).expect("Error creating route."),
);
self
}
}
10 changes: 4 additions & 6 deletions lib/route.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,25 +227,23 @@ impl<T> AdditionalRouteContext<T> for Result<T, RouteError> {

impl<T> AdditionalRouteContext<T> for Result<T, Box<dyn Error>> {
fn status(self, status: Status) -> Result<T, RouteError> {
self.map_err(|e| RouteError::from_error(e)).status(status)
self.map_err(RouteError::from_error).status(status)
}

fn with_status(self, status: impl Fn() -> Status) -> Result<T, RouteError> {
self.map_err(|e| RouteError::from_error(e))
.with_status(status)
self.map_err(RouteError::from_error).with_status(status)
}

fn header(self, name: impl Into<HeaderName>, value: impl AsRef<str>) -> Result<T, RouteError> {
self.map_err(|e| RouteError::from_error(e))
.header(name, value)
self.map_err(RouteError::from_error).header(name, value)
}

fn with_header(
self,
name: impl Into<HeaderName>,
value: impl Fn() -> String,
) -> Result<T, RouteError> {
self.map_err(|e| RouteError::from_error(e))
self.map_err(RouteError::from_error)
.with_header(name, value)
}
}
Expand Down

0 comments on commit 31a5fdf

Please sign in to comment.