Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

before filter in sinatra subapplication

I've got a Rails app and a Sinatra app inside it:

routes.rb:

mount MySinatraApp => "/streaming"

sinatra app:

class MySinatraApp< Sinatra::Base
  ...
  before do
    puts 'hello from sinatra!'
  end
  ...
end

I expectedly want the filter to run only on the requests starting with /streaming..., but, what surprises me, the filter runs on every request to the whole Rails app. What can I do with such a behaviour? I can add a regexp filter after before, but I don't think it's a good style.

like image 832
roman-roman Avatar asked Oct 22 '22 19:10

roman-roman


2 Answers

Well, I replaced

mount MySinatraApp => "/streaming"

with

match "/streaming" => SinatraQuoridor, :anchor => false

and filters started to word as expected. Allthough, I do not understand clearly why it is happening: according to this article, mount should just call match with :anchor => false, so the routes should be the same. But the behaviour differs.

like image 164
roman-roman Avatar answered Nov 11 '22 17:11

roman-roman


I'm surprised to see this happen too, but as it has I suppose it tells us that the filters are universal. Since they are, you might try using Sinatra::Namespace from the sinatra-contrib gem, e.g.

require 'sinatra/namespace'

class App < Sinatra::Base
  register Sinatra::Namespace

  namespace "/" do
    before do
      # this will only run within routes marked "/",
      # which should also be prepended with the mounted route, 
      # so "/streaming/"
    end

    get "/?" do
      # something here
    end

  end

I'm not entirely sure this will work, and it may mean that routes must include the trailing slash, so "/streaming/" not "/streaming" (there's surely a workaround) but at least it might solve the problem you have.


Update

I tested the code below and the filters only run for their own app's urls. It appears that even the namespace part isn't needed with this code either. I noticed you've specified the mount method, but that isn't part of Rack - which library are you using for that? rack-mount?

require 'rubygems'
require 'bundler'
Bundler.require

require 'sinatra'
require 'sinatra/namespace'

class StreamingApp < Sinatra::Base
  register Sinatra::Namespace

  namespace "/" do
    before do
      warn "Entering Streaming before filter"
    end

    get "/?" do
      "Hello from the StreamingApp"
    end
  end

  namespace "/something" do
    before do
      warn "Entering Streaming's /something before filter"
      warn "request.path_info = #{request.path_info}"
    end
    get "/?" do
      "Hello from StreamingApp something"
    end
  end
end

class OtherApp < Sinatra::Base
  before do
    warn "Entering OtherApp before filter"
    warn "request.path_info = #{request.path_info}"
  end
  get "/" do
    "Hello from the OtherApp"
  end
end

app = Rack::URLMap.new(
  "/streaming" => StreamingApp,
  "/" => OtherApp 
)

run app

The output:

[2013-01-25 14:19:52] INFO  WEBrick 1.3.1
[2013-01-25 14:19:52] INFO  ruby 1.9.3 (2012-04-20) [x86_64-darwin10.8.0]
[2013-01-25 14:19:52] INFO  WEBrick::HTTPServer#start: pid=78178 port=9292

Entering OtherApp before filter
request.path_info = /
127.0.0.1 - - [25/Jan/2013 14:20:03] "GET / HTTP/1.1" 200 23 0.0201

Entering Streaming before filter
request.path_info = 
127.0.0.1 - - [25/Jan/2013 14:20:11] "GET /streaming HTTP/1.1" 200 27 0.0044

Entering Streaming before filter
request.path_info = /
127.0.0.1 - - [25/Jan/2013 14:20:15] "GET /streaming/ HTTP/1.1" 200 27 0.0016

Entering Streaming before filter
request.path_info = /something
Entering Streaming's /something before filter
request.path_info = /something
127.0.0.1 - - [25/Jan/2013 14:20:21] "GET /streaming/something HTTP/1.1" 200 33 0.0018

Notice how both filters get run in StreamingApp even though the docs for Namespace say that it shouldn't happen. I must've done something wrong there.

like image 21
ian Avatar answered Nov 11 '22 18:11

ian