如何使用 mod_perl 发送自定义 http 状态码

Posted

技术标签:

【中文标题】如何使用 mod_perl 发送自定义 http 状态码【英文标题】:How to send a custom http status code with mod_perl 【发布时间】:2018-05-07 03:22:00 【问题描述】:

我编写了一个 CGI 程序,我向客户端发送带有 HTTP 标头的状态错误。但是当我尝试使用 mod_perl 时,它只响应 200 ok 状态。如何发送自定义状态码?

这是我想要响应自定义状态错误时的代码:

my $cgi      = new CGI;
print $cgi->header(-type=>"text/html", -charset=>'utf-8', -status=>599);

编辑: 这是代码:

#!/usr/bin/perl -w
use strict;
use warnings;
use CGI;
use SessionManagement;


my $cgi      = new CGI;
my $method = $cgi->param("method");

my $sessionManagement = new SessionManagement(cgi=>$cgi);
if($sessionManagement)

  if (defined($method)) 
    if($method eq "authentication") 
        loginMethod($cgi,$sessionManagement);
     elsif ($method eq "someMethod")
        someMethod($cgi);
     else
        print $cgi->header(-type=>"text/xml", -charset=>'utf-8');
        print "<html>method does not exist</html>";
    

   else 
      print $cgi->header(-type=>"text/html", -charset=>'utf-8' , -status=>599);
      print "<html>blah blah</html>";
  

else
  print $cgi->header(-type=>"text/html", -charset=>'utf-8' , -status=>599);
  print "<html>blah blah</html>";

-------------------------------------------

编辑 2

提供更多信息: 当我在 shell 中使用 curl -v 192.168.1.212/mymodperl/test.pl 命令时。 这是回复:

* About to connect() to 192.168.1.212 port 80 (#0)
*   Trying 192.168.1.212... connected
* Connected to 192.168.1.212 (192.168.1.212) port 80 (#0)
> GET /mymodperl/test.pl HTTP/1.1
> User-Agent: curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.15.3 zlib/1.2.3 libidn/1.18 libssh2/1.4.2
> Host: 192.168.1.212
> Accept: */*
> 
< HTTP/1.1 200 OK
< Date: Sat, 25 Nov 2017 11:04:18 GMT
< Server: Apache/2.2.15 (Red Hat)
< Connection: close
< Transfer-Encoding: chunked
< Content-Type: text/html; charset=ISO-8859-1
< 
<html>hi</html><!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>500 Internal Server Error</title>
</head><body>
<h1>Internal Server Error</h1>
<p>The server encountered an internal error or
misconfiguration and was unable to complete
your request.</p>
<p>Please contact the server administrator,
 root@localhost and inform them of the time the error occurred,
and anything you might have done that may have
caused the error.</p>
<p>More information about this error may be available
in the server error log.</p>
<hr>
<address>Apache/2.2.15 (Red Hat) Server at 192.168.1.212 Port 80</address>
</body></html>
* Closing connection #0

【问题讨论】:

你知道这是 2017 年吧? @GerhardBarnard 我愿意 :)) 好的,您遇到问题的 mod_perl 部分在哪里? 另外,在我从你那里得到澄清并重新发布之前,我的答案暂时搁置。 无论您使用什么软件,都不要发明新的 HTTP 代码。有一个标准,并且没有个人使用任何新代码对其进行扩展……当然,如果您想要互操作性和遵循标准。您没有给出任何正当理由来创建新的响应值。想象一下,如果每个人都喜欢你,你认为网络如何运作? 【参考方案1】:

来自http://www.perlmonks.org/?node_id=826769,设置状态码的方式是

package My::Handler;

use strict;
use warnings 'all';
use Apache2::RequestRec;

sub handler : method 
  my ($class, $r) = @_;

  $r->status( 401 );
  return 401;


1;# return true:

编辑:澄清

来自https://perl.apache.org/docs/2.0/user/handlers/intro.html

什么是处理程序?

Apache 区分了它提供挂钩的众多阶段(因为 C 函数称为 ap_hook_),其中模块可以插入各种回调来扩展和更改 Web 服务器的默认行为。 mod_perl 为大多数可用的钩子提供 Perl 接口,因此 mod_perl 模块编写者可以更改 Perl 中的 Apache 行为。这些回调通常称为处理程序,因此 mod_perl 处理程序的配置指令如下所示: PerlFooHandler,其中 Foo 是处理程序名称之一。例如 PerlResponseHandler 配置响应回调。

典型的处理程序只是一个带有处理程序子例程的 perl 包。例如:

file:MyApache2/CurrentTime.pm
----------------------------
package MyApache2::CurrentTime;

use strict;
use warnings;

use Apache2::RequestRec ();
use Apache2::RequestIO ();

use Apache2::Const -compile => qw(OK);

sub handler 
  my $r = shift;

  $r->content_type('text/plain');
  $r->print("Now is: " . scalar(localtime) . "\n");

  return Apache2::Const::OK;

1;

此处理程序仅返回当前日期和时间作为响应。

由于这是一个响应处理程序,我们在 httpd.conf 中对其进行配置:

PerlResponseHandler MyApache2::CurrentTime

由于应该为特定位置配置响应处理程序,让我们编写一个完整的配置部分:

PerlModule MyApache2::CurrentTime
<Location /time>
  SetHandler modperl
  PerlResponseHandler MyApache2::CurrentTime
</Location>

现在,当向http://localhost/time 发出请求时,将执行此响应处理程序并将包含当前时间的响应返回给客户端。

【讨论】:

我以前读过这个,但我不知道如何在我自己的代码中使用它。 @mikep OP 没有编写 mod_perl 处理程序;他们正在编写注册表脚本。 @SarahAziziyan,这似乎无法使用注册表脚本完成。所以你这样做的方式不允许你改变状态。您将需要使用处理程序来使其工作 @mikep 我将尝试使用您提到的处理程序,如果它有效,我会通知您。谢谢。 @TarunLalwani 当然,您可以使用注册表脚本设置状态。您可以使用my $r = Apache2::RequestUtil-&gt;request; 或通过脚本中的初始$r = shift() 获取请求对象。当然,最好将整个脚本封装在一个子例程中,然后调用该子例程并将请求对象作为参数传递,类似于在 perl 处理程序模块中使用 handler 方法。

以上是关于如何使用 mod_perl 发送自定义 http 状态码的主要内容,如果未能解决你的问题,请参考以下文章

重定向到页面并发送自定义 HTTP 标头

我们可以创建自定义 HTTP 状态代码吗?

Spring SAML - 如何在 SP HTTP 请求上添加自定义字段?

从 Laravel 发送自定义 500 http 响应

在 mod_perl2 中修改 POST 请求

使用 Ruby 发送自定义 HTTP 标头