Should I migrate from CGI::Fast to something else in light of CGI.pm's deprecated status and how should I do...





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







2















I am using CGI::Fast to leverage the speed and scalability of FastCGI, and I also CGI.pm's query string parsing. I do not use CGI.pm's deprecated HTML writing functions.



Stopping the use of CGI.pm is strongly advised in the community, but in my use case, should I also be thinking of migrating away? And if so, how do I



1) still leverage FastCGI



2) grab query params



...without adopting a framework like Dancer or Mojolicious?



The code I am looking at replacing is just:



 while ( $main::cgi = new CGI::Fast ) {
my $name = $main::cgi->param('name');
}


I am open to using something like CGI::PSGI in conjunction with Plack::Request, but I couldn't see how to finesse the FastCGI functionality as CGI::Fast and CGI::PSGI both want to subclass CGI for the creation of the object. And I'd still have CGI.pm in the mix to enable CGI::Fast. Plack seems like a lot to learn to replace what is now a few lines of code.










share|improve this question

























  • This strongly depends on your use case. You say a few lines of code, so you're talking about small scripts?

    – simbabque
    Nov 16 '18 at 14:43











  • The scripts aren't small but the use of CGI is limited to the CGI::Fast capability and the parsing of query params. I do my own route dispatch, templating with HTML::Template etc., so I already have a framework in those senses.

    – Marcus
    Nov 16 '18 at 14:46






  • 1





    Obligatory link to Sawyer X's CGI.pm must die talk.

    – simbabque
    Nov 16 '18 at 14:53






  • 1





    Plack::Request is your friend then. That should be all you need. Try this: plackup -MDDP -MPlack::Request -e '$app = sub { my $env = shift; my $req = Plack::Request->new($env); p $req->query_parameters; return $req->new_response(200)->finalize; }' and on another terminal, curl localhost:5000

    – simbabque
    Nov 16 '18 at 15:08








  • 1





    It seems like a bit of a guide is needed. I'll write up an answer with a hands-on guide. In the meantime, also take a look at cgi_this, a utility I whipped together for testing CGI related questions. It's build from various other PSGI and CGI bits and showcases how simple this stuff really is. Here's me talking about it at The Perl Conference in Glasgow this year.

    – simbabque
    Nov 16 '18 at 15:32


















2















I am using CGI::Fast to leverage the speed and scalability of FastCGI, and I also CGI.pm's query string parsing. I do not use CGI.pm's deprecated HTML writing functions.



Stopping the use of CGI.pm is strongly advised in the community, but in my use case, should I also be thinking of migrating away? And if so, how do I



1) still leverage FastCGI



2) grab query params



...without adopting a framework like Dancer or Mojolicious?



The code I am looking at replacing is just:



 while ( $main::cgi = new CGI::Fast ) {
my $name = $main::cgi->param('name');
}


I am open to using something like CGI::PSGI in conjunction with Plack::Request, but I couldn't see how to finesse the FastCGI functionality as CGI::Fast and CGI::PSGI both want to subclass CGI for the creation of the object. And I'd still have CGI.pm in the mix to enable CGI::Fast. Plack seems like a lot to learn to replace what is now a few lines of code.










share|improve this question

























  • This strongly depends on your use case. You say a few lines of code, so you're talking about small scripts?

    – simbabque
    Nov 16 '18 at 14:43











  • The scripts aren't small but the use of CGI is limited to the CGI::Fast capability and the parsing of query params. I do my own route dispatch, templating with HTML::Template etc., so I already have a framework in those senses.

    – Marcus
    Nov 16 '18 at 14:46






  • 1





    Obligatory link to Sawyer X's CGI.pm must die talk.

    – simbabque
    Nov 16 '18 at 14:53






  • 1





    Plack::Request is your friend then. That should be all you need. Try this: plackup -MDDP -MPlack::Request -e '$app = sub { my $env = shift; my $req = Plack::Request->new($env); p $req->query_parameters; return $req->new_response(200)->finalize; }' and on another terminal, curl localhost:5000

    – simbabque
    Nov 16 '18 at 15:08








  • 1





    It seems like a bit of a guide is needed. I'll write up an answer with a hands-on guide. In the meantime, also take a look at cgi_this, a utility I whipped together for testing CGI related questions. It's build from various other PSGI and CGI bits and showcases how simple this stuff really is. Here's me talking about it at The Perl Conference in Glasgow this year.

    – simbabque
    Nov 16 '18 at 15:32














2












2








2


1






I am using CGI::Fast to leverage the speed and scalability of FastCGI, and I also CGI.pm's query string parsing. I do not use CGI.pm's deprecated HTML writing functions.



Stopping the use of CGI.pm is strongly advised in the community, but in my use case, should I also be thinking of migrating away? And if so, how do I



1) still leverage FastCGI



2) grab query params



...without adopting a framework like Dancer or Mojolicious?



The code I am looking at replacing is just:



 while ( $main::cgi = new CGI::Fast ) {
my $name = $main::cgi->param('name');
}


I am open to using something like CGI::PSGI in conjunction with Plack::Request, but I couldn't see how to finesse the FastCGI functionality as CGI::Fast and CGI::PSGI both want to subclass CGI for the creation of the object. And I'd still have CGI.pm in the mix to enable CGI::Fast. Plack seems like a lot to learn to replace what is now a few lines of code.










share|improve this question
















I am using CGI::Fast to leverage the speed and scalability of FastCGI, and I also CGI.pm's query string parsing. I do not use CGI.pm's deprecated HTML writing functions.



Stopping the use of CGI.pm is strongly advised in the community, but in my use case, should I also be thinking of migrating away? And if so, how do I



1) still leverage FastCGI



2) grab query params



...without adopting a framework like Dancer or Mojolicious?



The code I am looking at replacing is just:



 while ( $main::cgi = new CGI::Fast ) {
my $name = $main::cgi->param('name');
}


I am open to using something like CGI::PSGI in conjunction with Plack::Request, but I couldn't see how to finesse the FastCGI functionality as CGI::Fast and CGI::PSGI both want to subclass CGI for the creation of the object. And I'd still have CGI.pm in the mix to enable CGI::Fast. Plack seems like a lot to learn to replace what is now a few lines of code.







perl cgi fastcgi






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 16 '18 at 14:59







Marcus

















asked Nov 16 '18 at 14:38









MarcusMarcus

2,91672956




2,91672956













  • This strongly depends on your use case. You say a few lines of code, so you're talking about small scripts?

    – simbabque
    Nov 16 '18 at 14:43











  • The scripts aren't small but the use of CGI is limited to the CGI::Fast capability and the parsing of query params. I do my own route dispatch, templating with HTML::Template etc., so I already have a framework in those senses.

    – Marcus
    Nov 16 '18 at 14:46






  • 1





    Obligatory link to Sawyer X's CGI.pm must die talk.

    – simbabque
    Nov 16 '18 at 14:53






  • 1





    Plack::Request is your friend then. That should be all you need. Try this: plackup -MDDP -MPlack::Request -e '$app = sub { my $env = shift; my $req = Plack::Request->new($env); p $req->query_parameters; return $req->new_response(200)->finalize; }' and on another terminal, curl localhost:5000

    – simbabque
    Nov 16 '18 at 15:08








  • 1





    It seems like a bit of a guide is needed. I'll write up an answer with a hands-on guide. In the meantime, also take a look at cgi_this, a utility I whipped together for testing CGI related questions. It's build from various other PSGI and CGI bits and showcases how simple this stuff really is. Here's me talking about it at The Perl Conference in Glasgow this year.

    – simbabque
    Nov 16 '18 at 15:32



















  • This strongly depends on your use case. You say a few lines of code, so you're talking about small scripts?

    – simbabque
    Nov 16 '18 at 14:43











  • The scripts aren't small but the use of CGI is limited to the CGI::Fast capability and the parsing of query params. I do my own route dispatch, templating with HTML::Template etc., so I already have a framework in those senses.

    – Marcus
    Nov 16 '18 at 14:46






  • 1





    Obligatory link to Sawyer X's CGI.pm must die talk.

    – simbabque
    Nov 16 '18 at 14:53






  • 1





    Plack::Request is your friend then. That should be all you need. Try this: plackup -MDDP -MPlack::Request -e '$app = sub { my $env = shift; my $req = Plack::Request->new($env); p $req->query_parameters; return $req->new_response(200)->finalize; }' and on another terminal, curl localhost:5000

    – simbabque
    Nov 16 '18 at 15:08








  • 1





    It seems like a bit of a guide is needed. I'll write up an answer with a hands-on guide. In the meantime, also take a look at cgi_this, a utility I whipped together for testing CGI related questions. It's build from various other PSGI and CGI bits and showcases how simple this stuff really is. Here's me talking about it at The Perl Conference in Glasgow this year.

    – simbabque
    Nov 16 '18 at 15:32

















This strongly depends on your use case. You say a few lines of code, so you're talking about small scripts?

– simbabque
Nov 16 '18 at 14:43





This strongly depends on your use case. You say a few lines of code, so you're talking about small scripts?

– simbabque
Nov 16 '18 at 14:43













The scripts aren't small but the use of CGI is limited to the CGI::Fast capability and the parsing of query params. I do my own route dispatch, templating with HTML::Template etc., so I already have a framework in those senses.

– Marcus
Nov 16 '18 at 14:46





The scripts aren't small but the use of CGI is limited to the CGI::Fast capability and the parsing of query params. I do my own route dispatch, templating with HTML::Template etc., so I already have a framework in those senses.

– Marcus
Nov 16 '18 at 14:46




1




1





Obligatory link to Sawyer X's CGI.pm must die talk.

– simbabque
Nov 16 '18 at 14:53





Obligatory link to Sawyer X's CGI.pm must die talk.

– simbabque
Nov 16 '18 at 14:53




1




1





Plack::Request is your friend then. That should be all you need. Try this: plackup -MDDP -MPlack::Request -e '$app = sub { my $env = shift; my $req = Plack::Request->new($env); p $req->query_parameters; return $req->new_response(200)->finalize; }' and on another terminal, curl localhost:5000

– simbabque
Nov 16 '18 at 15:08







Plack::Request is your friend then. That should be all you need. Try this: plackup -MDDP -MPlack::Request -e '$app = sub { my $env = shift; my $req = Plack::Request->new($env); p $req->query_parameters; return $req->new_response(200)->finalize; }' and on another terminal, curl localhost:5000

– simbabque
Nov 16 '18 at 15:08






1




1





It seems like a bit of a guide is needed. I'll write up an answer with a hands-on guide. In the meantime, also take a look at cgi_this, a utility I whipped together for testing CGI related questions. It's build from various other PSGI and CGI bits and showcases how simple this stuff really is. Here's me talking about it at The Perl Conference in Glasgow this year.

– simbabque
Nov 16 '18 at 15:32





It seems like a bit of a guide is needed. I'll write up an answer with a hands-on guide. In the meantime, also take a look at cgi_this, a utility I whipped together for testing CGI related questions. It's build from various other PSGI and CGI bits and showcases how simple this stuff really is. Here's me talking about it at The Perl Conference in Glasgow this year.

– simbabque
Nov 16 '18 at 15:32












3 Answers
3






active

oldest

votes


















4














This neatly illustrates one reason why PSGI is an improvement on CGI (and its related technologies like FastCGI). In CGI-style programs, the code is tightly coupled with the deployment method and when you change the deployment method, you usually need to make quite large changes to the code. With PSGI-style programs, the code is the same no matter how you deploy it.



You haven't shown us any of your code, but you talk about "a few lines of code". So here's the approach I'd take.




  1. Rip all FastCGI-specific code out of your program - leaving a pure CGI-style program.

  2. You then have a choice. You could use the techniques I describe in Easy PSGI to convert your program to a pure PSGI program. Or, if that's going to be too much work, use CGI::PSGI to run your CGI program in a PSGI environment.

  3. You now have a PSGI program that you can use in pretty much any web server environment. You can serve it as a CGI program. You can use Plack::Handler::FCGI to run it under FCGI. Or you can deploy it as a standalone service behind a web proxy (that last option is the one I'd choose).


But any choice you make at step 3 isn't irrevocable. The same code will work in all deployment environments. And, therefore, moving between them is usually pretty simple.



p.s. CGI.pm isn't exactly deprecated. It has been removed from the standard Perl distribution but that's because its use is discouraged.






share|improve this answer


























  • Thanks Dave I just added the lines that concern me...

    – Marcus
    Nov 16 '18 at 15:00











  • That's a really good blog post Dave!

    – simbabque
    Nov 16 '18 at 15:04











  • "Standalone service behind a web proxy", I wonder what you mean by that exactly. I think I understand your 3-steps to rewriting my stuff but I think the only FastCGI specific stuff is the request loop itself. I had to make sure my variables were clear at the end of the loop but not much else is specific to FastCGI, I don't believe.

    – Marcus
    Nov 16 '18 at 15:11






  • 1





    @Marcus one of the core features of PSGI/Plack is that it allows you to run without a traditional web server. There are many Plack based web servers written in Perl (and some in XS) that can run completely stand-alone. But you'd still have some sort of traditional web server that proxies the requests and catches static resources.

    – simbabque
    Nov 16 '18 at 15:13






  • 2





    @Marcus: I mean that your web application becomes a completely separate service (in the strict Unix meaning of the word) running on a high port number, accepting HTTP requests and returning HTTP responses. And then you configure your "real" web server (often nginx, in my experience) to forward requests that it receives for your app onto the actual service. It's actually a lot simpler than it sounds.

    – Dave Cross
    Nov 16 '18 at 15:16





















4














This is a short guide to help you get started. I'm going to use CGI, not FastCGI, but it's really the same thing. Just imagine the loop being around the parameter selection.



A simple CGI



Let's start with a simple CGI program. I will be using cgi_this to run it for lack of having a real web server handy.



#!/usr/bin/env perl
use strict;
use warnings;
use CGI;

my $q = CGI->new;
my $name = $q->param('name');

print $q->header;
if ($name) {
print <<"HTML";
<html><body><h1>Hello, $name</hi></body></html>
HTML
}
else {
print <<"HTML";
<html><body><form method="GET">
<label>What's your name? <input type="text" name="name"></label>
</form></body></html>
HTML
}

1;


This is hello.pl. It needs an executable flag.



Running the program



You start it with cgi_this as follows.



$ ls
hello.pl
$ cgi_this
Exporting '.', available at:
http://127.0.0.1:3000/

Found the following scripts:
http://127.0.0.1:3000/hello.pl


Now you can open it in the browser.



Firefox with CGI program and form



If you enter a name and submit the form, it will display a greeting.



Firefox with CGI program and greeting



Converting to PSGI



All of this is straight-forward. Now let's convert it.



We'll start with a new file named hello.psgi. It doesn't really matter if it's called .psgi, but this is the convention.



We have to do a couple of steps in order to make it work with the PSGI protocol. We will use Plack::Request to help us do that.



The entire program needs to be wrapped in a my $app = sub { ... }; call.



#!/usr/bin/env plackup
use strict;
use warnings;

use Plack::Request;

my $app = sub {
my $env = shift; # this is the Plack environment

my $req = Plack::Request->new($env);

my $q = CGI->new;
my $name = $q->param('name');

print $q->header;
if ($name) {
print <<"HTML";
<html><body><h1>Hello, $name</hi></body></html>
HTML
}
else {
print <<"HTML";
<html><body><form method="GET">
<label>What's your name? <input type="text" name="name"></label>
</form></body></html>
HTML
}
};

# no 1; here, we want it to return $app;


Now obviously we haven't loaded CGI, and there's no CGI environment anyway. So next we need to get the parameter. Get rid of the $q bit and use the $req instead.



my $name = $req->parameters->{name};


Now run this with plackup, then request it at http://localhost:5000.



$ plackup hello.psgi
HTTP::Server::PSGI: Accepting connections at http://0:5000/
<html><body><form method="GET">
<label>What's your name? <input type="text" name="name"></label>
</form></body></html>
Response should be array ref or code ref: 1 at ...


BANG! It fails, because we're not done yet. As you can see, it wrote the HTML to STDOUT, but that didn't go to the browser. That's because PSGI passes around references, and your program does not talk directly to STDOUT or STDERR.



It also complains about the missing reference. Let's deal with that first. At the end of the code reference, add this:



# prepare the response
my $res = $req->new_response(200);
$res->content_type('text/html');

return $res->finalize;


We're asking our Plack::Request to make a new Plack::Response for us, set a content type, and return the finalized (think immutable) response to the Plack handler, which will serialise and it to the browser as an actual HTTP response.



Now replace all the print statements. Make a new variable $content and instead of printing output, concatenate it to that variable. Then hand that to the response.



  my $content;
if ($name) {
$content .= <<"HTML";
<html><body><h1>Hello, $name</hi></body></html>
HTML
}
else {
$content .= <<"HTML";
<html><body><form method="GET">
<label>What's your name? <input type="text" name="name"></label>
</form></body></html>
HTML
}

# prepare the response
my $res = $req->new_response(200);
$res->content_type('text/html');
$res->body($content);


Now restart your app in the terminal and access it again. It will look the same as the CGI.



PSGI version output






share|improve this answer



















  • 1





    Excellent example... thanks!

    – Marcus
    Nov 16 '18 at 20:06



















3














PSGI, as referenced by CGI::Alternatives, is the way to go.



Dancer leverages PSGI, but you can write code using it directly without a framework wrapping around it.



You can use Plack::Handler::FCGI to run a PSGI app via FastCGI.






share|improve this answer


























  • This is helpful and I'm starting to wrap my mind around this stuff, a bit.

    – Marcus
    Nov 16 '18 at 15:20












Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53339936%2fshould-i-migrate-from-cgifast-to-something-else-in-light-of-cgi-pms-deprecate%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























3 Answers
3






active

oldest

votes








3 Answers
3






active

oldest

votes









active

oldest

votes






active

oldest

votes









4














This neatly illustrates one reason why PSGI is an improvement on CGI (and its related technologies like FastCGI). In CGI-style programs, the code is tightly coupled with the deployment method and when you change the deployment method, you usually need to make quite large changes to the code. With PSGI-style programs, the code is the same no matter how you deploy it.



You haven't shown us any of your code, but you talk about "a few lines of code". So here's the approach I'd take.




  1. Rip all FastCGI-specific code out of your program - leaving a pure CGI-style program.

  2. You then have a choice. You could use the techniques I describe in Easy PSGI to convert your program to a pure PSGI program. Or, if that's going to be too much work, use CGI::PSGI to run your CGI program in a PSGI environment.

  3. You now have a PSGI program that you can use in pretty much any web server environment. You can serve it as a CGI program. You can use Plack::Handler::FCGI to run it under FCGI. Or you can deploy it as a standalone service behind a web proxy (that last option is the one I'd choose).


But any choice you make at step 3 isn't irrevocable. The same code will work in all deployment environments. And, therefore, moving between them is usually pretty simple.



p.s. CGI.pm isn't exactly deprecated. It has been removed from the standard Perl distribution but that's because its use is discouraged.






share|improve this answer


























  • Thanks Dave I just added the lines that concern me...

    – Marcus
    Nov 16 '18 at 15:00











  • That's a really good blog post Dave!

    – simbabque
    Nov 16 '18 at 15:04











  • "Standalone service behind a web proxy", I wonder what you mean by that exactly. I think I understand your 3-steps to rewriting my stuff but I think the only FastCGI specific stuff is the request loop itself. I had to make sure my variables were clear at the end of the loop but not much else is specific to FastCGI, I don't believe.

    – Marcus
    Nov 16 '18 at 15:11






  • 1





    @Marcus one of the core features of PSGI/Plack is that it allows you to run without a traditional web server. There are many Plack based web servers written in Perl (and some in XS) that can run completely stand-alone. But you'd still have some sort of traditional web server that proxies the requests and catches static resources.

    – simbabque
    Nov 16 '18 at 15:13






  • 2





    @Marcus: I mean that your web application becomes a completely separate service (in the strict Unix meaning of the word) running on a high port number, accepting HTTP requests and returning HTTP responses. And then you configure your "real" web server (often nginx, in my experience) to forward requests that it receives for your app onto the actual service. It's actually a lot simpler than it sounds.

    – Dave Cross
    Nov 16 '18 at 15:16


















4














This neatly illustrates one reason why PSGI is an improvement on CGI (and its related technologies like FastCGI). In CGI-style programs, the code is tightly coupled with the deployment method and when you change the deployment method, you usually need to make quite large changes to the code. With PSGI-style programs, the code is the same no matter how you deploy it.



You haven't shown us any of your code, but you talk about "a few lines of code". So here's the approach I'd take.




  1. Rip all FastCGI-specific code out of your program - leaving a pure CGI-style program.

  2. You then have a choice. You could use the techniques I describe in Easy PSGI to convert your program to a pure PSGI program. Or, if that's going to be too much work, use CGI::PSGI to run your CGI program in a PSGI environment.

  3. You now have a PSGI program that you can use in pretty much any web server environment. You can serve it as a CGI program. You can use Plack::Handler::FCGI to run it under FCGI. Or you can deploy it as a standalone service behind a web proxy (that last option is the one I'd choose).


But any choice you make at step 3 isn't irrevocable. The same code will work in all deployment environments. And, therefore, moving between them is usually pretty simple.



p.s. CGI.pm isn't exactly deprecated. It has been removed from the standard Perl distribution but that's because its use is discouraged.






share|improve this answer


























  • Thanks Dave I just added the lines that concern me...

    – Marcus
    Nov 16 '18 at 15:00











  • That's a really good blog post Dave!

    – simbabque
    Nov 16 '18 at 15:04











  • "Standalone service behind a web proxy", I wonder what you mean by that exactly. I think I understand your 3-steps to rewriting my stuff but I think the only FastCGI specific stuff is the request loop itself. I had to make sure my variables were clear at the end of the loop but not much else is specific to FastCGI, I don't believe.

    – Marcus
    Nov 16 '18 at 15:11






  • 1





    @Marcus one of the core features of PSGI/Plack is that it allows you to run without a traditional web server. There are many Plack based web servers written in Perl (and some in XS) that can run completely stand-alone. But you'd still have some sort of traditional web server that proxies the requests and catches static resources.

    – simbabque
    Nov 16 '18 at 15:13






  • 2





    @Marcus: I mean that your web application becomes a completely separate service (in the strict Unix meaning of the word) running on a high port number, accepting HTTP requests and returning HTTP responses. And then you configure your "real" web server (often nginx, in my experience) to forward requests that it receives for your app onto the actual service. It's actually a lot simpler than it sounds.

    – Dave Cross
    Nov 16 '18 at 15:16
















4












4








4







This neatly illustrates one reason why PSGI is an improvement on CGI (and its related technologies like FastCGI). In CGI-style programs, the code is tightly coupled with the deployment method and when you change the deployment method, you usually need to make quite large changes to the code. With PSGI-style programs, the code is the same no matter how you deploy it.



You haven't shown us any of your code, but you talk about "a few lines of code". So here's the approach I'd take.




  1. Rip all FastCGI-specific code out of your program - leaving a pure CGI-style program.

  2. You then have a choice. You could use the techniques I describe in Easy PSGI to convert your program to a pure PSGI program. Or, if that's going to be too much work, use CGI::PSGI to run your CGI program in a PSGI environment.

  3. You now have a PSGI program that you can use in pretty much any web server environment. You can serve it as a CGI program. You can use Plack::Handler::FCGI to run it under FCGI. Or you can deploy it as a standalone service behind a web proxy (that last option is the one I'd choose).


But any choice you make at step 3 isn't irrevocable. The same code will work in all deployment environments. And, therefore, moving between them is usually pretty simple.



p.s. CGI.pm isn't exactly deprecated. It has been removed from the standard Perl distribution but that's because its use is discouraged.






share|improve this answer















This neatly illustrates one reason why PSGI is an improvement on CGI (and its related technologies like FastCGI). In CGI-style programs, the code is tightly coupled with the deployment method and when you change the deployment method, you usually need to make quite large changes to the code. With PSGI-style programs, the code is the same no matter how you deploy it.



You haven't shown us any of your code, but you talk about "a few lines of code". So here's the approach I'd take.




  1. Rip all FastCGI-specific code out of your program - leaving a pure CGI-style program.

  2. You then have a choice. You could use the techniques I describe in Easy PSGI to convert your program to a pure PSGI program. Or, if that's going to be too much work, use CGI::PSGI to run your CGI program in a PSGI environment.

  3. You now have a PSGI program that you can use in pretty much any web server environment. You can serve it as a CGI program. You can use Plack::Handler::FCGI to run it under FCGI. Or you can deploy it as a standalone service behind a web proxy (that last option is the one I'd choose).


But any choice you make at step 3 isn't irrevocable. The same code will work in all deployment environments. And, therefore, moving between them is usually pretty simple.



p.s. CGI.pm isn't exactly deprecated. It has been removed from the standard Perl distribution but that's because its use is discouraged.







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 16 '18 at 15:00

























answered Nov 16 '18 at 14:57









Dave CrossDave Cross

48.7k34079




48.7k34079













  • Thanks Dave I just added the lines that concern me...

    – Marcus
    Nov 16 '18 at 15:00











  • That's a really good blog post Dave!

    – simbabque
    Nov 16 '18 at 15:04











  • "Standalone service behind a web proxy", I wonder what you mean by that exactly. I think I understand your 3-steps to rewriting my stuff but I think the only FastCGI specific stuff is the request loop itself. I had to make sure my variables were clear at the end of the loop but not much else is specific to FastCGI, I don't believe.

    – Marcus
    Nov 16 '18 at 15:11






  • 1





    @Marcus one of the core features of PSGI/Plack is that it allows you to run without a traditional web server. There are many Plack based web servers written in Perl (and some in XS) that can run completely stand-alone. But you'd still have some sort of traditional web server that proxies the requests and catches static resources.

    – simbabque
    Nov 16 '18 at 15:13






  • 2





    @Marcus: I mean that your web application becomes a completely separate service (in the strict Unix meaning of the word) running on a high port number, accepting HTTP requests and returning HTTP responses. And then you configure your "real" web server (often nginx, in my experience) to forward requests that it receives for your app onto the actual service. It's actually a lot simpler than it sounds.

    – Dave Cross
    Nov 16 '18 at 15:16





















  • Thanks Dave I just added the lines that concern me...

    – Marcus
    Nov 16 '18 at 15:00











  • That's a really good blog post Dave!

    – simbabque
    Nov 16 '18 at 15:04











  • "Standalone service behind a web proxy", I wonder what you mean by that exactly. I think I understand your 3-steps to rewriting my stuff but I think the only FastCGI specific stuff is the request loop itself. I had to make sure my variables were clear at the end of the loop but not much else is specific to FastCGI, I don't believe.

    – Marcus
    Nov 16 '18 at 15:11






  • 1





    @Marcus one of the core features of PSGI/Plack is that it allows you to run without a traditional web server. There are many Plack based web servers written in Perl (and some in XS) that can run completely stand-alone. But you'd still have some sort of traditional web server that proxies the requests and catches static resources.

    – simbabque
    Nov 16 '18 at 15:13






  • 2





    @Marcus: I mean that your web application becomes a completely separate service (in the strict Unix meaning of the word) running on a high port number, accepting HTTP requests and returning HTTP responses. And then you configure your "real" web server (often nginx, in my experience) to forward requests that it receives for your app onto the actual service. It's actually a lot simpler than it sounds.

    – Dave Cross
    Nov 16 '18 at 15:16



















Thanks Dave I just added the lines that concern me...

– Marcus
Nov 16 '18 at 15:00





Thanks Dave I just added the lines that concern me...

– Marcus
Nov 16 '18 at 15:00













That's a really good blog post Dave!

– simbabque
Nov 16 '18 at 15:04





That's a really good blog post Dave!

– simbabque
Nov 16 '18 at 15:04













"Standalone service behind a web proxy", I wonder what you mean by that exactly. I think I understand your 3-steps to rewriting my stuff but I think the only FastCGI specific stuff is the request loop itself. I had to make sure my variables were clear at the end of the loop but not much else is specific to FastCGI, I don't believe.

– Marcus
Nov 16 '18 at 15:11





"Standalone service behind a web proxy", I wonder what you mean by that exactly. I think I understand your 3-steps to rewriting my stuff but I think the only FastCGI specific stuff is the request loop itself. I had to make sure my variables were clear at the end of the loop but not much else is specific to FastCGI, I don't believe.

– Marcus
Nov 16 '18 at 15:11




1




1





@Marcus one of the core features of PSGI/Plack is that it allows you to run without a traditional web server. There are many Plack based web servers written in Perl (and some in XS) that can run completely stand-alone. But you'd still have some sort of traditional web server that proxies the requests and catches static resources.

– simbabque
Nov 16 '18 at 15:13





@Marcus one of the core features of PSGI/Plack is that it allows you to run without a traditional web server. There are many Plack based web servers written in Perl (and some in XS) that can run completely stand-alone. But you'd still have some sort of traditional web server that proxies the requests and catches static resources.

– simbabque
Nov 16 '18 at 15:13




2




2





@Marcus: I mean that your web application becomes a completely separate service (in the strict Unix meaning of the word) running on a high port number, accepting HTTP requests and returning HTTP responses. And then you configure your "real" web server (often nginx, in my experience) to forward requests that it receives for your app onto the actual service. It's actually a lot simpler than it sounds.

– Dave Cross
Nov 16 '18 at 15:16







@Marcus: I mean that your web application becomes a completely separate service (in the strict Unix meaning of the word) running on a high port number, accepting HTTP requests and returning HTTP responses. And then you configure your "real" web server (often nginx, in my experience) to forward requests that it receives for your app onto the actual service. It's actually a lot simpler than it sounds.

– Dave Cross
Nov 16 '18 at 15:16















4














This is a short guide to help you get started. I'm going to use CGI, not FastCGI, but it's really the same thing. Just imagine the loop being around the parameter selection.



A simple CGI



Let's start with a simple CGI program. I will be using cgi_this to run it for lack of having a real web server handy.



#!/usr/bin/env perl
use strict;
use warnings;
use CGI;

my $q = CGI->new;
my $name = $q->param('name');

print $q->header;
if ($name) {
print <<"HTML";
<html><body><h1>Hello, $name</hi></body></html>
HTML
}
else {
print <<"HTML";
<html><body><form method="GET">
<label>What's your name? <input type="text" name="name"></label>
</form></body></html>
HTML
}

1;


This is hello.pl. It needs an executable flag.



Running the program



You start it with cgi_this as follows.



$ ls
hello.pl
$ cgi_this
Exporting '.', available at:
http://127.0.0.1:3000/

Found the following scripts:
http://127.0.0.1:3000/hello.pl


Now you can open it in the browser.



Firefox with CGI program and form



If you enter a name and submit the form, it will display a greeting.



Firefox with CGI program and greeting



Converting to PSGI



All of this is straight-forward. Now let's convert it.



We'll start with a new file named hello.psgi. It doesn't really matter if it's called .psgi, but this is the convention.



We have to do a couple of steps in order to make it work with the PSGI protocol. We will use Plack::Request to help us do that.



The entire program needs to be wrapped in a my $app = sub { ... }; call.



#!/usr/bin/env plackup
use strict;
use warnings;

use Plack::Request;

my $app = sub {
my $env = shift; # this is the Plack environment

my $req = Plack::Request->new($env);

my $q = CGI->new;
my $name = $q->param('name');

print $q->header;
if ($name) {
print <<"HTML";
<html><body><h1>Hello, $name</hi></body></html>
HTML
}
else {
print <<"HTML";
<html><body><form method="GET">
<label>What's your name? <input type="text" name="name"></label>
</form></body></html>
HTML
}
};

# no 1; here, we want it to return $app;


Now obviously we haven't loaded CGI, and there's no CGI environment anyway. So next we need to get the parameter. Get rid of the $q bit and use the $req instead.



my $name = $req->parameters->{name};


Now run this with plackup, then request it at http://localhost:5000.



$ plackup hello.psgi
HTTP::Server::PSGI: Accepting connections at http://0:5000/
<html><body><form method="GET">
<label>What's your name? <input type="text" name="name"></label>
</form></body></html>
Response should be array ref or code ref: 1 at ...


BANG! It fails, because we're not done yet. As you can see, it wrote the HTML to STDOUT, but that didn't go to the browser. That's because PSGI passes around references, and your program does not talk directly to STDOUT or STDERR.



It also complains about the missing reference. Let's deal with that first. At the end of the code reference, add this:



# prepare the response
my $res = $req->new_response(200);
$res->content_type('text/html');

return $res->finalize;


We're asking our Plack::Request to make a new Plack::Response for us, set a content type, and return the finalized (think immutable) response to the Plack handler, which will serialise and it to the browser as an actual HTTP response.



Now replace all the print statements. Make a new variable $content and instead of printing output, concatenate it to that variable. Then hand that to the response.



  my $content;
if ($name) {
$content .= <<"HTML";
<html><body><h1>Hello, $name</hi></body></html>
HTML
}
else {
$content .= <<"HTML";
<html><body><form method="GET">
<label>What's your name? <input type="text" name="name"></label>
</form></body></html>
HTML
}

# prepare the response
my $res = $req->new_response(200);
$res->content_type('text/html');
$res->body($content);


Now restart your app in the terminal and access it again. It will look the same as the CGI.



PSGI version output






share|improve this answer



















  • 1





    Excellent example... thanks!

    – Marcus
    Nov 16 '18 at 20:06
















4














This is a short guide to help you get started. I'm going to use CGI, not FastCGI, but it's really the same thing. Just imagine the loop being around the parameter selection.



A simple CGI



Let's start with a simple CGI program. I will be using cgi_this to run it for lack of having a real web server handy.



#!/usr/bin/env perl
use strict;
use warnings;
use CGI;

my $q = CGI->new;
my $name = $q->param('name');

print $q->header;
if ($name) {
print <<"HTML";
<html><body><h1>Hello, $name</hi></body></html>
HTML
}
else {
print <<"HTML";
<html><body><form method="GET">
<label>What's your name? <input type="text" name="name"></label>
</form></body></html>
HTML
}

1;


This is hello.pl. It needs an executable flag.



Running the program



You start it with cgi_this as follows.



$ ls
hello.pl
$ cgi_this
Exporting '.', available at:
http://127.0.0.1:3000/

Found the following scripts:
http://127.0.0.1:3000/hello.pl


Now you can open it in the browser.



Firefox with CGI program and form



If you enter a name and submit the form, it will display a greeting.



Firefox with CGI program and greeting



Converting to PSGI



All of this is straight-forward. Now let's convert it.



We'll start with a new file named hello.psgi. It doesn't really matter if it's called .psgi, but this is the convention.



We have to do a couple of steps in order to make it work with the PSGI protocol. We will use Plack::Request to help us do that.



The entire program needs to be wrapped in a my $app = sub { ... }; call.



#!/usr/bin/env plackup
use strict;
use warnings;

use Plack::Request;

my $app = sub {
my $env = shift; # this is the Plack environment

my $req = Plack::Request->new($env);

my $q = CGI->new;
my $name = $q->param('name');

print $q->header;
if ($name) {
print <<"HTML";
<html><body><h1>Hello, $name</hi></body></html>
HTML
}
else {
print <<"HTML";
<html><body><form method="GET">
<label>What's your name? <input type="text" name="name"></label>
</form></body></html>
HTML
}
};

# no 1; here, we want it to return $app;


Now obviously we haven't loaded CGI, and there's no CGI environment anyway. So next we need to get the parameter. Get rid of the $q bit and use the $req instead.



my $name = $req->parameters->{name};


Now run this with plackup, then request it at http://localhost:5000.



$ plackup hello.psgi
HTTP::Server::PSGI: Accepting connections at http://0:5000/
<html><body><form method="GET">
<label>What's your name? <input type="text" name="name"></label>
</form></body></html>
Response should be array ref or code ref: 1 at ...


BANG! It fails, because we're not done yet. As you can see, it wrote the HTML to STDOUT, but that didn't go to the browser. That's because PSGI passes around references, and your program does not talk directly to STDOUT or STDERR.



It also complains about the missing reference. Let's deal with that first. At the end of the code reference, add this:



# prepare the response
my $res = $req->new_response(200);
$res->content_type('text/html');

return $res->finalize;


We're asking our Plack::Request to make a new Plack::Response for us, set a content type, and return the finalized (think immutable) response to the Plack handler, which will serialise and it to the browser as an actual HTTP response.



Now replace all the print statements. Make a new variable $content and instead of printing output, concatenate it to that variable. Then hand that to the response.



  my $content;
if ($name) {
$content .= <<"HTML";
<html><body><h1>Hello, $name</hi></body></html>
HTML
}
else {
$content .= <<"HTML";
<html><body><form method="GET">
<label>What's your name? <input type="text" name="name"></label>
</form></body></html>
HTML
}

# prepare the response
my $res = $req->new_response(200);
$res->content_type('text/html');
$res->body($content);


Now restart your app in the terminal and access it again. It will look the same as the CGI.



PSGI version output






share|improve this answer



















  • 1





    Excellent example... thanks!

    – Marcus
    Nov 16 '18 at 20:06














4












4








4







This is a short guide to help you get started. I'm going to use CGI, not FastCGI, but it's really the same thing. Just imagine the loop being around the parameter selection.



A simple CGI



Let's start with a simple CGI program. I will be using cgi_this to run it for lack of having a real web server handy.



#!/usr/bin/env perl
use strict;
use warnings;
use CGI;

my $q = CGI->new;
my $name = $q->param('name');

print $q->header;
if ($name) {
print <<"HTML";
<html><body><h1>Hello, $name</hi></body></html>
HTML
}
else {
print <<"HTML";
<html><body><form method="GET">
<label>What's your name? <input type="text" name="name"></label>
</form></body></html>
HTML
}

1;


This is hello.pl. It needs an executable flag.



Running the program



You start it with cgi_this as follows.



$ ls
hello.pl
$ cgi_this
Exporting '.', available at:
http://127.0.0.1:3000/

Found the following scripts:
http://127.0.0.1:3000/hello.pl


Now you can open it in the browser.



Firefox with CGI program and form



If you enter a name and submit the form, it will display a greeting.



Firefox with CGI program and greeting



Converting to PSGI



All of this is straight-forward. Now let's convert it.



We'll start with a new file named hello.psgi. It doesn't really matter if it's called .psgi, but this is the convention.



We have to do a couple of steps in order to make it work with the PSGI protocol. We will use Plack::Request to help us do that.



The entire program needs to be wrapped in a my $app = sub { ... }; call.



#!/usr/bin/env plackup
use strict;
use warnings;

use Plack::Request;

my $app = sub {
my $env = shift; # this is the Plack environment

my $req = Plack::Request->new($env);

my $q = CGI->new;
my $name = $q->param('name');

print $q->header;
if ($name) {
print <<"HTML";
<html><body><h1>Hello, $name</hi></body></html>
HTML
}
else {
print <<"HTML";
<html><body><form method="GET">
<label>What's your name? <input type="text" name="name"></label>
</form></body></html>
HTML
}
};

# no 1; here, we want it to return $app;


Now obviously we haven't loaded CGI, and there's no CGI environment anyway. So next we need to get the parameter. Get rid of the $q bit and use the $req instead.



my $name = $req->parameters->{name};


Now run this with plackup, then request it at http://localhost:5000.



$ plackup hello.psgi
HTTP::Server::PSGI: Accepting connections at http://0:5000/
<html><body><form method="GET">
<label>What's your name? <input type="text" name="name"></label>
</form></body></html>
Response should be array ref or code ref: 1 at ...


BANG! It fails, because we're not done yet. As you can see, it wrote the HTML to STDOUT, but that didn't go to the browser. That's because PSGI passes around references, and your program does not talk directly to STDOUT or STDERR.



It also complains about the missing reference. Let's deal with that first. At the end of the code reference, add this:



# prepare the response
my $res = $req->new_response(200);
$res->content_type('text/html');

return $res->finalize;


We're asking our Plack::Request to make a new Plack::Response for us, set a content type, and return the finalized (think immutable) response to the Plack handler, which will serialise and it to the browser as an actual HTTP response.



Now replace all the print statements. Make a new variable $content and instead of printing output, concatenate it to that variable. Then hand that to the response.



  my $content;
if ($name) {
$content .= <<"HTML";
<html><body><h1>Hello, $name</hi></body></html>
HTML
}
else {
$content .= <<"HTML";
<html><body><form method="GET">
<label>What's your name? <input type="text" name="name"></label>
</form></body></html>
HTML
}

# prepare the response
my $res = $req->new_response(200);
$res->content_type('text/html');
$res->body($content);


Now restart your app in the terminal and access it again. It will look the same as the CGI.



PSGI version output






share|improve this answer













This is a short guide to help you get started. I'm going to use CGI, not FastCGI, but it's really the same thing. Just imagine the loop being around the parameter selection.



A simple CGI



Let's start with a simple CGI program. I will be using cgi_this to run it for lack of having a real web server handy.



#!/usr/bin/env perl
use strict;
use warnings;
use CGI;

my $q = CGI->new;
my $name = $q->param('name');

print $q->header;
if ($name) {
print <<"HTML";
<html><body><h1>Hello, $name</hi></body></html>
HTML
}
else {
print <<"HTML";
<html><body><form method="GET">
<label>What's your name? <input type="text" name="name"></label>
</form></body></html>
HTML
}

1;


This is hello.pl. It needs an executable flag.



Running the program



You start it with cgi_this as follows.



$ ls
hello.pl
$ cgi_this
Exporting '.', available at:
http://127.0.0.1:3000/

Found the following scripts:
http://127.0.0.1:3000/hello.pl


Now you can open it in the browser.



Firefox with CGI program and form



If you enter a name and submit the form, it will display a greeting.



Firefox with CGI program and greeting



Converting to PSGI



All of this is straight-forward. Now let's convert it.



We'll start with a new file named hello.psgi. It doesn't really matter if it's called .psgi, but this is the convention.



We have to do a couple of steps in order to make it work with the PSGI protocol. We will use Plack::Request to help us do that.



The entire program needs to be wrapped in a my $app = sub { ... }; call.



#!/usr/bin/env plackup
use strict;
use warnings;

use Plack::Request;

my $app = sub {
my $env = shift; # this is the Plack environment

my $req = Plack::Request->new($env);

my $q = CGI->new;
my $name = $q->param('name');

print $q->header;
if ($name) {
print <<"HTML";
<html><body><h1>Hello, $name</hi></body></html>
HTML
}
else {
print <<"HTML";
<html><body><form method="GET">
<label>What's your name? <input type="text" name="name"></label>
</form></body></html>
HTML
}
};

# no 1; here, we want it to return $app;


Now obviously we haven't loaded CGI, and there's no CGI environment anyway. So next we need to get the parameter. Get rid of the $q bit and use the $req instead.



my $name = $req->parameters->{name};


Now run this with plackup, then request it at http://localhost:5000.



$ plackup hello.psgi
HTTP::Server::PSGI: Accepting connections at http://0:5000/
<html><body><form method="GET">
<label>What's your name? <input type="text" name="name"></label>
</form></body></html>
Response should be array ref or code ref: 1 at ...


BANG! It fails, because we're not done yet. As you can see, it wrote the HTML to STDOUT, but that didn't go to the browser. That's because PSGI passes around references, and your program does not talk directly to STDOUT or STDERR.



It also complains about the missing reference. Let's deal with that first. At the end of the code reference, add this:



# prepare the response
my $res = $req->new_response(200);
$res->content_type('text/html');

return $res->finalize;


We're asking our Plack::Request to make a new Plack::Response for us, set a content type, and return the finalized (think immutable) response to the Plack handler, which will serialise and it to the browser as an actual HTTP response.



Now replace all the print statements. Make a new variable $content and instead of printing output, concatenate it to that variable. Then hand that to the response.



  my $content;
if ($name) {
$content .= <<"HTML";
<html><body><h1>Hello, $name</hi></body></html>
HTML
}
else {
$content .= <<"HTML";
<html><body><form method="GET">
<label>What's your name? <input type="text" name="name"></label>
</form></body></html>
HTML
}

# prepare the response
my $res = $req->new_response(200);
$res->content_type('text/html');
$res->body($content);


Now restart your app in the terminal and access it again. It will look the same as the CGI.



PSGI version output







share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 16 '18 at 16:03









simbabquesimbabque

44.5k757106




44.5k757106








  • 1





    Excellent example... thanks!

    – Marcus
    Nov 16 '18 at 20:06














  • 1





    Excellent example... thanks!

    – Marcus
    Nov 16 '18 at 20:06








1




1





Excellent example... thanks!

– Marcus
Nov 16 '18 at 20:06





Excellent example... thanks!

– Marcus
Nov 16 '18 at 20:06











3














PSGI, as referenced by CGI::Alternatives, is the way to go.



Dancer leverages PSGI, but you can write code using it directly without a framework wrapping around it.



You can use Plack::Handler::FCGI to run a PSGI app via FastCGI.






share|improve this answer


























  • This is helpful and I'm starting to wrap my mind around this stuff, a bit.

    – Marcus
    Nov 16 '18 at 15:20
















3














PSGI, as referenced by CGI::Alternatives, is the way to go.



Dancer leverages PSGI, but you can write code using it directly without a framework wrapping around it.



You can use Plack::Handler::FCGI to run a PSGI app via FastCGI.






share|improve this answer


























  • This is helpful and I'm starting to wrap my mind around this stuff, a bit.

    – Marcus
    Nov 16 '18 at 15:20














3












3








3







PSGI, as referenced by CGI::Alternatives, is the way to go.



Dancer leverages PSGI, but you can write code using it directly without a framework wrapping around it.



You can use Plack::Handler::FCGI to run a PSGI app via FastCGI.






share|improve this answer















PSGI, as referenced by CGI::Alternatives, is the way to go.



Dancer leverages PSGI, but you can write code using it directly without a framework wrapping around it.



You can use Plack::Handler::FCGI to run a PSGI app via FastCGI.







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 16 '18 at 14:49

























answered Nov 16 '18 at 14:43









QuentinQuentin

658k748951057




658k748951057













  • This is helpful and I'm starting to wrap my mind around this stuff, a bit.

    – Marcus
    Nov 16 '18 at 15:20



















  • This is helpful and I'm starting to wrap my mind around this stuff, a bit.

    – Marcus
    Nov 16 '18 at 15:20

















This is helpful and I'm starting to wrap my mind around this stuff, a bit.

– Marcus
Nov 16 '18 at 15:20





This is helpful and I'm starting to wrap my mind around this stuff, a bit.

– Marcus
Nov 16 '18 at 15:20


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53339936%2fshould-i-migrate-from-cgifast-to-something-else-in-light-of-cgi-pms-deprecate%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Bressuire

Vorschmack

Quarantine