Rails 3 passing parameters between non-secure and secure pages - ruby-on-rails

This seems like a pretty straight-forward question, but Google is failing me.
My currently all-SSL site needs to be only partially secure (it's not search engine friendly otherwise). But while I want my home page to be unsecure, there's a form on that page that does go to a secure page. As things stand, any form parameters going to a secure site are lost, causing the usual mayhem.
What is the best practice for this situation? In terms of my setup, I'm using rack-ssl-enforcer gem for Rails 3 (works beauty, btw). But these secure and non-secure pages need to co-exist somehow.
Thanks!
Aaron

not sure i get the point, but why don't you use the :except or :only option:
config.middleware.use Rack::SslEnforcer, :only => /^\/admin\//
config.middleware.use Rack::SslEnforcer, :except => /^\/home\//
Then, use the :protocol option for your form, e.g.
# PagesController#home
%h1 Home
= render 'comments/form'
# CommentsController#_form
= form_for #comment, :url => comments_path, :protocol => https
...
That should do the trick...

Related

Handling mix of HTTP and HTTPS links on a page

My setup: Rails 3.0.9, Ruby 1.9.2
My app requires that only a certain part of my site be SSL protected and the rest not. In case anyone thinks this isn't normal behavior, check out Amazon. When merely browsing for products, it's in HTTP mode, during checkout, it switches to HTTPS. Even in the middle of a secure checkout transaction, there are several other links on the same page that are HTTP only.
I looked at ssl_requirement gem and decided not to use it because it isn't a complete solution for my needs. I ended up setting up specific SSL routes like
resources :projects do
resources :tasks, :constraints => { :protocol => "https" }
end
In my view code, for HTTP specific links
<%= link_to 'Projects', project_url(#project, :protocol => "http") %>
and to handle HTTPS specific link
<%= link_to 'Task', new_project_task_url(#project, :protocol => "https") %>
I understand this isn't the cleanest way but it's what I have decided to do. The problem with this setup is how to properly set both HTTP and HTTPS links on every page. There is a proposed solution here but it requires wholesale changes _path to _url and I prefer to avoid that if at all possible. The solutions involves adding this method in
application_helper.rb
module ApplicationHelper
def url_for(options = nil)
if Hash === options
options[:protocol] ||= 'http'
end
super(options)
end
end
So my question is it possible to change this method or another one to change _path calls to explicit urls so I can use the above method to set the proper protocol.
you could try this, although I'm not 100% sure it works:
Use the proposed changes from the stackoverflow answer
Add this to application_controll.rb:
class ApplicationController < ActionController::Base
def url_options
{ :host => request.host }.merge(super)
end
end
According to the Docs it should add the full url even if you use _path:
:only_path - If true, returns the relative URL (omitting the protocol,
host name, and port) (true by default unless :host is specified).
My app requires that only a certain part of my site be SSL protected and the rest not.
That's your faulty assumption. The secure premise is that if some of your app requires SSL, then all of your app requires SSL. The correct assumption then is that your entire app requires SSL.
If your app requires SSL, then you should use something simple like rack-ssl which sets the HSTS header and enforces the secure flag on cookies in all responses.

Getting Rails URL helpers to automatically output https urls

I am developing a site that mixes http and https a lot - whats the best/easiest way to make the links use the right protocol for the route - can it be specified in the routes file?
Say I have the following route in Rails 3.
match "/test" => "test#index", :as => :test, :constraints => { :protocol => 'https' }
If I'm on a http page, and I use test_url(), it'll output http://domain.com/test. I want https://domain.com/test instead.
I know I can use test_url(:secure => true), but that's duplicating logic.
I know I could have http://domain.com/test to https://domain.com/test, but that's an extra redirect, plus it fails on form posts.
Ideas?
Use test_url(:protocol => 'https') for https urls.
Haven't tried but add this in your ApplicationController:
def default_url_options(options={})
{ :secure => true }
end
def default_url_options(options={})
{ :protocol => "https" }
end
For Rails 3.2 I used a combination of #apneadiving's answer. Adding the below code to my ApplicationController
def default_url_options(options={})
options.merge{ :protocol => "https" }
end
It looks like this will be solved in Rails 4! https://github.com/rails/rails/commit/9b4514c3b8ecfbc40a44dbd4c2ebd4ce67f4a459
Rails 3 SSL routing redirects from https to http answers this question pretty well. In short, there's not a great way to do it. I submitted the following Rails bug: https://github.com/rails/rails/issues/3571
To generate https url, add an option called protocol with value https
test_url(protocol: 'https')
You can use a plugin called ss_requirement, it will provide you with methods like
ssl_required
ssl_allowed
You can simply add this in your controller to enable ot disable https on any action
ssl_allowed :login, :update_profile
https://github.com/rails/ssl_requirement

Static pages in Ruby on Rails

What are the standard way of making a Ruby on Rails application that will have pages such as
Home
About
Contact
I would appricate if someone had links or an answers rather than just say use a gem because I want to learn how to make simple webapps with such behavior.
Depends on how you want to handle the content in those pages.
Approach #1 - store content in views
If you just want to put all your content in ERB views, then a very simple approach is to create a PagesController whose purpose is to deal with static pages. Each page is represented by one action in the controller.
pages_controller.rb:
class PagesController < ApplicationController
def home
end
def about
end
def contact
end
end
routes.rb:
match '/home' => 'pages#home'
match '/about' => 'pages#about'
match '/contact' => 'pages#contact'
Then create home.html.erb, about.html.erb, and contact.html.erb views under app/views/pages. These views contain whatever content you want on your static pages. They'll by default use your app's application.html.erb layout.
You'll also want to look into page caching to give yourself a boost in performance.
Approach #2 - store content in database
Another approach I've used is to make a very basic CMS for static pages. In this case, pages are represented in the model. It uses the friendly_id gem to handle slugs for each page so that they can be retrieved by a pretty name in the URL (e.g., /about) rather than by ID.
page.rb:
class Page < ActiveRecord::Base
attr_accessible :title, :content
validates_presence_of :title, :content
has_friendly_id :title, :use_slug => true, :approximate_ascii => true
end
pages_controller.rb:
class PagesController < ApplicationController
def show
#page = Page.find(params[:id])
render 'shared/404', :status => 404 if #page.nil?
end
end
show.html.erb:
<%= raw #page.content %>
routes.rb:
match '/:id' => 'pages#show'
Note: put this entry at the end of routes.rb since it matches everything.
Then how you want to create, edit and update pages are up to you - you can have an admin interface, or build it in to your public interface somehow. This approach can benefit from page caching too.
Another option is the high_voltage gem: https://github.com/thoughtbot/high_voltage
This makes it super easy to create static pages where the content is stored in views.
Jeff's approach #1 (storing content in views and having a route and controller action for each static page) is a good one. The only thing I would add is to use the controller macro in your routes.
So, instead of this:
match '/home' => 'pages#home'
match '/about' => 'pages#about'
match '/contact' => 'pages#contact'
You can do this:
controller :pages do
get :home
get :about
get :contact
end
It's two extra lines, yet much so much more elegant, since it eliminates repetition and groups your static page routes together visually.
It also uses the get http verb method instead of match, which is a better practice for Rails routes (and more concise, now that Rails 4 requires the http verb to be specified when using match.
Jeff's Approach #1 works great for me. Here is a trick to make the controller dynamically look up pages. With this, you don't need to touch the controller nor the routes.rb for adding pages. Just drop the pages under app/views/pages and the controller will find it.
class PagesController < ApplicationController
def show
render params[:id]
end
end
Check out Michael Hartl's http://railstutorial.org
which comes in a 2.3.8 and 3.0.x version. It covers this with great examples and leads you through building them very early on and you will also have the opportunity to learn a lot more than this example.
I highly recommend it.
config/routes.rb
get ':id', to: 'pages#show'
app/controllers/pages_controller.rb
class PagesController < ApplicationController
def show
begin
render params[:id]
rescue ActionView::MissingTemplate
render :file => "#{Rails.root}/public/404", :layout => false, :status => :not_found
end
end
end
Then place your static pages in app/views/pages/{name}.html.erb (or whatever template format.)
An adequate answer to your question would basically look like an introduction to the Rails framework: the MVC structure, templating, and routing DSL at least. Jeff has given a good stab, but his answer still assumes a lot of basic Rails knowledge on your part.
I'd suggest though, that if your webapp is really that simple, Rails might be overkill. I'd look into something lighter, like Sinatra, which has a much lower learning curve than Rails and does a great job of this kind of thing without having to deal with complex routing, magic MVC action/template mapping, etc.
I'd suggest adding your pages in the public folder so as to be served directly without having to pass through rails at all. I'm not an expert though so I'm not sure if this could have any cons if the page is static.
For more you can create static pages using Jekyll bootstrap or also Jekyll using Danger blog
Refer it is very helpful.

Is it possible to use rack-rewrite for rewriting just POST requests?

That's it. I need to redirect just the POST requests. Something like:
rewrite /.*/, '/universal_POST_handler', :if => (something_cool_goes_here)
Is it possible?
The purpose of a rewriter in an application that has routing is to rewrite legacy URLs to more current URLs. Legacy URLs are URLs that were supported and that external users have come to depend on but that are no longer supported because the architecture of the application has changed.
You should use the router instead.
post '*path' => 'actions#universal',
:constraints => FancyConstraint.new
From the README:
Using the :method option you can restrict the matching of a rule by the HTTP method of a given request.
redirect GETs one way
r301 "/players", "/current_players", :method => :get
and redirect POSTs another way
r302 "/players", "/no_longer_available.html?message=No&longer&supported", :method => :post

Modifying rails route helper

I'd like to modify the behavior of the rails route helper *_url for a single route/page.
Here's what I'm try to do:
User visits:
http://test1.myapp.com/account
All the *_url routing helpers resolve to http://test1.myapp.com/ as normal.
But, then if the user goes to https://myapp.heroku.com/account/billing?id=test1
I'd like all the *_url routing helpers on that page to resolve to: http://test1.myapp.com/
instead of http://myapp.heroku.com/
So, is it possible to change the domain bit for all the *_url helper calls for a specific page?
For those interested, I'm trying to use heroku's piggyback ssl method for my app for just a secured billing page.
You can actually just modify the links that point to the billing area:
<%= link_to "Billing", my_helper_url(test1, :host => "myapp.heroku.com", :protocol => "https") %>

Resources