How do I discover on what server the app.psgi process is running?

317 views Asked by At

Is there a way to discover on what server app.psgi is running?

For example, I am looking for some idea for how to solve the next code fragment from app.psgi:

#app.psgi
use Modern::Perl;
use Plack::Builder;
my $app = sub { ... };

my $server = MyApp::GetServerType(); # <--- I need some idea for how to write this...

given($server) {
    when (/plackup/) { ... do something ... };
    when (/Starman/) { ... do something other ... };
    default { die "Unknown" };
}

$app;

Checking the PLACK_ENV environment variable is not a solution...

1

There are 1 answers

0
benrifkah On BEST ANSWER

Short answer, inspect the caller:

#app.psgi
# use Modern::Perl;
use feature qw(switch say);
use Carp qw(longmess);
use Plack::Builder;

my $app = sub {
    return [ 200, [ 'Content-Type' => 'text/plain' ], [ 'Hello World' ] ];
};

# This hack gets what we need out of the call stack
my $stack = longmess("Stack:");

# say STDERR $stack;

given($stack) {
    when (/plackup/) { say STDERR "Server: plackup" };
    when (/Starman/) { say STDERR "Server: starman" };
    default { die "Server: Unknown" };
}
return $app;

However, doing this in the app.psgi will make your code less portable. If you die on an unknown server people won't be able to run your code in an unknown location.

Also, be aware that this code may be run multiple times depending on how the server is implemented so any side effects may occur multiple times.

For example, here is the output for plackup:

plackup --app /usr/lusers/bburnett/dev/trunk/getserver.psgi
Server: plackup
HTTP::Server::PSGI: Accepting connections at http://0:5000/

So far so good. But here is the output for starman:

starman --app /usr/lusers/bburnett/dev/trunk/getserver.psgi
2014/02/21-16:09:46 Starman::Server (type Net::Server::PreFork) starting! pid(27365)
Resolved [*]:5000 to [0.0.0.0]:5000, IPv4
Binding to TCP port 5000 on host 0.0.0.0 with IPv4
Setting gid to "15 15 0 0 15 20920 20921 20927"
Server: starman
Server: starman
Server: starman
Server: starman
Server: starman

Here it gets run once for the master and once per child (defaults to four children).

If you really want something different to happen for these different servers a more robust way may be to subclass them yourself and put the code into each subclass passing -s My::Starman::Wrapper to plackup and starman as needed.

If you really want a switch statement and to put the code in one place, you could look into writing some code that calls Plack::Loader or Plack::Runner. Take a look at the source for plackup, and you'll see how it wraps Plack::Runner. Take a look at the source for Plack::Loader, and you'll see how it gets the backend to run and then loads the appropriate server class.