Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add type map http::Extensions to Request and MethodResponse types #1305

Closed
Tracked by #1292
niklasad1 opened this issue Feb 29, 2024 · 0 comments · Fixed by #1306
Closed
Tracked by #1292

add type map http::Extensions to Request and MethodResponse types #1305

niklasad1 opened this issue Feb 29, 2024 · 0 comments · Fixed by #1306

Comments

@niklasad1
Copy link
Member

niklasad1 commented Feb 29, 2024

After trying to "share state" between different layers of the middleware in jsonrpsee, which is hard to
do properly.

One possibility is to inject a shared state such as Arc<Mutex<HashSet<(RequestId, MethodName, Params)>>> but it's not a good solution because the RequestId isn't necessarily unique, and it's possible that an identical RPC call may overwrite a pending call or something similar.

For instance, my own use case is that I would want to know whether a call was rate-limited or not, which was controlled by another middleware layer.

A good solution is to copy what hyper/http has for the Request/Response in the http::Extensions API so that one could just inject custom data in there, as in the following example:

impl<'a, S> RpcServiceT<'a> for Metrics<S>
where
    S: Send + RpcServiceT<'a>,
{
    type Future = BoxFuture<'a, MethodResponse>;

    fn call(&self, req: Request<'a>) -> Self::Future {
        if self.is_rate_limited() {
            req.extensions_mut().insert("rate_limited", true);
        }

        let rp = self.service.call(req);

        if rp.extensions.get("rate_limited").is_some() {
            update_metrics(true);
        } else {
            update_metrics(false);
        }
    }
}

impl<'a, S> RpcServiceT<'a> for RateLimit<S>
where
    S: Send + RpcServiceT<'a>,
{
    type Future = BoxFuture<'a, MethodResponse>;

    fn call(&self, req: Request<'a>) -> Self::Future {
        if self.guard.check() {
            req.extensions_mut().insert("rate_limited", true);
            wait_until_ready();
        }

        self.service.call(req)
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant