Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

Re^2: Dancer2 App Deployment through Apache Proxy

by choroba (Cardinal)
on May 21, 2025 at 12:50 UTC ( [id://11165070]=note: print w/replies, xml ) Need Help??


in reply to Re: Dancer2 App Deployment through Apache Proxy
in thread Dancer2 App Deployment through Apache Proxy

Thank you and all others who helped me. I had a conversation with brtastic on Perl Applications and Algorithms Discord, he first recommended trying Plack::Middleware::ReverseProxy, but it didn't solve everything, so I wrote my own middleware like this:
package Plack::Middleware::Proxy; use warnings; use strict; use parent 'Plack::Middleware'; use Plack::Util::Accessor qw( prefix scheme ); sub call { my ($self, $env) = @_; if ($env->{REMOTE_ADDR} ne '127.0.0.1') { $env->{SCRIPT_NAME} = $self->prefix; $env->{HTTP_X_FORWARDED_PROTO} = $self->scheme; } my $res = $self->app->($env); return Plack::Util::response_cb($res, sub { my $res = shift; if ($res->[0] == 302) { my %header = @{ $res->[1] }; my $prefix = $self->prefix; $header{Location} =~ s{^\Q$prefix/}{/$prefix/}; @{ $res->[1] } = %header; } return }); return $res } __PACKAGE__

It sovles several problems at once:

  1. It fixes links like /login to include the prefix when rendered through the proxy. All such links must have the form <% response.uri_base %>/path in the template files.
  2. On the VM, the server runs on http, but it's only accessible from the outside world through https (the proxy redirects http to https). Some links kept the http scheme, this fixes the behaviour.
  3. In the code, I have several instances of redirect('/');. For some reason, this lead to errors with the path becoming prefix/prefix, the postprocessing of the response fixes this. I had to use the callback, because the app also streams files, so a simple change to $res would crash the download.

I use it like this:

use Plack::Builder; builder { enable 'Plack::Middleware::Proxy', prefix => 'prefix', scheme => ' +https'; 'MyApp'->to_app; };

So, in the end, I also need to have the prefix in the code, but at least as a parameter to middleware, which seems much nicer.

map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]

Replies are listed 'Best First'.
Re^3: Dancer2 App Deployment through Apache Proxy
by NERDVANA (Priest) on May 21, 2025 at 14:25 UTC
    IMO the "Perfect Solution" is to have the app receive its mount prefix from the reverse proxy, and then you can even mount the app at different host/paths simultaneously. In other words, each request supplies the prefix to be used for that request.

    I don't use Dancer, and I try to avoid Apache, but the checklist looks something like:

    • Check your HTTP headers. The request path should have the prefix removed. There should be another header like X-Forwarded-Prefix (the default in Traefik) that should specify the prefix. If not, fix the config in the reverse proxy.
    • Check your Plack environment. It should have the prefix in SCRIPT_NAME, and not in PATH_INFO. If not, fix your middleware until it does.
    • When generating URLs in templates, always include the prefix, which your framework should provide in some convenient variable. Never include the hostname or protocol. If your framework insists on that, modify it until it doesn't.
    • When returning redirects, find out whether your framework automatically adds the prefix, or if you need to add it manually. Never include the protocol or host name in the redirect URL (even though that's mandated by the standard) and leave that task to your reverse proxy. (path-only 3xx locations work in every browser since forever, and proxies will usually rewrite them to full URLs for you anyway)

    There are many ways to do it of course, including Apache mod_proxy_html that can rewrite your html output to modify the generated URLs, but this just leads to frustration. (If you're not in control of the application, sometimes its the only option, though)

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://11165070]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others taking refuge in the Monastery: (4)
As of 2025-06-19 12:24 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?
    erzuuliAnonymous Monks are no longer allowed to use Super Search, due to an excessive use of this resource by robots.