GitHub - teechap/kitura-limiter: Rate limiting middleware for Kitura

2 min read Original article ↗
import Foundation
import Kitura
import SwiftRedis
import KituraLimiter

let redis = Redis() // remember to make sure a redis instance is running

redis.connect(host: "localhost", port: 6379) { (redisError: NSError?) in
    if let error = redisError {
        print("Could not connect to Redis: \(error)")
    } else {
        print("Redis connected")
        // Create a new router
        let router = Router()

        // By default, Limiter allows 150 requests/hour for each IP address
        router.all(middleware: Limiter(redis: redis))

        // Handle HTTP GET requests to /
        router.get("/") { request, response, next in
            response.send("Hello, World!")
            next()
        }

        // Add an HTTP server and connect it to the router
        Kitura.addHTTPServer(onPort: 8090, with: router)

        // Start the Kitura runloop (this call never returns)
        Kitura.run()
    }
}
func apiToken(request: RouterRequest) -> String {
    // use api token from middleware, cookies, etc.
    return request.userInfo["apiToken"]
}

func isAdmin(request: RouterRequest) -> Bool {
    return request.userInfo["isAdmin"]
}

func onRedisError(request: RouterRequest, response: RouterResponse, next: @escaping NextFunc) throws {
    response.status(HTTPStatusCode.internalServerError).send("This service is awful!")
    try response.end()
}

func onRateLimited(request: RouterRequest, response: RouterResponse, next: @escaping NextFunc) throws {
    response.status(HTTPStatusCode.tooManyRequests).send("I need you to calm down")
    try response.end()
}

router.all(middleware:
    Limiter(
        redis: redis,
        by: apiToken, // limit by api token instead of default ip address
        total: 2, // 2 req/second
        expire: 1000, // 1000 ms
        whitelist: isAdmin, // admin users shouldn't be limited
        ignoreErrors: true, // is rate limiting really *that* important?
        onRedisError: onRedisError, // this is ignored because ignoreErrors is true
        skipHeaders: true, // I don't care if my clients know when they can make more requests!
        onRateLimited: onRateLimited
    )
)