Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight

PSGI, Plack

by McA (Priest)
on Oct 24, 2012 at 11:15 UTC ( #1000606=perlquestion: print w/replies, xml ) Need Help??

McA has asked for the wisdom of the Perl Monks concerning the following question:

Hi all,

I'm pretty new to Plack and PSGI and need your recommendation/advice. I like the possibility to start a development server with using plackup in the foreground. Is there also an easy way to start a server listening on two ports, one with and the other without SSL? Do I have to start two servers? Or is there a PSGI aware server out there which can listen on two ports (SSL/no SSL) for the same app? Probably there is a nice way with Server::Starter.

How do I know which PSGI aware server is SSL enabled? E.g. when I look (perldoc) at HTTP::Server::PSGI there is no information concerning SSL. When you look at the code you can get the idea that this server is SSL capable. (Is starman SSL enabled?)

Best regards

Replies are listed 'Best First'.
Re: PSGI, Plack
by Corion (Patriarch) on Oct 24, 2012 at 11:29 UTC

    I have written a toy "enforce-https" middleware, and also a toy "run two servers" middleware, but not yet released onto CPAN.

    To write a multiplexing server that can serve PSGI applications from two (or more) ports, you will have to look at the various backends. I chose AnyEvent, which is based on the idea of nonblocking handling. The existing implementations on CPAN (partially in Server::Starter I think) didn't work on Windows for me. One ugly part is that SSL does not work well on Windows+Strawberry+AnyEvent, I think because OpenSSL is linked to a different memory allocator than Strawberry Perl.

    I think SSL-enabling a server is basically only the process of "replacing" the socket the server reads from by a socket that knows SSL. AnyEvent did that nicely, but I don't know what other servers/frameworks do.

    Update: Plack::Handler::AnyEvent::HTTPD needs a small patch to allow SSL:

      I found that multi-server implementation. It does not only use AnyEvent, it also relies on Coro to make switching between server loops easy when they get blocked. The code was developed under Windows, but the SSL problems alluded to above still apply.

      #!perl -w use strict; use Coro; use AnyEvent; use AnyEvent::TLS; use Plack::Handler::AnyEvent::HTTPD; use Dancer (); use App::Regexplain; use Data::Dumper; my %config = ( 'http' => { host => '', port => 8080, protocol => 'http', + proto => 'tcp' }, 'https' => { host => '', port => 8443, ssl => { cert_file => 'C:/Projekte/App-Regexplain/certs/testcert.pem', key_file => 'C:/Projekte/App-Regexplain/certs/testkey-nopass.p +em', }, }, ); =begin other_api __PACKAGE__->run( port => [8080, "8443/ssl"], ipv => '*', # IPv6 if available SSL_key_file => '/my/key', SSL_cert_file => '/my/cert', ); =cut for my $serverkey (sort keys %config) { my $config = $config{ $serverkey }; my $runner = Plack::Runner::Multi->new; $runner->parse_options( '--server', 'AnyEvent::HTTPD', '-p', $config->{port}, '-o', $config->{host}, 'bin\\', ); if( $config->{ssl} ) { #$config->{ ssl } = AnyEvent::TLS->new( # %{$config->{ ssl }} #); push @{$runner->{options}}, ssl => $config->{ssl} }; my ($loader,$server,$app) = $runner->psgi_app(); async { $loader->preload_app($app); $loader->run($server); }; }; # Kick off the event loop AnyEvent->condvar->recv; package Plack::Runner::Multi; use strict; use parent 'Plack::Runner'; use Coro; use Data::Dumper; # Paste from Plack::Runner::run except the $loader->run at the end sub psgi_app { my $self = shift; #unless (ref $self) { # $self = $self->new; # $self->parse_options(@_); # return $self->run; #} unless ($self->{options}) { $self->parse_options(@_); }; my @args = @{$self->{argv}}; $self->setup; my $app = $self->locate_app(@args); $ENV{PLACK_ENV} ||= $self->{env} || 'development'; if ($ENV{PLACK_ENV} eq 'development') { $app = $self->prepare_devel($app); } if ($self->{access_log}) { open my $logfh, ">>", $self->{access_log} or die "open($self->{access_log}): $!"; $logfh->autoflush(1); $app = $self->apply_middleware($app, 'AccessLog', logger => su +b { $logfh->print( @_ ) }); } my $loader = $self->loader; #warn "Loading Server with " . Dumper $self->{options}; my $server = $self->load_server($loader); #$loader->preload_app($app); return ($loader, $server, $app); #$loader->run($server); } 1;
Re: PSGI, Plack
by Anonymous Monk on Oct 24, 2012 at 11:45 UTC

      Thank you, Anonymous Monk.

      The last hint was helpful. I'll have a look at Gepok. It seems promising.

      Update: I looked at it and as far as I can see it fulfills exactly what I want for development. Therefor a ++ to our Anonymous Monk.

      Best regards

        I really like Gepok. For Starman etc the advice is to place an HTTPS proxy (e.g. Apache) in front of the server. However, that means that the server misses out on all the transactional information in the HTTPS connection, such as client certificates. Gepok has the HTTPS built in, so you can use HTTPS certificates for authentication.

        perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'
      Actually, it does not matter. HTTP or HTTPS, the underlying protocol is exactly the same. In Apache, a different <virtualHost> definition will correspond to each. What each one of them does, if need be, could be exactly the same. (If the FastCGI servers are static, the traffic from both VHosts could in fact be sent without error to the same pool. So it CAN be done, should you actually want to do it, and the Perl code does not have to know or care.


        but you should not forget that there are circumstances where you want to know whether requests came via https or http. Just two examples:

        • You want to generate absolute URL in the response to reflect the currently used protocol.
        • You want to set the secure attribute on cookies when you know that the response is sent via https.

        Best regards

Re: PSGI, Plack
by sundialsvc4 (Abbot) on Oct 24, 2012 at 12:59 UTC

    So far as I know, once the data gets through the HTTP/HTTPS layer, the FastCGI layer doesn’t care.   But what I have always done is to nevertheless clearly-separate the HTTPS from the HTTP traffic handlers, since one is thought of as secure and the other is not.   I want to keep them at arm’s length and maybe on a different set of servers, due to the classification of the data which each one handles.   Both sets of handlers actually use (or require) duplicate copies of the same code-base, however.

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1000606]
Approved by nemesdani
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others lurking in the Monastery: (3)
As of 2022-01-26 17:03 GMT
Find Nodes?
    Voting Booth?
    In 2022, my preferred method to securely store passwords is:

    Results (69 votes). Check out past polls.