-
|
Hello there, First I'd like to thank everyone who worked on rama for their amazing work. It's kind of the perfect project for me both in terms of functionality and programming language! However I have a question regarding dynamic routing. Is there any way to base routing decisions on a signed cookie rama would previously have sent to the user? I had a look at the http_conn_state example and even if it was interesting to improve my rama understanding, I've come to the conclusion that it can't be used to persist state over a larger time span. Any thoughts on this matter? Obviously this is for a http reverse proxy use. I'd like to implement a small service to catch untrusted clients and redirect them to a captcha/proof-of-work page before they can continue further. Sorry if the question has been already asked or is irrelevant to the project, if so feel free to close the topic 😇 |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
|
With rama you should be able to do whatever you want, and what you are asking especially. Rama can work with state, question is mostly where do you want to store it?
Either way the answer would be the same though. Here is a basic architecture on how to add such a middleware (but given it's rama there probably plenty of other ways to do it as well): #[derive(Debug, Clone)]
struct PowRouter<S, P> {
inner: S,
pow: P,
auth: PowAuthorizer,
}
#[derive(Debug, Clone)]
struct PowAuthorizer;
impl PowAuthorizer {
pub fn user_authorized(cookie: &str) -> Result<bool, OpaqueError> {
todo!()
}
}
impl<S, P, State, Body> Service<State, Request<Body>> for PowRouter<S, P>
where
S: Service<State, Request<Body>, Error: Into<BoxError>>,
P: Service<State, Request<Body>, Error: Into<BoxError>>,
State: Clone + Send + Sync + 'static,
Body: Send + Sync + 'static,
{
type Response = S::Response;
type Error = BoxError;
async fn serve(
&self,
ctx: Context<State>,
req: Request<Body>,
) -> Result<Self::Response, Self::Error> {
if let Some(cookie) = req
.headers()
.typed_get::<Cookie>()
.map(|c| c.get("my-auth-cookie"))
{
if self
.auth
.user_authorized(cookie)
.context("user authorization failed")?
{
return self.inner.serve(ctx, req).await.map_err(Into::into);
}
}
self.pow.serve(ctx, req).await.map_err(Into::into)
}
}Your inner service would be the regular flow service that you serve (directly or forwarded) to authorized users. The For now I made an abstract
Anyway, anything is possible and your request is very reasonable. Future rama versions will make that even easier with more rich jwt/cookie support built-in, but don't think that lack of in-depth support for those 2 areas is a true blocker for you here as you can probably do enough what is already there. And what is not there you can for now polly-fill easily yourself or make use of other crates out there in the open. Hope this helps you and good luck! Also feel free to become a sponsor (https://github.com/sponsors/plabayo) as it helps keep this project sustainable and also provide some basic support to users like you. Take care either way. Either way that is how you probably more or less would do it. |
Beta Was this translation helpful? Give feedback.
With rama you should be able to do whatever you want, and what you are asking especially.
Rama can work with state, question is mostly where do you want to store it?
Either way the answer would be the same though.
Here is a basic architecture on how to add such a middleware (but given it's rama there probably plenty of other ways to do it as well):