Coder Social home page Coder Social logo

Comments (8)

welcome avatar welcome commented on September 18, 2024

Thanks for opening your first issue here! 🎉 Be sure to follow the issue template! If you need help or want to chat with us, join us on Discord https://gofiber.io/discord

from fiber.

ReneWerner87 avatar ReneWerner87 commented on September 18, 2024

@zhangyongding can you please describe in more detail what you want to achieve and, if necessary, provide an example

from fiber.

zhangyongding avatar zhangyongding commented on September 18, 2024

add in middleware\limiter\config.go

type Config struct {
	...

	// MaxGenerator allows you to generate custom max, by default nil is used
	//
	// Default: nil
	MaxGenerator func(fiber.Ctx) int

	...
}

or

type Config struct {
	...

	// MaxGenerator allows you to generate custom max, by default nil is used
	//
	// Default: nil
	MaxGenerator func(key string) int
	
	...
}

example: middleware\limiter\limiter_fixed.go

// New creates a new fixed window middleware handler
func (FixedWindow) New(cfg Config) fiber.Handler {
	var (
		// Limiter variables
		mux        = &sync.RWMutex{}
		expiration = uint64(cfg.Expiration.Seconds())
	)

	// Create manager to simplify storage operations ( see manager.go )
	manager := newManager(cfg.Storage)

	// Update timestamp every second
	utils.StartTimeStampUpdater()

	// Return new handler
	return func(c fiber.Ctx) error {
		// Don't execute middleware if Next returns true
		if cfg.Next != nil && cfg.Next(c) {
			return c.Next()
		}

		// Get key from request
		key := cfg.KeyGenerator(c)

		// Get max from request or config
		max := cfg.Max
		if cfg.MaxGenerator != nil {
			max = cfg.MaxGenerator(c) // or max = cfg.MaxGenerator(key)
		}

		if max == 0 {
			return c.Next()
		}

		// Lock entry
		mux.Lock()

		// Get entry from pool and release when finished
		e := manager.get(key)

		// Get timestamp
		ts := uint64(utils.Timestamp())

		// Set expiration if entry does not exist
		if e.exp == 0 {
			e.exp = ts + expiration
		} else if ts >= e.exp {
			// Check if entry is expired
			e.currHits = 0
			e.exp = ts + expiration
		}

		// Increment hits
		e.currHits++

		// Calculate when it resets in seconds
		resetInSec := e.exp - ts

		// Set how many hits we have left
		remaining := max - e.currHits

		// Update storage
		manager.set(key, e, cfg.Expiration)

		// Unlock entry
		mux.Unlock()

		// Check if hits exceed the max
		if remaining < 0 {
			// Return response with Retry-After header
			// https://tools.ietf.org/html/rfc6584
			c.Set(fiber.HeaderRetryAfter, strconv.FormatUint(resetInSec, 10))

			// Call LimitReached handler
			return cfg.LimitReached(c)
		}

		// Continue stack for reaching c.Response().StatusCode()
		// Store err for returning
		err := c.Next()

		// Check for SkipFailedRequests and SkipSuccessfulRequests
		if (cfg.SkipSuccessfulRequests && c.Response().StatusCode() < fiber.StatusBadRequest) ||
			(cfg.SkipFailedRequests && c.Response().StatusCode() >= fiber.StatusBadRequest) {
			// Lock entry
			mux.Lock()
			e = manager.get(key)
			e.currHits--
			remaining++
			manager.set(key, e, cfg.Expiration)
			// Unlock entry
			mux.Unlock()
		}

		// We can continue, update RateLimit headers
		c.Set(xRateLimitLimit, strconv.Itoa(max))
		c.Set(xRateLimitRemaining, strconv.Itoa(remaining))
		c.Set(xRateLimitReset, strconv.FormatUint(resetInSec, 10))

		return err
	}
}

from fiber.

ReneWerner87 avatar ReneWerner87 commented on September 18, 2024

I'm not sure what use case this is intended for
probably for the usecase where you want to manage different accounts with different rate limits

from fiber.

zhangyongding avatar zhangyongding commented on September 18, 2024

Yes, I want to manage different accounts with different rate limits

from fiber.

zhangyongding avatar zhangyongding commented on September 18, 2024

Does v2 accept PR?

from fiber.

ReneWerner87 avatar ReneWerner87 commented on September 18, 2024

Does v2 accept PR?

no, only v3 accept new features

from fiber.

luk3skyw4lker avatar luk3skyw4lker commented on September 18, 2024

@zhangyongding are you working on a PR? If not I could do it and send the PR today still

from fiber.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.