8

I have written a CGI program and I send a status error with the HTTP header to the client. but when I tried to use mod_perl it only responds with 200 ok status. How can I send a custom status code?

here is the code when I want to respond with the custom status error :

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

EDIT :
here is the code :

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

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

EDIT 2

giving some more information: when I use curl -v 192.168.1.212/mymodperl/test.pl command in shell.
here is the response :

* 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
Sarah Aziziyan
  • 498
  • 9
  • 22
  • 3
    You do realise this is 2017 right? – Gerhard Nov 23 '17 at 08:30
  • 1
    @GerhardBarnard I do :)) – Sarah Aziziyan Nov 23 '17 at 08:31
  • ok, where is the mod_perl portion you are experiencing the issues with? – Gerhard Nov 23 '17 at 08:51
  • also, putting my answer on hold until I get clarity from you and will repost. – Gerhard Nov 23 '17 at 09:18
  • @GerhardBarnard what do you mean by "where is the mod_perl portion"? I have placed my code in mod_perl directory and called it with a browser, it runs by mod_perl. but the statuses I have set do not work. – Sarah Aziziyan Nov 23 '17 at 09:22
  • that is what I mean, show me how you call it and your directory structure – Gerhard Nov 23 '17 at 09:29
  • Can you run a `curl -v ` for the one where you expect 599 code and post the output that you get in your question? Status is the first thing that should go back, and I guess it might be a case of header order error – Tarun Lalwani Nov 25 '17 at 10:05
  • You should try using `$cgi->$header->status('599 Some Issue');` before printing or setting any header – Tarun Lalwani Nov 25 '17 at 10:07
  • @TarunLalwani I did 'curl -v ' and I got 200 ok again. I cleared all the other header settings except status, and still have the same problem. – Sarah Aziziyan Nov 25 '17 at 10:50
  • I think this is a mod_perl issue, there must be some other way to set header status in mod_perl, That is because I have no problem running the code in CGI mode. – Sarah Aziziyan Nov 25 '17 at 10:51
  • @TarunLalwani I edited the question and added the response of `curl` too. – Sarah Aziziyan Nov 25 '17 at 11:01
  • Using mod_perl for writing web applications is not recommended. Have you considered something PSGI based? – melpomene Nov 25 '17 at 11:04
  • Works fine for me on `Apache/2.4.18`, could it be because of older apache version? Can you try with latest one? – Tarun Lalwani Nov 25 '17 at 12:18
  • did you try it with mod_perl ??? @TarunLalwani – Sarah Aziziyan Nov 26 '17 at 06:29
  • I think i mixed CGI and mod perl. Let me try that out – Tarun Lalwani Nov 26 '17 at 06:33
  • You could simply print the header that you want. There isn't any real magic in what CGI->header is doing. I would also recommend using a valid HTTP return code. – Jim Black Nov 28 '17 at 14:05
  • Do not use perl module CGI anymore, and do not invent new HTTP codes. – Patrick Mevzek Nov 29 '17 at 21:38
  • @melpomene Thank you for your suggestion, but at this time I need to make it work with mod_perl (not my choice). but I'll consider your advice for later apps. Thanks. – Sarah Aziziyan Dec 02 '17 at 08:29
  • @JimBlack actually I have sent other valid codes and it still is not working. so I know that the problem is not with sending the HTTP valid code. – Sarah Aziziyan Dec 02 '17 at 08:31
  • @PatrickMevzek I suggest you read the question thoroughly. I am using **mod_perl** and I need to use a **custom code**. if you had any solutions in mind I'd be happy to hear it. – Sarah Aziziyan Dec 02 '17 at 08:35
  • 1
    Do not invent new HTTP codes, whatever software you use. There is a standard, and it is not there to extend it personnally with any new codes... of course if you want interoperability and following standards. You nowhere gave any valid reason to create a new response value. Imagine if everyone does like you, how do you think the web could work? – Patrick Mevzek Dec 02 '17 at 09:32
  • There is no law against using a custom HTTP code. and there are no boundaries in programming. The way to do it is in the answers below. if I want to do sth I make it work. That is the way to push the limits. I like to have a growing mindset. – Sarah Aziziyan Dec 02 '17 at 10:03
  • You are wrong, there is a "law". HTTP is a protocol defined by IETF RFCs. They do not say you are free to decide unilateraly to create new status codes. This has nothing to do with a "growing mindset". – Patrick Mevzek Dec 04 '17 at 03:54
  • @PatrickMevzek RFCs are not laws. they define some rules and protocols and standards. breaking these rules or standards does not put you in jail !!! plus it's doable. It's also acceptable to even create a custom protocol as long as your applications understand it, and works fine with it. I don't have information about your country/state laws, it may be a law in your region. but as long as I remember there is no such a thing written in RFC 2616. – Sarah Aziziyan Dec 04 '17 at 07:07
  • Playing on words does not lead to anything fruitful. Standards are there for a reason, starting with interoperability. If you prefer to break everything and do your thing alone in your corner, you are right you are technically free to do so. But it does not mean it is a good idea at all. EOT. – Patrick Mevzek Dec 04 '17 at 12:58

1 Answers1

3

From http://www.perlmonks.org/?node_id=826769, the way to set a status code is

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:

EDIT: Clarification

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

What are Handlers?

Apache distinguishes between numerous phases for which it provides hooks (because the C functions are called ap_hook_) where modules can plug various callbacks to extend and alter the default behavior of the webserver. mod_perl provides a Perl interface for most of the available hooks, so mod_perl modules writers can change the Apache behavior in Perl. These callbacks are usually referred to as handlers and therefore the configuration directives for the mod_perl handlers look like: PerlFooHandler, where Foo is one of the handler names. For example PerlResponseHandler configures the response callback.

A typical handler is simply a perl package with a handler subroutine. For example:

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;

This handler simply returns the current date and time as a response.

Since this is a response handler, we configure it as a such in httpd.conf:

PerlResponseHandler MyApache2::CurrentTime

Since the response handler should be configured for a specific location, let's write a complete configuration section:

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

Now when a request is issued to http://localhost/time this response handler is executed and a response that includes the current time is returned to the client.

mikep
  • 3,841
  • 8
  • 21
  • I have read this before but I don't know how to use this in my own code. @mikep – Sarah Aziziyan Nov 26 '17 at 14:40
  • 2
    The OP is not writing a mod_perl handler; they are writing a Registry script. – ikegami Nov 26 '17 at 22:23
  • @SarahAziziyan, it seems this cannot be done using a registry script. So the way you are doing it won't allow you to change the status. You will need to use a handler to make it work – Tarun Lalwani Nov 27 '17 at 17:22
  • @mikep I will try to use a handler as you mentioned, and I'll inform you if it worked. thanks. – Sarah Aziziyan Nov 27 '17 at 18:01
  • @TarunLalwani I'll try to use a handler. – Sarah Aziziyan Nov 27 '17 at 18:01
  • @mikep I tried to use a handler but as far as I read, handlers can handle requests from specific URLs. In my case (the code that I wrote in the question), I need to send an error msg to the user with some status (sth like 599) in the case when they don't send a parameter called 'method'. but I don't want to send the same error status for all the requests coming to the `test.pl`. – Sarah Aziziyan Nov 28 '17 at 07:55
  • If you like, we can take this into chat. – mikep Nov 28 '17 at 08:07
  • Thank you for your time and energy @mikep. you were a huge help. – Sarah Aziziyan Dec 02 '17 at 09:58
  • @Sarah Aziziyan, happy to help :) – mikep Dec 02 '17 at 11:37
  • 1
    @TarunLalwani Of course you can set the status using a registry script. You can get the request object with `my $r = Apache2::RequestUtil->request;`, or via an initial `$r = shift()` in the script. Of course it's better to enclose the whole script in a subroutine and then call that subroutine passing the request object as argument, similar to using the `handler` method in a perl handler module. – Francisco Zarabozo Nov 08 '18 at 05:11