perlplackpsgi

How to get information about itself in app.psgi?


Having any PSGI based app, e.g. like the following app.psgi snippet

use 5.016;
use warnings;
use Data::Dumper;

#WHAT TO DO HERE to get the $port?
my $port = $ENV{SERVER_PORT} // "undefined"; 
print STDERR "my port is: $port\n"; #says "undefined"

my $app = sub {
    my $env = shift;
    printf STDERR "Port from the app is: $env->{SERVER_PORT}\n";
    return [
        200,
        ['Content-Type' => 'text/plain'],
        [ "hello world!"],
    ];
};

$app;

How to discover some informations about the runnig server? For example, when run the app.psgi as:

plackup -p 6000

will set & print the $port- 6000.

Inside the $app it is easy, because i have access to the $env. But i want get the $port before the $app is called, e.g. the above example prints the port at every request - but i want get the $port once, before the $app starts running.

EDIT

Yes, I had to be aware of than the server for example could listening on more ports, and the exact port is defined when request is arrived to some port(s).

I want to get the listening port(s).

But based on comment and answer probably here isn't any unified API to different server implementations (Starman, Twiggy) to get the listening port.

The real reason behind the question is that I want to advertise the applications to Bonjour (Zeroconf). (I haven't idea how (yet), but it is necessary to know on which port the application is listening.)

Also now I realised than will be much easier wrap the plackup command itself to some code, for example runserver.pl - and will know the port what I will to use to run the plackup command. ;)


Solution

  • There's no API to get this in the current PSGI spec, by design. As already pointed out, listening port could be multiple ports or even unix sockets. The app doesn't and shouldn't need to know the running environment.

    For your actual motivation, which is to advertise the bind address/port via bonjour:

    a) You could write your boot script and then run the plackup core by using the Plack::Runner module. Actually that's exactly what App::HTTPThis does (it does the bonjour bit as well) https://metacpan.org/release/App-HTTPThis

    b) There's server_ready hook supported in Plack::Runner and some PSGI handlers, which is unfortunately not documented well, which allows you to pass a code reference to get the bind host and port in the startup time.