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;
}
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
|
show 2 more comments
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
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 atcgi_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
|
show 2 more comments
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
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
perl cgi fastcgi
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 atcgi_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
|
show 2 more comments
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 atcgi_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
|
show 2 more comments
3 Answers
3
active
oldest
votes
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.
- Rip all FastCGI-specific code out of your program - leaving a pure CGI-style program.
- 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.
- 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.
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
|
show 6 more comments
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.
If you enter a name and submit the form, it will display a 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 print
ing 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.
1
Excellent example... thanks!
– Marcus
Nov 16 '18 at 20:06
add a comment |
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.
This is helpful and I'm starting to wrap my mind around this stuff, a bit.
– Marcus
Nov 16 '18 at 15:20
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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.
- Rip all FastCGI-specific code out of your program - leaving a pure CGI-style program.
- 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.
- 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.
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
|
show 6 more comments
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.
- Rip all FastCGI-specific code out of your program - leaving a pure CGI-style program.
- 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.
- 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.
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
|
show 6 more comments
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.
- Rip all FastCGI-specific code out of your program - leaving a pure CGI-style program.
- 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.
- 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.
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.
- Rip all FastCGI-specific code out of your program - leaving a pure CGI-style program.
- 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.
- 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.
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
|
show 6 more comments
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
|
show 6 more comments
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.
If you enter a name and submit the form, it will display a 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 print
ing 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.
1
Excellent example... thanks!
– Marcus
Nov 16 '18 at 20:06
add a comment |
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.
If you enter a name and submit the form, it will display a 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 print
ing 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.
1
Excellent example... thanks!
– Marcus
Nov 16 '18 at 20:06
add a comment |
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.
If you enter a name and submit the form, it will display a 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 print
ing 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.
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.
If you enter a name and submit the form, it will display a 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 print
ing 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.
answered Nov 16 '18 at 16:03
simbabquesimbabque
44.5k757106
44.5k757106
1
Excellent example... thanks!
– Marcus
Nov 16 '18 at 20:06
add a comment |
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
add a comment |
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.
This is helpful and I'm starting to wrap my mind around this stuff, a bit.
– Marcus
Nov 16 '18 at 15:20
add a comment |
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.
This is helpful and I'm starting to wrap my mind around this stuff, a bit.
– Marcus
Nov 16 '18 at 15:20
add a comment |
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.
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.
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
add a comment |
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
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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