hono icon indicating copy to clipboard operation
hono copied to clipboard

Rate-limiting middleware & Helmet

Open ethndotsh opened this issue 2 years ago • 5 comments

Rate-limiting and helmet middlewares would really be the cherries on top in terms of the built-in middleware. It would also be interesting if the rate-limiting middleware could natively support Redis stores for the storage of IP addresses.

ethndotsh avatar Jul 07 '22 02:07 ethndotsh

Rate limiting middleware requires a storage (cloudflare KV, Redis, etc), so middleware's options have to expose the store configuration for customization.

metrue avatar Jul 07 '22 04:07 metrue

For Deno at least, we could use the example provided by oak_rate_limit.

ethndotsh avatar Jul 08 '22 02:07 ethndotsh

How would we get the client IP? Cloudflare is guaranteed to have the CF-Connecting-IP; but what about deno and bun?

Weilbyte avatar Sep 10 '22 11:09 Weilbyte

A simple storage to implement would be in-memory storage, this would work for Cloudflare Workers as well (downsides are that the rate limit will be per-worker and that for long rate-limit windows there is a big chance the worker will be evicted, thus starting from scratch). I'm thinking it would be ideal to implement a couple of basic stores (memory, cloudflare kv, redis) and also let the user specify a custom store by passing their own get and put functions in the config object. Maybe even durable object (might be cheaper than KV)?

What do you think @metrue @yusukebe ?

Weilbyte avatar Sep 10 '22 12:09 Weilbyte

Hi @Weilbyte !

I'm thinking it would be ideal to implement a couple of basic stores (memory, cloudflare kv, redis) and also let the user specify a custom store by passing their own get and put functions in the config object.

This is a very good idea!

Since Hono is used on a variety of platforms, it is great that users can choose their favorite storage options. For Cloudflare Workers, I think Durable Objects is better, but I haven't tried it yet.

yusukebe avatar Sep 12 '22 10:09 yusukebe

Durable objects is definitely better as it is consistent kv is eventually consistent so not idea for rate limiting, especially with short windows.

OultimoCoder avatar Nov 10 '22 12:11 OultimoCoder

@OultimoCoder I see, are there any limitations for DO compared to KV?

Weilbyte avatar Nov 10 '22 12:11 Weilbyte

Max out at 100 requests a second per object but for a rate limiter you should be instantiating 1 object per ip/user and only really limit endpoints that could be abused like email endpoints.

See my implementation here:

https://github.com/OultimoCoder/cloudflare-planetscale-hono-boilerplate

I am using Hono and made a durable objects rate limiter using the sliding window algorithm, mainly taken from:

https://github.com/honzabit/durable-limiter

You coudl easily turn it into a third party middleware in Hono if you wanted but it would only work with Cloudflare because it used durable objects.

OultimoCoder avatar Nov 30 '22 22:11 OultimoCoder

Would love to see this!

JustJoostNL avatar Jan 22 '23 20:01 JustJoostNL

I am currently looking into how to transform node-rate-limiter-flexible for hono as a middleware. node-rate-limiter-flexible

RobertSasak avatar Aug 30 '23 08:08 RobertSasak

That would be cool!

JustJoostNL avatar Aug 30 '23 08:08 JustJoostNL

Here is an example of a middleware wrapping around rate limiter. Please share your thoughts.

import { RateLimiterMemory } from 'rate-limiter-flexible'

const rateLimiter = new RateLimiterMemory({
    points: 100,
    duration: 100,
})

app.use('*', async (c, next) => {
    const ip = c.req.headers.get('x-forwarded-for')
    if (!ip) {
        return next()
    }
    try {
        await rateLimiter.consume(ip)
    } catch (e) {
        return c.text(
            'Too many requests',
            429,
        )
    }
    await next()
})

RobertSasak avatar Aug 30 '23 13:08 RobertSasak

Very nice, how/where are the ip's saved?

JustJoostNL avatar Aug 30 '23 17:08 JustJoostNL

Please refer to the rate limiter documentation to explore all available possibilities. The current one employs the instance's memory.

RobertSasak avatar Aug 30 '23 18:08 RobertSasak

Nice! Any ETA for the package? 😄

JustJoostNL avatar Sep 09 '23 18:09 JustJoostNL

I think there is no need for an extra package and this issue can be closed. Example https://github.com/honojs/hono/issues/346#issuecomment-1699193147 shows how to use any rate limiter.

RobertSasak avatar Sep 10 '23 07:09 RobertSasak

@RobertSasak

Yeah. And now, we have Secure Headers Middleware. Closing now.

yusukebe avatar Nov 14 '23 16:11 yusukebe