How to modify base path in Plack::Builder

57 views
Skip to first unread message

Mikolaj Kucharski

unread,
Oct 31, 2011, 1:13:33 PM10/31/11
to psgi-...@googlegroups.com
Hi,

I've setup mod_proxy in Apache to plackup as follows:


<IfModule mod_proxy.c>
ProxyRequests Off
ProxyPass /plackup http://localhost:3501/plackup
ProxyPassReverse /plackup http://localhost:3501/plackup
</IfModule>

env -i plackup -L Shotgun -l 127.0.0.1:3501 -a /var/www/conf/pl.revproxy

#!/usr/bin/perl

use warnings;
use strict;

use Plack::App::PSGIBin;
use Plack::Middleware::ReverseProxy;
use Plack::Middleware::Conditional;
use Plack::Builder;

my $app = Plack::App::PSGIBin->new(root => '/var/www/psgi-bin')->to_app;

builder {
mount '/plackup' => builder {
enable_if { $_[0]->{REMOTE_ADDR} eq '127.0.0.1' }
"Plack::Middleware::ReverseProxy";
$app;
}
};

But I was wondering can I set in httpd.conf proxy url as

http://localhost:3501/

and modify base path of all requests in Plack::Builder somehow?


--
best regards
q#

Zbigniew Łukasiak

unread,
Oct 31, 2011, 1:30:12 PM10/31/11
to psgi-...@googlegroups.com

I am not sure if I understand what you need - but

mount '/' => builder {

would mount the service at root.


--
Zbigniew Lukasiak
http://brudnopis.blogspot.com/
http://perlalchemy.blogspot.com/

Mikolaj Kucharski

unread,
Oct 31, 2011, 1:43:58 PM10/31/11
to psgi-...@googlegroups.com
On Mon, Oct 31, 2011 at 06:30:12PM +0100, Zbigniew �ukasiak wrote:
> I am not sure if I understand what you need - but
>
> mount '/' => builder {
>
> would mount the service at root.

Correct, but because all requests come from /plackup on Apache, $app
needs to know that's the real base path and not "/".

Basically URLs in the app will be wrong and whatever you click you'll get
404s.

--
best regards
q#

Tatsuhiko Miyagawa

unread,
Oct 31, 2011, 2:06:50 PM10/31/11
to psgi-...@googlegroups.com
I don't understand your need - yes you can change the proxypass to
localhost:3501/ instead, but then when you construct links in your
application you have to be aware that the frontend URL is /plackup,
not /. You can achieve that by writing a (possibly inline) piece of
middleware that sets $env->{SCRIPT_NAME} to '/plackup'.

--
Tatsuhiko Miyagawa

Zbigniew Łukasiak

unread,
Oct 31, 2011, 2:07:52 PM10/31/11
to psgi-...@googlegroups.com
2011/10/31 Mikolaj Kucharski <mik...@kucharski.name>:

> On Mon, Oct 31, 2011 at 06:30:12PM +0100, Zbigniew Łukasiak wrote:
>> I am not sure if I understand what you need - but
>>
>>  mount '/' => builder {
>>
>> would mount the service at root.
>
> Correct, but because all requests come from /plackup on Apache, $app
> needs to know that's the real base path and not "/".
>
> Basically URLs in the app will be wrong and whatever you click you'll get
> 404s.

Aha - so what you want is:

ProxyPass /plackup http://localhost:3501/

then

mount '/' => builder {

and PATH_INFO shortened by /plackup?

Maybe you could do something like:

my $app = Plack::App::PSGIBin->new(root => '/var/www/psgi-bin')->to_app;

$app = sub {
my $env = shift;
$env->{PATH_INFO} =~ s{^/plackup}{};
return $app->( $env );

Mikolaj Kucharski

unread,
Oct 31, 2011, 3:44:35 PM10/31/11
to psgi-...@googlegroups.com
On Mon, Oct 31, 2011 at 11:06:50AM -0700, Tatsuhiko Miyagawa wrote:
> I don't understand your need - yes you can change the proxypass to
> localhost:3501/ instead, but then when you construct links in your
> application you have to be aware that the frontend URL is /plackup,
> not /. You can achieve that by writing a (possibly inline) piece of
> middleware that sets $env->{SCRIPT_NAME} to '/plackup'.

Yes, this is exactly what I need. Should I also modify REQUEST_URI?


package Plack::Middleware::FrontendPrefix;
use warnings;
use strict;
use parent qw(Plack::Middleware);

sub call {
my ($self, $env) = @_;

my $prefix = '/plackup';

$env->{REQUEST_URI} =~ s|^|$prefix|;
$env->{SCRIPT_NAME} =~ s|^|$prefix|;

$self->app->($env);
}

1;


--
best regards
q#

Mikolaj Kucharski

unread,
Oct 31, 2011, 3:48:25 PM10/31/11
to psgi-...@googlegroups.com
On Mon, Oct 31, 2011 at 07:07:52PM +0100, Zbigniew �ukasiak wrote:
> $env->{PATH_INFO} =~ s{^/plackup}{};

It's actually other way around s|^|/plackup| as Apache removes the
prefix and I want to add it back.

Also, AFAICS and what Tatsuhiko pointed out in other email I should
modify SCRIPT_NAME and (maybe) REQUEST_URI.

--
best regards
q#

Zbigniew Łukasiak

unread,
Nov 1, 2011, 5:24:05 AM11/1/11
to psgi-...@googlegroups.com
2011/10/31 Mikolaj Kucharski <mik...@kucharski.name>:

> On Mon, Oct 31, 2011 at 07:07:52PM +0100, Zbigniew Łukasiak wrote:
>>     $env->{PATH_INFO} =~ s{^/plackup}{};
>
> It's actually other way around s|^|/plackup| as Apache removes the
> prefix and I want to add it back.
>
> Also, AFAICS and what Tatsuhiko pointed out in other email I should
> modify SCRIPT_NAME and (maybe) REQUEST_URI.
>

Isn't it dual? Shouldn't it be that

REQUEST_URI == SCRIPT_NAME . PATH_INFO

and that if you add something to SCRIPT_NAME - then you you also need
to remove it from PATH_INFO? Or I guess you can add to REQUEST_URI -
but REQUEST_URI is usually the most reliable.

Tatsuhiko Miyagawa

unread,
Nov 1, 2011, 5:31:47 AM11/1/11
to psgi-...@googlegroups.com
2011/11/1 Zbigniew Łukasiak <zzb...@gmail.com>:

> Isn't it dual?  Shouldn't it be that
>
> REQUEST_URI == SCRIPT_NAME . PATH_INFO
>
> and that if you add something to SCRIPT_NAME - then you you also need
> to remove it from PATH_INFO?

Not in this case since mod_proxy will modify the internal path when
proxying to the backend.


--
Tatsuhiko Miyagawa

Tatsuhiko Miyagawa

unread,
Nov 1, 2011, 5:33:55 AM11/1/11
to psgi-...@googlegroups.com
On Mon, Oct 31, 2011 at 12:44 PM, Mikolaj Kucharski
<mik...@kucharski.name> wrote:
> On Mon, Oct 31, 2011 at 11:06:50AM -0700, Tatsuhiko Miyagawa wrote:
>> I don't understand your need - yes you can change the proxypass to
>> localhost:3501/ instead, but then when you construct links in your
>> application you have to be aware that the frontend URL is /plackup,
>> not /. You can achieve that by writing a (possibly inline) piece of
>> middleware that sets $env->{SCRIPT_NAME} to '/plackup'.
>
> Yes, this is exactly what I need. Should I also modify REQUEST_URI?

It depends what you want to do with REQUEST_URI, but most of the time
it is best to keep the REQUEST_URI intact.

Also, back to the original question, I still don't see why you want to
do this. With mount DSL you'll get automatically "fixed" SCRIPT_NAME
for you and your script needs no change. Changing different base paths
in front and backend tends to cause more troubles.

> package Plack::Middleware::FrontendPrefix;
> use warnings;
> use strict;
> use parent qw(Plack::Middleware);
>
> sub call {
>        my ($self, $env) = @_;
>
>        my $prefix = '/plackup';
>
>        $env->{REQUEST_URI} =~ s|^|$prefix|;
>        $env->{SCRIPT_NAME} =~ s|^|$prefix|;
>
>        $self->app->($env);
> }
>
> 1;
>
>
> --
> best regards
> q#
>

--
Tatsuhiko Miyagawa

Mikolaj Kucharski

unread,
Nov 1, 2011, 4:26:19 PM11/1/11
to psgi-...@googlegroups.com
On Tue, Nov 01, 2011 at 02:33:55AM -0700, Tatsuhiko Miyagawa wrote:
> On Mon, Oct 31, 2011 at 12:44 PM, Mikolaj Kucharski
> <mik...@kucharski.name> wrote:
> > On Mon, Oct 31, 2011 at 11:06:50AM -0700, Tatsuhiko Miyagawa wrote:
> >> I don't understand your need - yes you can change the proxypass to
> >> localhost:3501/ instead, but then when you construct links in your
> >> application you have to be aware that the frontend URL is /plackup,
> >> not /. You can achieve that by writing a (possibly inline) piece of
> >> middleware that sets $env->{SCRIPT_NAME} to '/plackup'.
> >
> > Yes, this is exactly what I need. Should I also modify REQUEST_URI?
>
> It depends what you want to do with REQUEST_URI, but most of the time
> it is best to keep the REQUEST_URI intact.
>
> Also, back to the original question, I still don't see why you want to
> do this. With mount DSL you'll get automatically "fixed" SCRIPT_NAME
> for you and your script needs no change. Changing different base paths
> in front and backend tends to cause more troubles.

You are correct. I think I'm naturally overcomplicating things during my
learning process. Anyway, I figured out how to modify SCRIPT_NAME or
REQUEST_URI inline and via small middleware module. It was a good lesson
nonetheless.

Thanks again.

--
best regards
q#

Reply all
Reply to author
Forward
0 new messages