我是否应该根据CGI.pm的过时状态从CGI :: Fast迁移到其他地方?我该怎么做?

时间:2018-11-16 14:38:22

标签: perl cgi fastcgi

我正在使用CGI::Fast来利用FastCGI的速度和可伸缩性,并且我还使用CGI.pm的查询字符串解析。我不使用CGI.pm不推荐使用的HTML编写功能。

在社区中停止使用CGI.pm是strongly advised,但是在我的用例中,我是否也应该考虑迁移?如果是这样,我怎么办

1)仍然使用FastCGI

2)获取查询参数

...没有采用像Dancer或Mojolicious这样的框架?

我要替换的代码只是:

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

我愿意与CGI::PSGI一起使用类似Plack::Request的东西,但是我无法看到如何精炼FastCGI功能,因为CGI::FastCGI::PSGI都想要子类CGI的创建对象。而且我仍然需要在CGI.pm中启用CGI::Fast。 Plack似乎需要学习很多知识来替换现在的几行代码。

3 个答案:

答案 0 :(得分:4)

这很好地说明了PSGI是对CGI(及其相关技术,如FastCGI)的改进的一个原因。在CGI风格的程序中,代码与部署方法紧密结合,当您更改部署方法时,通常需要对代码进行相当大的更改。使用PSGI风格的程序,无论您如何部署,代码都是相同的。

您没有向我们展示任何代码,但是您谈论的是“几行代码”。所以这就是我要采取的方法。

  1. 从程序中剥离所有特定于FastCGI的代码-保留纯CGI风格的程序。
  2. 然后您可以选择。您可以使用我在Easy PSGI中描述的技术将程序转换为纯PSGI程序。或者,如果要进行太多工作,请使用CGI::PSGI在PSGI环境中运行CGI程序。
  3. 您现在有了一个PSGI程序,几乎可以在任何Web服务器环境中使用。您可以将其作为CGI程序使用。您可以使用Plack::Handler::FCGI在FCGI下运行它。或者,您也可以将其部署为Web代理后面的独立服务(最后一个选项是我选择的那个)。

但是您在第3步中所做的任何选择都是不可撤销的。相同的代码将在所有部署环境中工作。因此,在它们之间移动通常非常简单。

p.s。 CGI.pm并非完全不推荐使用。它已从标准Perl发行版中删除,但这是因为不鼓励使用它。

答案 1 :(得分:4)

这是帮助您入门的简短指南。我将使用CGI,而不是FastCGI,但这确实是一样的。只需想象一下围绕参数选择的循环。

一个简单的CGI

让我们从一个简单的CGI程序开始。由于缺少真正的Web服务器,我将使用cgi_this来运行它。

#!/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;

这是 hello.pl 。它需要一个可执行标志。

运行程序

您以cgi_this开头,如下所示。

$ 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

现在您可以在浏览器中打开它。

Firefox with CGI program and form

如果输入名称并提交表单,它将显示问候语。

Firefox with CGI program and greeting

转换为PSGI

所有这些都是直截了当的。现在,将其转换。

我们将从一个名为 hello.psgi 的新文件开始。名为 .psgi 并不重要,但这是约定。

我们必须执行几个步骤才能使其与PSGI协议兼容。我们将使用Plack::Request来帮助我们做到这一点。

整个程序需要包装在my $app = sub { ... };调用中。

#!/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;

现在显然我们还没有加载CGI,并且也没有CGI环境。因此,接下来我们需要获取参数。摆脱$q位,改用$req

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

现在使用plackup运行它,然后在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 ...

B!它失败了,因为我们还没有完成。如您所见,它将HTML写入了STDOUT,但这并没有传递给浏览器。这是因为PSGI会绕过引用,并且您的程序不会直接与STDOUT或STDERR通信。

它也抱怨缺少参考。让我们先处理一下。在代码参考的末尾,添加以下内容:

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

return $res->finalize;

我们要我们的Plack :: Request为我们创建一个新的Plack :: Response,设置内容类型,并将最终的(认为是 immutable )响应返回给Plack处理程序,将序列化并作为实际的HTTP响应发送到浏览器。

现在替换所有print语句。创建一个新变量$content,而不是print处理输出,将其连接到该变量。然后将其交给响应。

  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);

现在,在终端中重新启动您的应用,然后再次访问它。看起来和CGI一样。

PSGI version output

答案 2 :(得分:3)

PSGI引用的

CGI::Alternatives是解决之道。

Dancer利用PSGI,但您可以write code using it directly,而无需使用框架。

您可以使用Plack::Handler::FCGI通过FastCGI运行PSGI应用。