Forum: RSpec [Cucumber] ssl requirement

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Wincent C. (Guest)
on 2009-02-13 15:46
(Received via mailing list)
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
James B. (Guest)
on 2009-02-13 17:20
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-...

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

Good luck.
Wincent C. (Guest)
on 2009-02-14 12:19
(Received via mailing list)
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-...
>
> 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/sett...

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
James B. (Guest)
on 2009-02-14 18:05
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.
Steve R. (Guest)
on 2009-02-15 04:27
(Received via mailing list)
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
Wincent C. (Guest)
on 2009-02-16 10:54
(Received via mailing list)
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
Chris F. (Guest)
on 2009-02-17 16:14
(Received via mailing list)
>
> 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-test...
This topic is locked and can not be replied to.