¿Cómo utilizo un middleware rack sólo para ciertos caminos?
-
06-09-2019 - |
Pregunta
Me gustaría tener MyMiddleware
carrera en mi aplicación Rack, pero sólo para ciertos caminos. Tenía la esperanza de utilizar Rack::Builder
o al menos Rack::URLMap
, pero no puedo encontrar la manera.
Esto es lo que pensé que trabajar, pero no:
# in my rackup file or Rails environment.rb:
map '/foo' do
use MyMiddleware, { :some => 'options' }
end
O, mejor aún, con una expresión regular:
map /^foo/ do
use MyMiddleware, { :some => 'options' }
end
Pero map
parece exigir una aplicación en el extremo; no va a caer de nuevo simplemente pasar el control de nuevo a su padre. (El error real es "undefined method 'each' for nil:NilClass
" de cuando estante intenta convertir el final de ese bloque do...end
en un app
.)
¿Hay un middleware por ahí que toma una matriz de middleware y un camino y sólo se ejecuta si ellos coincide con la ruta?
Solución
Usted podría tener MyMiddleware comprobar el camino y no pasar el control a la siguiente pieza de cerámica de media si coincide.
class MyMiddleware
def initialize app
@app = app
end
def call env
middlewary_stuff if env['PATH_INFO'] == '/foo'
@app.call env
end
def middlewary_stuff
#...
end
end
O, usted podría utilizar URLMap w / o la dslness. Se vería algo como esto:
main_app = MainApp.new
Rack::URLMap.new '/'=>main_app, /^(foo|bar)/ => MyMiddleWare.new(main_app)
Otros consejos
Esto no funciona porque @app
no existe en el ámbito derecha:
# in my_app.ru or any Rack::Builder context:
@app = self
map '/foo' do
use MyMiddleware
run lambda { |env| @app.call(env) }
end
Pero esta voluntad:
# in my_app.ru or any Rack::Builder context:
::MAIN_RACK_APP = self
map '/foo' do
use MyMiddleware
run lambda { |env| ::MAIN_RACK_APP.call(env) }
end
Rack::Builder
tiras el primer argumento de map
de la parte frontal de la ruta, por lo que no hace cesar Recurse. Desafortunadamente, esto significa que después de ese prefijo de ruta se elimina, es poco probable que el resto de la ruta coincidirá correctamente otras asignaciones.
Este es un ejemplo:
::MAIN_APP = self
use Rack::ShowExceptions
use Rack::Lint
use Rack::Reloader, 0
use Rack::ContentLength
map '/html' do
use MyContentTypeSettingMiddleware, 'text/html'
run lambda { |env| puts 'HTML!'; ::MAIN_APP.call(env) }
end
map '/xml' do
use MyContentTypeSettingMiddleware, 'application/xml'
run lambda { |env| puts 'XML!'; ::MAIN_APP.call(env) }
end
map '/' do
use ContentType, 'text/plain'
run lambda { |env| [ 200, {}, "<p>Hello!</p>" ] }
end
El ir a /html/xml
hace que el siguiente ir al registro:
HTML!
XML!
127.0.0.1 - - [28/May/2009 17:41:42] "GET /html/xml HTTP/1.1" 200 13 0.3626
Es decir, la aplicación asignada a '/html'
tiras de '/html'
el prefijo y la llamada ahora coincide con la aplicación asignada a '/xml'
.