[Cucumber] ssl requirement


#1

I’m trying to write features for an SSL-only site, but I can’t test
anything because every request in my stories results in a redirect
(the site is set up to redirect non-SSL requests to SSL).

In my specs I hack around this problem with this nasty kludge in my
spec_helper:

module ActionController
class TestRequest
def ssl?
true
end
end
end

But this doesn’t seem to work for Cucumber when I add it to my
features/support/env.rb, as my ssl? override is never called. I guess
either Cucumber doesn’t use ActionController::TestRequest under the
covers, or if it does the real ActionController::TestRequest.ssl?
method is evaluated after and so my override gets overridden itself.

Any ideas for how I can stop the redirects from happening? Evidently
I’ve already tried changing instances of:

get ‘/foo’

To:

get ‘/foo’, :protocol => ‘https’

But, that makes no difference.

Cheers,
Wincent


#2

Wincent C. wrote:

I’m trying to write features for an SSL-only site, but I can’t test
anything because every request in my stories results in a redirect
(the site is set up to redirect non-SSL requests to SSL).

You could consider moving your spec_helper method into a separate
library module, put that in /lib and load it in
config/environments/test.rb. You can also look at:

http://www.subelsky.com/2007/11/testing-rails-ssl-requirements-on-your.html

for ideas, although I do not think that his approach will tie into
cucumber.

Good luck.


#3

Thanks for the reply, James.

El 13/2/2009, a las 16:28, James B. removed_email_address@domain.invalid
escribió:

You could consider moving your spec_helper method into a separate
library module, put that in /lib and load it in
config/environments/test.rb.

Moving the hack from the spec_helper.rb file into a different file
unfortunately doesn’t make it any less of a kludge…

You can also look at:

http://www.subelsky.com/2007/11/testing-rails-ssl-requirements-on-your.html

for ideas, although I do not think that his approach will tie into
cucumber.

That article is about setting up a local Apache instance to proxy to a
local Mongrel instance so that you can connect via HTTPS in local,
manual testing on your development machine. I actually already do that
(although I am using nginx, not Apache), but that really has nothing
to do with RSpec or Cucumber because unless you’re doing in-browser
testing with Selenium or similar you’re not actually making an HTTP/
HTTPS connection at all.

Nevertheless, that article led me to this one:

http://www.ricroberts.com/articles/2008/09/25/setting-up-ssl-for-rails-and-testing-it-locally

Which itself had a hideous suggestion in it that actually works around
my problem. Basically the advice consists of doing something like this
in your “ssl_required?” method in your application_controller.rb:

always return false for tests

return false if RAILS_ENV == ‘test’

I brand this as “hideous” because it commits the heinous crime of
dynamically modifying application behaviour only when execution within
the testing context is detected. Ugh.

For the time being, though, looks like the only way to get my Cucumber
features working. At least until I find out a better way.

Cheers,
Wincent


#4

I have a fix to SslRequirement that allows you to exclude user-
specified domain names. It’s quite likely that you won’t want to use
SSL on some machines when in development. In any case, I have a bear
of a time with the Rails Test::Unit setup so that part’s missing, but
look over:

http://github.com/sxross/ssl_requirement/tree/master

Cheers


#5

El 14/2/2009, a las 21:56, James B. removed_email_address@domain.invalid
escribió:

For the time being, though, looks like the only way to get my
variables. Since you can set these outside your application code then

HTTP_X_FORWARDED_SSL = ?on?

As I wrote, I have not tested any of this.

I haven’t (yet) tested it either, but from looking at the Rails source
code it looks like you could be right. The “ssl?” method is defined in
actionpack/lib/action_controller/request.rb as follows:

 # Is this an SSL request?
 def ssl?
   @env['HTTPS'] == 'on' || @env['HTTP_X_FORWARDED_PROTO'] ==

‘https’
end

That’s in ActionController::Request, which
ActionController::TestRequest inherits from (see vendor/rails/
actionpack/lib/action_controller/test_process.rb). So you would think
that setting the environment variable should indeed work.

Further snooping in the source (actionpack/lib/action_controller/
integration.rb) shows that while using integration tests, at least,
you should also be able to do a “session.https!” to indicate that
you’re simulating an HTTPS request. So in Cucumber stories that should
work too (I gather that Cucumber just wraps Rails’ built-in
integration testing).

[Goes off to test if this actually works…]

Ok, so I tried just sticking an “ENV[‘HTTPS’] = ‘on’” in my spec/
spec_helper.rb file and re-running my spec suite. Looks like this is
not enough in itself, as I got about 77 spec failures, all of them
apparently caused by “ssl?” returning false and producing unwanted
redirects.

It appears that setting ENV in spec/spec_helper.rb has no effect on
the @env instance variable inside ActionController::AbstractRequest.
Setting it “sooner” (ie. from the command line with “HTTPS=on rake
spec”) is evidently not the solution either. I’ll need to pore over
the labyrinthine source code a little more to figure out exactly how
and where @env is getting set up.

Ok… had to dig a little bit outside of Rails, into the Rack gem
installed on the system, to find out where @env is getting set up.
Looks like it’s getting passed in as a parameter to
Rack::Request.initialize, but looks like it’s not coming from the
environment, and the backtrace I get is totally useless (only one
frame in it!). So I guess I’m going to put further investigation on
hold.

Cheers,
Wincent


#6

Wincent C. wrote:

always return false for tests

return false if RAILS_ENV == ‘test’

I brand this as “hideous” because it commits the heinous crime of
dynamically modifying application behaviour only when execution within
the testing context is detected. Ugh.

For the time being, though, looks like the only way to get my Cucumber
features working. At least until I find out a better way.

Cheers,
Wincent

I am reluctant to go forward on this because I have not yet dealt with
this problem first hand. However, I looked into this issue briefly in
the past and it seemed to me that the behaviour you wish to test might
be triggered by setting one or more of the following environment
variables. Since you can set these outside your application code then
this might satisfy your desire to avoid custom test code therein.

It appears that either one of these is sufficient by itself:

HTTPS = ‘on’
HTTP_X_FORWARDED_PROTO = ‘https’

I read somewhere that this one might prove necessary in addition to the
foregoing.

HTTP_X_FORWARDED_SSL = ‘on’

As I wrote, I have not tested any of this.


#7

Ok, so I tried just sticking an “ENV[‘HTTPS’] = ‘on’” in my
spec/spec_helper.rb file and re-running my spec suite. Looks like this is
not enough in itself, as I got about 77 spec failures, all of them
apparently caused by “ssl?” returning false and producing unwanted
redirects.

Rails doesn’t pull the HTTPS from the env, it pulls it from the request
headers. In rails integration tests, you specify those by providing a
third argument for get/post/put/delete:

get :show, { :id => :foobar }, { “HTTPS” => “on” }

… If you’re using webrat, you can just call

header(“HTTPS”, “on”)

and that will, as of 0.4, be sticky through all the redirects and
everything
else your app can throw at it. I’ve been doing this at work for a
while,
and it does work.

http://devcaffeine.com/2009/02/16/integration-testing-ssl-with-cucumber/