Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to force $c->uri_for in Catalyst to generate a URI that begins with https?

Tags:

perl

catalyst

I've written a web application using Catalyst that has a lot of forms and needs to run over https. There are no hard-coded URLs, everything uses $c->uri_for or $c->req->uri. Everything worked great in the development environment using the dev server running over http.

Today, when I went ahead and deployed the application, I noticed a problem. The way our production environment is currently setup, client browsers talk to a F5 load-balancer over HTTPS and the F5 talks to the web server on the internal network over HTTP.

[ Browser ] ---HTTPS---> [ F5 ] ---HTTP---> [ Web Server ]

Now, because the web server only gets HTTP requests, all URIs are generated starting with HTTP. This means:

<form action='[% c.uri_for('/secure/form') %]' method='post'>

becomes:

<form action='http://websitename.org/secure/form' method='post'>

and now all browsers complain you are submitting data over an insecure connection. I need that c.uri_for to begin with https.

The app needed to go live today, so I did a mass search/replace for all form actions to this:

<form action='[% c.uri_for('/secure/form') | replace('http:', 'https:'%]' method='post'>

Well, now that breaks development, so I conditionalized the form actions based on a config key:

[% IF c.config.production %]
  <form action='[% c.uri_for('/secure/form') | replace ('http:', 'https:') %]' method='post'>
[% ELSE %]
  <form action='[% c.uri_for('/secure/form') %]' method='post'>
[% END %]

Needless to say, this all just seems wrong on multiple levels. Anyone have a better idea? And is there a way to force $c->uri_for to generate a URI that begins with https?

Solution

If you're using Catalyst 5.80008 or later, set MyApp->config(using_frontend_proxy => 1); and simply have your proxy set the X-Forwarded-Port header. For Catalyst versions prior to 5.80008, still set using_frontend_proxy so you get the actual client_ip, but to generate the correct URIs have your web server set the environment variable HTTPS to ON

like image 598
mhchaudhry Avatar asked Nov 03 '09 02:11

mhchaudhry


2 Answers

You might try this configuration option:

MyApp->config(using_frontend_proxy => 1);

It's described in Catalyst's documentation

like image 74
zakovyrya Avatar answered Sep 24 '22 23:09

zakovyrya


The following works (tested):

In MyApp.pm, add the following sub:

sub secure_uri_for {
    my ($self, @args) = @_;
    my $u = $self->uri_for(@args);
    $u->scheme('https');
    return $u;
}

Now any time you want a guaranteed https, you can call $c->secure_uri_for('whatever')

like image 26
singingfish Avatar answered Sep 25 '22 23:09

singingfish