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