mirror of
https://github.com/zerotier/ratpack.git
synced 2026-05-22 16:27:23 -07:00
rewrite ratpack example to be a little easier on the eyes, thanks @antifuchs
Signed-off-by: Erik Hollensbe <linux@hollensbe.org>
This commit is contained in:
+39
-24
@@ -1,16 +1,28 @@
|
||||
use ratpack::prelude::*;
|
||||
|
||||
// We'll use authstate to (optionally) capture information about the token
|
||||
// being correct. if it is Some(true), the user was authed, if None, there was no
|
||||
// authentication performed.
|
||||
#[derive(Clone)]
|
||||
struct AuthedState {
|
||||
authed: Option<bool>,
|
||||
}
|
||||
|
||||
// All transient state structs must have an initial state, which will be
|
||||
// initialized internally in the router.
|
||||
impl TransientState for AuthedState {
|
||||
fn initial() -> Self {
|
||||
Self { authed: None }
|
||||
}
|
||||
}
|
||||
|
||||
// our authtoken validator, this queries the app state and the header
|
||||
// `X-AuthToken` and compares the two. If there are any discrepancies, it
|
||||
// returns `401 Unauthorized`.
|
||||
//
|
||||
// every handler & middleware takes and returns the same params and has the
|
||||
// same prototype.
|
||||
//
|
||||
async fn validate_authtoken(
|
||||
req: Request<Body>,
|
||||
resp: Option<Response<Body>>,
|
||||
@@ -18,24 +30,16 @@ async fn validate_authtoken(
|
||||
app: App<State, AuthedState>,
|
||||
mut authstate: AuthedState,
|
||||
) -> HTTPResult<AuthedState> {
|
||||
let token = req.headers().get("X-AuthToken");
|
||||
if token.is_none() {
|
||||
return Err(Error::StatusCode(StatusCode::UNAUTHORIZED));
|
||||
if let (Some(token), Some(state)) = (req.headers().get("X-AuthToken"), app.state().await) {
|
||||
authstate.authed = Some(state.clone().lock().await.authtoken == token);
|
||||
Ok((req, resp, authstate))
|
||||
} else {
|
||||
Err(Error::StatusCode(StatusCode::UNAUTHORIZED))
|
||||
}
|
||||
|
||||
let token = token.unwrap();
|
||||
|
||||
let state = app.state().await;
|
||||
if state.is_none() {
|
||||
return Err(Error::StatusCode(StatusCode::UNAUTHORIZED));
|
||||
}
|
||||
|
||||
let state = state.unwrap();
|
||||
authstate.authed = Some(state.clone().lock().await.authtoken == token);
|
||||
|
||||
return Ok((req, resp, authstate));
|
||||
}
|
||||
|
||||
// our `hello` responder; it simply echoes the `name` parameter provided in the
|
||||
// route.
|
||||
async fn hello(
|
||||
req: Request<Body>,
|
||||
_resp: Option<Response<Body>>,
|
||||
@@ -43,25 +47,36 @@ async fn hello(
|
||||
_app: App<State, AuthedState>,
|
||||
authstate: AuthedState,
|
||||
) -> HTTPResult<AuthedState> {
|
||||
if authstate.authed.is_some() && !authstate.authed.unwrap() {
|
||||
return Err(Error::StatusCode(StatusCode::UNAUTHORIZED));
|
||||
}
|
||||
|
||||
let name = params.get("name").unwrap();
|
||||
let bytes = Body::from(format!("hello, {}!\n", name));
|
||||
|
||||
return Ok((
|
||||
req,
|
||||
Some(Response::builder().status(200).body(bytes).unwrap()),
|
||||
authstate,
|
||||
));
|
||||
if let Some(authed) = authstate.authed {
|
||||
if authed {
|
||||
return Ok((
|
||||
req,
|
||||
Some(Response::builder().status(200).body(bytes).unwrap()),
|
||||
authstate,
|
||||
));
|
||||
}
|
||||
} else if authstate.authed.is_none() {
|
||||
return Ok((
|
||||
req,
|
||||
Some(Response::builder().status(200).body(bytes).unwrap()),
|
||||
authstate,
|
||||
));
|
||||
}
|
||||
|
||||
Err(Error::StatusCode(StatusCode::UNAUTHORIZED))
|
||||
}
|
||||
|
||||
// Our global application state; must be `Clone`.
|
||||
#[derive(Clone)]
|
||||
struct State {
|
||||
authtoken: &'static str,
|
||||
}
|
||||
|
||||
// ServerError is a catch-all for errors returned by serving content through
|
||||
// ratpack.
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), ServerError> {
|
||||
let mut app = App::with_state(State {
|
||||
|
||||
Reference in New Issue
Block a user