Phusion, Rack, Sinatra, and sub-domains
by Ardekantur
I’ve spent the past couple of hours futzing around with Sinatra and Rack being hooked up to the latest Phusion Passenger, and I’ve come across a bizarre problem. Let’s see what I can illustrate.
I have a Slicehost VPS, and I threw a DynDNS address at it because I didn’t feel like registering a domain name for something that was essentially supposed to be a playground. I set it up so that subdomains would also get redirected to my slice, since I didn’t want Phusion interfering with some PHP, Trac, and SVN stuff I also have running on it. My configuration basically looks like this:
/etc/apache2/sites-available/phusion-passenger
<VirtualHost *:80>
ServerAdmin webmaster@localhost
ServerName projects.example.com
DocumentRoot /var/projects
<Directory /var/projects>
Options -Indexes
</Directory>
RackBaseURI /sinatra_test
</VirtualHost>
Then I set up /webapps/sinatra_test, along with the latest version of Sinatra, as outlined on the “Bleeding Edge” section of the Sinatra website. The Phusion Passenger documentation provides instructions on the proper way to format your Rack directories, which includes a tmp directory, a public directory, and a config.ru. Add my actual Sinatra application, and I have a setup that looks like this:
root@slice:/webapps/sinatra_test# ls -l
total 16
-rw-r--r-- 1 www-data www-data 326 Jul 27 15:19 config.ru
-rw-r--r-- 1 www-data www-data 235 Jul 27 15:44 myapp.rb
drwxr-xr-x 2 www-data www-data 4096 Jul 27 05:54 public
lrwxrwxrwx 1 www-data www-data 10 Jul 27 06:13 sinatra -> ../sinatra
drwxr-xr-x 2 www-data www-data 4096 Jul 27 15:46 tmp
All good to go, right? You’d think. There’s some bizarre things going on with Phusion, or Rack, or Sinatra, in terms of discerning correct actions and mapping them to URL endpoints.
My Sinatra application:
myapp.rb
$:.unshift File.dirname(__FILE__) + '/sinatra/lib' require 'sinatra' get '' do "Rootless test" end get '/' do "Root test" end get '/other' do "Other application part" end get '/other/' do "This is a different endpoint" end
As well as the config.ru I’m using for it:
config.ru
$:.unshift File.dirname(__FILE__) + '/sinatra/lib' require 'sinatra' Sinatra::Application.default_options.merge!( :run => false, :env => :development, :raise_errors => true, :app_file => 'myapp.rb' ) log = File.new("sinatra.log", "a") STDOUT.reopen(log) STDERR.reopen(log) require 'myapp' run Sinatra.application
And this is what I get when I play with curl.
~ $ curl http://projects.example.com/sinatra_test/other
Other application part
~ $ curl http://projects.example.com/sinatra_test/other/
This is a different endpoint
~ $ curl http://projects.example.com/sinatra_test
Rootless test
~ $ curl http://projects.example.com/sinatra_test/
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>403 Forbidden</title>
</head><body>
<h1>Forbidden</h1>
<p>You don't have permission to access /sinatra_test/
on this server.</p>
...
What’s going on? other and other/ are considered different endpoints, which makes sense, I imagine. I’m not an HTTP wizard. Even if the root of the sinatra_test directory and the same root with an ending slash are considered different endpoints, then why wouldn’t I be able to access the latter? Especially with it defined explicitly in my Sinatra application? Even more, especially since if this was a distinction, as in the case of other and other/, but isn’t working the same way for the root URL?
Curioser and curioser. I have no idea if the problem is with Sinatra, Rack, Phusion, or my Apache configuration, and I’ve played around with omitting or specifying explicitly an ending forward slash for the DocumentRoot and RackBaseURI. Some of you may point out that I’ve specified -Indexes for the VirtualHost configuration, but if that isn’t specified, then navigating to http://projects.example.com/sinatra_test/ generates an empty directory listing, since it is pointing to my empty public folder.
So that’s where I am. Any insight would be appreciated, but I’ll keep hacking at it.
EDIT Well, there’s some relief for me – disabling mod_autoindex in Apache does the trick. I’m still not sure how I feel about the two endpoints — one with trailing slash and one with — being distinct, but at least there’s a viable solution. If you don’t have a reason to use mod_autoindex, disable it, and it will stop the interference. If you do need it, I’m not entirely sure what you would do.
Comments
/sinatra_test/ (with the trailing slash) is handled by Apache’s directory handler. It’s trying to display a directory index.
I suppose this could be considered a “bug”, but it’s really quite a mess. There are so many combinations of Apache modules, that it’s almost impossible to get everything right. Help/patches will be much appreciated.
I believe the problem you experience only occurs if RailsAllowModRewrite is on.
Hongli -
Thanks for your quick response. I tried explicitly declaring RailsAllodModRewrite off in my VirtualHost configuration, since the documentation implies it’s off by default, but no dice. Clearly it’s some kind of bizarre configuration overlap. I’ll try and see if I can narrow the problem down and provide a test case.
As it turns out, disabling mod_autoindex solves the problem fairly succinctly, but I have no use for autoindex. I have no idea what would be done if someone did need it.
Thank you for this awesome post! I had been trying to figure this out with Camping ever since Phusion put Rack support into Passenger and was too dim to figure out what was going on. Thanks again!
Thanks.
I solved it without disabling mod_autoindex, but by adding a rewrite rule which rewrites the trailing-slash URL to a non-trailing-slash URL (I don’t need these two different endpoints).
Just add these two lines inside your VirtualHost section:
To everyone who stumbles onto this post, I’ve started using a Sinatra before filter I found somewhere to take care of this for me on the application level:
[...] Phusion, Rack, Sinatra, and sub-domains [...]
[...] the information on the main domain and other subdomains anyway, this won't affect most people. …Phusion, Rack, Sinatra, and sub-domains : ArdekanturPhusion, Rack, Sinatra, and sub-domains. by Ardekantur. I've spent the past couple of hours futzing [...]