Apache-HeavyCGI

 view release on metacpan or  search on metacpan

lib/Apache/HeavyCGI.pm  view on Meta::CPAN

package Apache::HeavyCGI;
use 5.005; # for fields support and package-named exceptions
use Apache::Constants qw(:common);
use Apache::HeavyCGI::Date;
use Apache::HeavyCGI::Exception;
use strict;
use vars qw($VERSION $DEBUG);

$VERSION = "0.013302";

sub can_gzip {
  my Apache::HeavyCGI $self = shift;
  return $self->{CAN_GZIP} if defined $self->{CAN_GZIP};
  my $acce = $self->{R}->header_in('Accept-Encoding') || "";
  return $self->{CAN_GZIP} = 0 unless $acce;
  $self->{CAN_GZIP} = $acce =~ /\bgzip\b/;
}

sub can_png {
  my Apache::HeavyCGI $self = shift;
  return $self->{CAN_PNG} if defined $self->{CAN_PNG};
  my $acce = $self->{R}->header_in("Accept") || "";
  return $self->{CAN_PNG} = 0 unless $acce;
  $self->{CAN_PNG} = $acce =~ m|image/png|i;
}

sub can_utf8 {
  my Apache::HeavyCGI $self = shift;
  return $self->{CAN_UTF8} if defined $self->{CAN_UTF8};

  # From chapter 14.2. HTTP/1.1

  ##   If no Accept-Charset header is present, the default is that any
  ##   character set is acceptable. If an Accept-Charset header is present,
  ##   and if the server cannot send a response which is acceptable
  ##   according to the Accept-Charset header, then the server SHOULD send
  ##   an error response with the 406 (not acceptable) status code, though
  ##   the sending of an unacceptable response is also allowed.

  my $acce = $self->{R}->header_in("Accept-Charset") || "";
  if (defined $acce){
    if ($acce =~ m|\butf-8\b|i){
      $self->{CAN_UTF8} = 1;
    } else {
      $self->{CAN_UTF8} = 0;
    }
    return $self->{CAN_UTF8};
  }
  my $protocol = $self->{R}->protocol || "";
  my($major,$minor) = $protocol =~ m|HTTP/(\d+)\.(\d+)|;
  $self->{CAN_UTF8} = $major >= 1 && $minor >= 1;
}

sub deliver {
  my Apache::HeavyCGI $self = shift;
  my $r = $self->{R};
  # warn "Going to send_http_header";
  $r->send_http_header;
  return OK if $r->method eq "HEAD";
  # warn "Going to print content";
  $r->print($self->{CONTENT});
  DONE; # we've sent the headers and the body, apache shouldn't talk
        # to the browser anymore
}

sub handler {
  warn "The handler of the request hasn't defined a handler subroutine.";
  __PACKAGE__->new( R => shift )->dispatch;
}

sub dispatch {
  my Apache::HeavyCGI $self = shift;
  $self->init;
  eval { $self->prepare; };
  if ($@) {
    if (UNIVERSAL::isa($@,"Apache::HeavyCGI::Exception")) {
      if ($@->{ERROR}) {
	warn "\$\@ ERROR[$@->{ERROR}]";
	$@->{ERROR} = [ $@->{ERROR} ] unless ref $@->{ERROR};
	warn "\$\@ ERROR[$@->{ERROR}]";
	push @{$self->{ERROR}}, @{$@->{ERROR}};
	warn "self ERROR[$self->{ERROR}]";
      } elsif ($@->{HTTP_STATUS}) {
	return $@->{HTTP_STATUS};

lib/Apache/HeavyCGI.pm  view on Meta::CPAN


                                        +-------------------+
                                        | sub new {...}     |
 +--------------------+                 | sub dispatch {...}|
 |Apache::HeavyCGI    |---defines------>| sub prepare {...} |
 +--------------------+                 | sub deliver {...} |
                                        +-------------------+

 +----------------------+               +--------------------+
 |Handler_1 .. Handler_N|               | sub header {...}   |
 |ISA Class::Singleton  |---define----->| sub parameter {...}|
 +----------------------+               +--------------------+

                                                                       +----+
                                                                       |Your|
                                                                       |Duty|
 +----------------------------+----------------------------------------+----+
 |Apache                      | calls Your::Class::handler()           |    |
 +----------------------------+----------------------------------------+----+
 |                            | nominates the handlers,                |    |
 |Your::Class::handler()      | constructs $self,                      | ** |
 |                            | and calls $self->dispatch              |    |
 +----------------------------+----------------------------------------+----+
 |                            |        $self->init     (does nothing)  | ?? |
 |                            |        $self->prepare  (see below)     |    |
 |Apache::HeavyCGI::dispatch()| calls  $self->layout   (sets up layout)| ** |
 |                            |        $self->finish   (headers and    | ** |
 |                            |                         gross content) |    |
 |                            |        $self->deliver  (delivers)      | ?? |
 +----------------------------+----------------------------------------+----+
 |Apache::HeavyCGI::prepare() | calls HANDLER->instance->header($self) | ** |
 |                            | and HANDLER->instance->parameter($self)| ** |
 |                            | on all of your nominated handlers      |    |
 +----------------------------+----------------------------------------+----+


=head1 Object Attributes

As already mentioned, the HeavyCGI object is a pseudo-hash, i.e. can
be treated like a HASH, but all attributes that are being used must be
predeclared at compile time with a C<use fields> clause.

The convention regarding attributes is as simple as it can be:
uppercase attributes are reserved for the Apache::HeavyCGI class, all
other attribute names are at your disposition if you write a subclass.

The following attributes are currently defined. The module author's
production environment has a couple of attributes more that seem to
work well but most probably need more thought to be implemented in a
generic way.

=over

=item CAN_GZIP

Set by the can_gzip method. True if client is able to handle gzipped
data.

=item CAN_PNG

Set by the can_png method. True if client is able to handle PNG.

=item CAN_UTF8

Set by the can_utf8 method. True if client is able to handle UTF8
endoded data.

=item CGI

An object that handles GET and POST parameters and offers the method
param() and upload() in a manner compatible with Apache::Request.
Needs to be constructed and set by the user typically in the
contructor.

=item CHARSET

Optional attribute to denote the charset in which the outgoing data
are being encoded. Only used within the finish method. If it is set,
the finish() method will set the content type to text/html with this
charset.

=item CONTENT

Scalar that contains the content that should be sent to the user
uncompressed. During te finish() method the content may become
compressed.

=item DOCUMENT_ROOT

Unused.

=item ERROR

Anonymous array that accumulates error messages. HeavyCGI doesn't
handle the error though. It is left to the user to set up a proper
response to the user.

=item EXECUTION_PLAN

Object of type L<Apache::HeavyCGI::ExePlan>. It is recommended to
compute the object at startup time and always pass the same execution
plan into the constructor.

=item EXPIRES

Optional Attribute set by the expires() method. If set, HeavyCGI will
send an Expires header. The EXPIRES attribute needs to contain an
L<Apache::HeavyCGI::Date> object.

=item HANDLER

If there is an EXECUTION_PLAN, this attribute is ignored. Without an
EXECUTION_PLAN, it must be an array of package names. HeavyCGI treats
the packages as Class::Singleton classes. During the prepare() method
HeavyCGI calls HANDLER->instance->header($self) and
HANDLER->instance->parameter($self) on all of your nominated handlers.

=item LAST_MODIFIED

Optional Attribute set by the last_modified() method. If set, HeavyCGI
will send a Last-Modified header of the specified time, otherwise it



( run in 0.786 second using v1.01-cache-2.11-cpan-df04353d9ac )