Practical mod_perlPractical mod_perlSearch this book

6.6. Apache::Registry Specifics

The following coding issues are relevant only for scripts running under the Apache::Registry content handler and similar handlers, such as Apache::PerlRun. Of course, all of the mod_perl specifics described earlier apply as well.

6.6.1. _ _END_ _ and _ _DATA_ _ Tokens

An Apache::Registry script cannot contain _ _END_ _ or _ _DATA_ _ tokens, because Apache::Registry wraps the original script's code into a subroutine called handler( ), which is then called. Consider the following script, accessed as /perl/test.pl:

print "Content-type: text/plain\n\n";
print "Hi";

When this script is executed under Apache::Registry, it becomes wrapped in a handler( )subroutine, like this:

package Apache::ROOT::perl::test_2epl;
use Apache qw(exit);
sub handler {
    print "Content-type: text/plain\n\n";
    print "Hi";
}

If we happen to put an _ _END_ _ tag in the code, like this:

print "Content-type: text/plain\n\n";
print "Hi";
_ _END_ _
Some text that wouldn't be normally executed

it will be turned into:

package Apache::ROOT::perl::test_2epl;
use Apache qw(exit);
sub handler {
    print "Content-type: text/plain\n\n";
    print "Hi";
    _ _END_ _
    Some text that wouldn't be normally executed
}

When issuing a request to /perl/test.pl, the following error will then be reported:

Missing right bracket at .... line 4, at end of line

Perl cuts everything after the _ _END_ _ tag. Therefore, the subroutine handler( )'s closing curly bracket is not seen by Perl. The same applies to the _ _DATA_ _ tag.

6.6.2. Symbolic Links

Apache::Registry caches the script in the package whose name is constructed from the URI from which the script is accessed. If the same script can be reached by different URIs, which is possible if you have used symbolic links or aliases, the same script will be stored in memory more than once, which is a waste.

For example, assuming that you already have the script at /home/httpd/perl/news/news.pl, you can create a symbolic link:

panic% ln -s /home/httpd/perl/news/news.pl /home/httpd/perl/news.pl

Now the script can be reached through both URIs, /news/news.pl and /news.pl. This doesn't really matter until the two URIs get advertised and users reach the same script from the two of them.

Now start the server in single-server mode and issue a request to both URIs:

http://localhost/perl/news/news.pl
http://localhost/perl/news.pl

To reveal the duplication, you should use the Apache::Status module. Among other things, it shows all the compiled Apache::Registryscripts (using their respective packages). If you are using the default configuration directives, you should either use this URI:

http://localhost/perl-status?rgysubs

or just go to the main menu at:

http://localhost/perl-status

and click on the "Compiled Registry Scripts" menu item.

If the script was accessed through the two URIs, you will see the output shown in Figure 6-1.

Figure 6-1

Figure 6-1. Compiled Registry Scripts output

You can usually spot this kind of problem by running a link checker that goes recursively through all the pages of the service by following all links, and then using Apache::Status to find the symlink duplicates (without restarting the server, of course). To make it easier to figure out what to look for, first find all symbolic links. For example, in our case, the following command shows that we have only one symlink:

panic% find /home/httpd/perl -type l
/home/httpd/perl/news.pl

So now we can look for that symlink in the output of the Compiled Registry Scripts section.

Notice that if you perform the testing in multi-server mode, some child processes might show only one entry or none at all, since they might not serve the same requests as the others.

6.6.3. Return Codes

Apache::Registry normally assumes a return code of OK (200) and sends it for you. If a different return code needs to be sent, $r->status( ) can be used. For example, to send the return code 404 (Not Found), you can use the following code:

use Apache::Constants qw(NOT_FOUND);
$r->status(NOT_FOUND);

If this method is used, there is no need to call $r->send_http_header( ) (assuming that the PerlSendHeader Offsetting is in effect).



Library Navigation Links

Copyright © 2003 O'Reilly & Associates. All rights reserved.