2012-10-01 17 views
9

¿Es posible activar el middleware Rack solo en rutas Rails específicas?Middleware Trigger Rack en rutas Rails específicas

Por ejemplo, supongamos que quería ejecutar un middleware de limitador de velocidad solo en el espacio de nombres de la API.

namespace :api do 
    resources :users 
end 

Respuesta

15

He tenido buen éxito con Rack::Throttle de limitación de velocidad. Subclase una de las clases de acelerador incorporadas y sobrecargue el método allowed?. Su lógica personalizada puede verificar a qué controlador se accede y aplicar el límite de velocidad según sea necesario.

class ApiThrottle < Rack::Throttle::Hourly 
    ## 
    # Returns `false` if the rate limit has been exceeded for the given 
    # `request`, or `true` otherwise. 
    # 
    # Rate limits are only imposed on the "api" controller 
    # 
    # @param [Rack::Request] request 
    # @return [Boolean] 
    def allowed?(request) 
    path_info = (Rails.application.routes.recognize_path request.url rescue {}) || {} 

    # Check if this route should be rate-limited 
    if path_info[:controller] == "api" 
     super 
    else 
     # other routes are not throttled, so we allow them 
     true 
    end 
    end 
end 
5

Adición de respuesta de Ian, para configurar el ApiThrottle usted tiene que:

# application.rb 
require 'rack/throttle' 
class Application < Rails::Application 
    ... 
    config.require "api_throttle" 
    # max 100 requests per hour per ip 
    config.middleware.use ApiThrottle, :max => 100 
    ... 
end 

# /lib/api_throttle.rb 
# Ian's code here 

Una cosa importante a añadir es que, para mí, la path_info[:controller] llegaron como "api/v1/cities" y no sólo como "api". Por supuesto, eso se debe a la configuración del espacio de nombres. Por lo tanto, tenga cuidado al configurar el estrangulador.

0

También puede usar (ahora) un motor Rails para crear un conjunto aislado de rutas que agrega middleware adicional a la pila para sus rutas montadas.

Ver https://stackoverflow.com/a/41515577/79079

(Por desgracia me encontré con esta pregunta mientras mira para ver si había alguna forma más simple de hacerlo. Escribir un middleware personalizado para cada middleware que quería añadir parece aún más rotonda de utilizar a Rails :: Engine)

Cuestiones relacionadas