I want to have my API controller use SSL, so I added another listen directive to my nginx.conf
upstream unicorn { server unix:/tmp/unicorn.foo.sock fail_timeout=0; } server { listen 80 default deferred; listen 443 ssl default; ssl_certificate /etc/ssl/certs/foo.crt; ssl_certificate_key /etc/ssl/private/foo.key; server_name foo; root /var/apps/foo/current/public; try_files $uri/system/maintenance.html $uri/index.html $uri @unicorn; location @unicorn { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_redirect off; proxy_pass http://unicorn; } error_page 502 503 /maintenance.html; error_page 500 504 /500.html; keepalive_timeout 5; }
which passes the nginx conftest without any problems. I also added a force_ssl
directive to my ApiController
class ApiController < ApplicationController force_ssl if Rails.env.production? def auth user = User.authenticate(params[:username], params[:password]) respond_to do |format| format.json do if user user.generate_api_key! unless user.api_key.present? render json: { key: user.api_key } else render json: { error: 401 }, status: 401 end end end end def check user = User.find_by_api_key(params[:api_key]) respond_to do |format| format.json do if user render json: { status: 'ok' } else render json: { status: 'failure' }, status: 401 end end end end end
which worked just fine when I wasn't using SSL, but now when I try to curl --LI http://foo/api/auth.json
, I get properly redirected to https
, but then I keep on getting redirected to http://foo/api/auth
ending in an infinite redirect loop.
My routes simply have
get "api/auth" get "api/check"
I'm using Rails 3.2.1 on Ruby 1.9.2 with nginx 0.7.65
You're not forwarding any information about whether this request was an HTTPS-terminated request or not. Normally, in a server, the "ssl on;" directive will set these headers, but you're using a combined block.
Rack (and force_ssl) determines SSL by:
See the force_ssl source for the full story.
Since you're using a combined block, you want to use the third form. Try:
proxy_set_header X-Forwarded-Proto $scheme;
in your server or location block per the nginx documentation.
This will set the header to "http" when you come in on a port 80 request, and set it to "https" when you come in on a 443 request.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With