Tom Christensen offers a good way to filter in the Perl Cookbook
in chapter 16.5 (Filtering Your Own Output) by forking open on your
own STDOUT and then having the child process filter STDIN to STDOUT.
#!/usr/bin/perl -w
use strict;
use CGI;
oneheader();
my $q = new CGI;
print $q->header;
print $q->header;
close(STDOUT);
exit;
sub oneheader
{
my $pid;
my $seen = 0;
return if $pid = open(STDOUT, "|-");
die "cannot fork: $!" unless defined $pid;
while(<STDIN>)
{
if(m/^Content-Type/)
{
print unless $seen;
$seen = 1;
}
else
{
print;
}
}
exit;
}
Which produces:
(offline mode: enter name=value pairs on standard input)
Content-Type: text/html
(yep, thats two blank lines)
Another method is to tie a file handle and select it.
This requires that you play nice and don't try to fool
it by printing something in multiple chunks. This will
also fail if CGI::Carp dosn't print to the selected filehandle
but rather STDOUT directly. Please forgive me for not
doing the return value from PRINT nicely and failing to
implement PRINTF and WRITE.
#!/usr/bin/perl -w
use strict;
use CGI;
tie *FILTER, "OneHeader";
my $q = new CGI;
select FILTER;
print $q->header;
print $q->header;
print "Foo!\n";
exit;
package OneHeader;
sub TIEHANDLE
{
my $class = shift;
my $me = 0;
bless \$me, $class;
}
sub PRINT
{
my $self = shift;
foreach my $item (@_)
{
if($item =~ m/^Content-Type/)
{
if(not $$self)
{
$$self = 1;
print STDOUT $item;
}
}
else
{
print STDOUT $item;
}
}
1;
}
1;
The output of this method is:
(offline mode: enter name=value pairs on standard input)
Content-Type: text/html
Foo!
Just looked at the code for CGI::Carp and it always
specifies the filehandle that it prints to. Thus the
tie method will require additional twists to get it to
work. Still, the essence is there. |