Passenger + Apache "TraceEnable Off" - ruby-on-rails

We're using Passenger 4.0.59 behind Apache 2.2 (CentOS 6.latest) with Rails 3.2.
In /etc/httpd/conf/httpd.conf we have:
TraceEnable off
We have one virtual host configured in httpd.conf and a second virtual host configured in /etc/httpd/conf.d/ssl.conf that's configured with Passenger.
I'm using commands of this form to test:
curl -I -X {method} https://{host}/{resource}
...and seeing the following behavior:
When I TRACE a static image over http, i.e. http://host.domain.com/images/foo.png, I get a 405 response (as expected).
When I TRACE the same static image over https, meaning it goes through the virtual host configured with Passenger, I get 405 (as expected).
However, when I TRACE a Rails service in our app, e.g. https://host.domain.com/status.json, I get a 200 response w/ valid data.
I would expect Apache to shut down the request and return a 405 response before it even gets to Passenger/Rails, but that isn't happening.
What am I missing / misunderstanding?

What am I missing / misunderstanding?
TraceEnable off is the correct directive to use, but you may have another TraceEnable directive elsewhere in your configs.
You should check all of your apache config files to be sure there is no other TraceEnable directives.
Since the TraceEnable directive can be used within either the server config or the virtual host config, so you may just want to add it to both.

Related

Rails + thin: Not possible to download large files

I have a rails app where users can manage large files (currently up to 15 GB). They have also the possibility to download the stored files.
Everything works perfect for files < 510 MB. But for > 510 MB, the download stops after 522,256 KB (510 MB).
I think thin produces this issue. When I start my dev server using thin, I cannot download the complete file. When I start the dev server using webrick, everything works.
I used top to compare the RAM/CPU behavior, but both server, thin and webrick, behave the same way. In development, both server read the complete file into RAM and then send it to the user/client.
I tried to change some options of send_file like stream, or buffer_size. I also set length manually. But again, I was not able to download the complete file using thin.
I can reproduce this behavior using Firefox, Chrome, and curl.
The problem is that my productive rails app uses 4 thin servers behind an nginx proxy. Currently, I cannot use unicorn, or passenger.
In development, I use thin 1.6.3, rails 4.1.8, ruby 2.1.2.
def download
file_path = '/tmp/big_file.tar.gz' # 5 GB
send_file(file_path, buffer_size: 4096, stream: true)
end
If you are using send_file, it is ideal to use a front end proxy to pass off the responsibility of serving the file. You said you are using nginx in production, so:
In your production.rb file, uncomment config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect'.
You will also have to change your nginx configuration to accommodate Rack::Sendfile. Its documentation is located here. The changes amount to adding:
proxy_set_header X-Sendfile-Type X-Accel-Redirect;
proxy_set_header X-Accel-Mapping /=/files/; # or something similar that doesn't interfere with your routes
to your existing location block and adding an additional location block that handles the X-Accel-Mapping that you added. That new location block might look like:
location ~ /files(.*) {
internal;
alias $1;
}
You will know it is working correctly when you ssh to your production server and curl -I the thin server (not nginx) and see a X-Accel-Redirect header. curl (no -I) directly to the thin server should not send the file contents.
You can see my recent struggle with nginx and send_file here.

Access localhost:3000 through mysite.loc

When I'm on my development laptop, I want to go to the URL "mysite.loc" instead of "localhost:3000" for a particular project. How can I do this?
I am using Ruby on Rails 4, and the default WEBrick server.
I have tried adding "127.0.0.1 mysite.loc" to my /etc/hosts file.
Some people suggest installing Fiddler
Add your local sitename to the HOSTS file then add a custom rule to Fiddler.
static function OnBeforeRequest(oSession: Session) {
if (oSession.host.toLowerCase() == "mysite.loc") {
oSession.host = "mysite.loc:3000";
}
}
Then when you navigate to http://mysite.loc it should be proxied to http://mysite.loc:3000.
Related questions:
ServerFault
StackOverflow
You can add a definition to your /etc/hosts file, but you will still have to use port 3000 in the URL, unless you also change this to the HTTP default (80). You could, if you really wanted, just run on port 80
sudo rails s -p 80
Not that binding to port 80 generally requires su privilege - hence the use of sudo (if available).
If you want to get straight to the desired result, with the assistance of some programming magic there is
http://pow.cx/
It does some local DNS and port magic to let you do what you are wanting.

How to move redmine to a sub-URI with nginx as a proxy

I want to put redmine (listening on localhost:3000 standalone passenger) behind nginx, serving from http://domain.com/redmine with this simple nginx config:
server {
location /redmine/ {
proxy_pass http://domain.com:3000/;
}
}
I rewrote redmine's config/environments.rb based on the instructions from this HOWTO, and redmine properly rewrites static asset URLs, but controller URLS are not rewritten, for ex. settings point to http://domain.com/settings instead of http://domain.com/redmine/settings.
How can I properly configure redmine to run behind nginx?
This is a pretty complicated thing to do. You wouldn't think so but it is. Every single redmine version that comes out has a different set of correct and incorrect ways of accomplishing this. For example, I have a working configuration with (nginx-1.4.1, unicorn, redmine-2.2.1) but now that I'm using (nginx-1.4.2, unicorn, redmine-2.3.3) that doesn't seem to work anymore. Here's some links that may be of use:
http://www.redmine.org/issues/11881
http://www.redmine.org/issues/12102

403 Error after upgrading passenger (for nginx) is keeping me up at night...where did I go wrong?

I think I've read every question and answer on SO related to passenger/nginx and 403 errors, but none have lead me to a solution, so here I go...
I had Nginx (1.0.6) with Passenger (3.0.9) running beautifully for a rails app for many, many months with no real issues. Tonight I decided to upgrade from Passenger v3.0.9 to v3.0.12 to take advantage of a new feature. After running the install according to the provided instructions (using RVM), I went to the URL served by my rails app and got the dreaded 403 error. The nginx log file first had me thinking it was a permissions error:
directory index of "/home/SimfoUsers/public/" is forbidden, client: , server: , request: "GET / HTTP/1.1", host: ""
But after checking every possible permission, I no longer think that is the issue. I think the problem is actually that passenger is somehow not actually running, and the page is being served as a "normal" webpage by nginx. This is supported by the fact that if I add an index.html file to my rails public directory (/home/SimfoUsers/public/), nginx serves up this file as one would expect. Also, if I run passenger-memory-stats, ZERO passenger processes are running. Shouldn't nginx automatically spawn passenger processes whenever needed, or am I completely missing something here?
Here are the relevant parts of my nginx.conf file:
http {
passenger_root /usr/local/rvm/gems/ruby-1.9.2-p290#Simfo/gems/passenger-3.0.12;
passenger_ruby /usr/local/rvm/wrappers/ruby-1.9.2-p290#Simfo/ruby;
...
server {
listen 80;
server_name simfo.info www.simfo.info;
root /home/SimfoUsers/public;
passenger_enabled on;
}
}
Basically the only thing that I changed from my previously working config file is to update the passenger_root and passenger_ruby directives to reflect the new version of passenger (3.0.12). So if this is a config file issue, I'm really at a loss to understand it...
I'm not sure whether to just delete this question, or leave it in case it can save someone else the same frustration. This definitely is a face palm moment...
In desperation, I finally rebooted the server. After that, everything worked fine. It seems that at some point the passenger-related processes died and were not re-spawned automatically. One would think that after a fresh installation and reboot of nginx, passenger would be restarted, but apparentally this is not the case. My only advice to anyone having a similar problem is to issue a ps aux | grep passenger (or tasklist on Windows?). You should see one or two processes related to passenger. If not, then something strange is going on, and a reboot might help you as well.

Why does grails URL params decoding behave differently on server vs. local

Let's say I have the following entry in my grails URLMappings.groovy:
"/actionName/param1"(controller:'myController', action:'myAction')
When I call an URL where param1 includes + as a special character, the URL is encoded correctly to /actionName/my%2Bparam for example, both in my local and in my server environment.
In my local environment - also using "prod" as the environment parameter - this is correctly resolved to my+param in the controller. However in my "real" production environment (Amazon Web Service EC2 instance), the URL is resolved to "my param" which is wrong.
I have no idea what the reason for this could be. Both environments use TomCat, and as stated above I'm even using the prod environment settings in my local environment so it can't be a differing configuration between development and production.
Does anybody have an idea where I could dig deeper to identify the problem?
Is the EC2 instance running Apache in front of Tomcat? I've had issues before with params being decoded twice, once by Apache and then again by Tomcat. From memory, I think I adjusted the configuration of the ProxyPass directive in Apache to correct it.
EDIT:
I found the following instructions I'd left with the source code for my app :)
Apache httpd.conf additions
AllowEncodedSlashes On
ProxyTimeout 3600
We also upgraded apache 2.2.12+ to fix HEAD > GET rewrite bug using a startup shell script.
I also added 'nocanon' option to ProxyPass directive to stop auto decoding by mod_proxy in /etc/httpd/conf.d/cluster.conf
I think I had to do this on the server as you can't modify this using the GUI. I also have a note that says it causes they query string to be encoded. Perhaps I had to add an extra decode in my app to handle this (sorry can't remember for sure!)
Tomcat startup parameters
-Dorg.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true
-Dorg.apache.catalina.connector.CoyoteAdapter.ALLOW_BACKSLASH=true
I think this was to get tomcat to handle slashes correctly
cheers
Lee
That's a known bug that has been introduced in Groovy 1.3.4 or few build versions before. It has been fixed in current version 1.3.5.
this is correctly resolved to my+param
in the controller
No, the expected resolution is "my param" (with a space).
As that works at the Amazon host, you'd upgrade Grails to 1.3.5, locally.

Resources