PSGI/Plack sind mir bekannt. Ist jedoch keine Lösung für die beschrieben Mängel an CGI.pm. Außerdem ergeben sich keine Vorteile gegenüber Legacy, wenn die Serverumgebung %ENV, die ein Webserver lt. CGI/1.1 Standard ohnehin anlegen muss, innerhalb von Perl gekapselt wird.
Denn CGI/1.1 umfasst nämlich nicht nur die Serverumgebung sondern auch STDIN/STDOUT und das lässt sich gar nicht kapseln -- auch mit PSGI nicht. PSGI ist ein typisches Beispiel für alten Wein in neuen Schläuchen und daher weder eine Alternative zu CGI.pm noch eine Weiterentwicklung von CGI/1.1 im innovativen Sinne.
Genau hier an dieser Stelle bietet sich ein Verweis auf die uralte Doku SELFHTML/Perl an, weil der Parser, der damals in dieser Doku vorgestellt wurde, gleichermaßen die CGI/1.1 Standard erklärt hat, das war so um 1997.
Die seit 20 Jahren fällige Weiterentwicklung von CGI.pm könnte so aussehen:
sub _parse_rawdata{
my $self = shift;
if( $self->{CONTENT_TYPE} eq 'multipart/c-eav' ){
require cEAV;
$self->{eav} = cEAV->decode_eav( $self->rawdata );
$self->{param} = $self->{eav}->{param};
}
elsif( $self->{CONTENT_TYPE} eq 'multipart/eav' ){
# coming soon
}
elsif( $self->{CONTENT_TYPE} eq 'multipart/form-data' ){
require ParseMultipart;
$self->{STDIN}->seek(0,0);
$self->{param} = ParseMultipart->parse_multipart( $self->{STDIN} );
}
elsif( $self->{CONTENT_TYPE} eq 'application/json' ){
require JSON;
my $json = JSON->new;
$self->{json} = $json->decode($self->rawdata);
$self->{param} = $self->{json}{param};
}
elsif( $self->{CONTENT_TYPE} eq 'bserialize/av' ){
require bSerialize;
my $bs = bSerialize->new;
my $binary = $self->rawdata;
$self->{param} = $bs->bin2av( \$binary );
}
elsif( $self->{CONTENT_TYPE} eq 'bserialize/eav' ){
require bSerialize;
my $bs = bSerialize->new;
my $binary = $self->rawdata;
$self->{eav} = $bs->bin2eav( \$binary );
$self->{param} = $self->{eav}{param};
}
elsif( $self->{CONTENT_TYPE} eq 'application/body+query' ){
# QUERY_STRING mit Parametern + Message Body mit Binary
$self->{param} = $self->qparse($self->{QUERY_STRING});
}
else{
# Default Enctype
# Parameter: Name => [Value], application/x-www-form-urlencoded
$self->{param} = $self->qparse($self->rawdata);
}
}
und genau hier liegt der Hase im Pfeffer: Eine solche Kontrollstruktur ist beliebig erweiterbar für beliebige Content-Types. Und auch ein schönes Beispiel dafür, wie CODE zweckmäßig, nämlich nur bei Bedarf nachgeladen werden kann. Siehe auch hier über den Sinn des Request-Headers Content-Type.
MfG