Apache2-API

 view release on metacpan or  search on metacpan

lib/Apache2/API/Response.pm  view on Meta::CPAN

# 
#    return Apache2::Const::OK;
#  }
sub custom_response { return( shift->_try( '_request', 'custom_response', @_ ) ); }

sub decode
{
    my $self = shift( @_ );
    return( APR::Request::decode( shift( @_ ) ) );
}

# <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Digest>
sub digest { return( shift->_set_get_one( 'Digest', @_ ) ); }

sub encode
{
    my $self = shift( @_ );
    return( APR::Request::encode( shift( @_ ) ) );
}

sub env
{
    my $self = shift( @_ );
    my $r = $self->request;
    if( @_ )
    {
        if( scalar( @_ ) == 1 )
        {
            my $v = shift( @_ );
            if( ref( $v ) eq 'HASH' )
            {
                foreach my $k ( sort( keys( %$v ) ) )
                {
                    $r->subprocess_env( $k => $v->{ $k } );
                }
            }
            else
            {
                return( $r->subprocess_env( $v ) );
            }
        }
        else
        {
            my $hash = { @_ };
            foreach my $k ( sort( keys( %$hash ) ) )
            {
                $r->subprocess_env( $k => $hash->{ $k } );
            }
        }
    }
    else
    {
        $r->subprocess_env;
    }
}

sub err_headers { return( shift->_headers( 'err_headers_out', @_ ) ); }

sub err_headers_out { return( shift->_headers( 'err_headers_out', @_ ) ); }

sub escape { return( URI::Escape::uri_escape( @_ ) ); }

sub etag { return( shift->headers( 'ETag', @_ ) ); }
# <https://perl.apache.org/docs/2.0/api/Apache2/Response.html#toc_C_set_etag_>
# sub etag { return( shift->_try( '_request', 'set_etag', @_ ) ); }

sub expires { return( shift->headers( 'Expires', @_ ) ); }

# <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers>
# e.g.: Access-Control-Expose-Headers: Content-Encoding, X-Kuma-Revision
sub expose_headers { return( shift->_set_get_multi( 'Access-Control-Expose-Headers', @_ ) ); }

sub flush { return( shift->_try( '_request', 'rflush' ) ); }

# sub get_http_message
# {
#   my $self = shift( @_ );
#   my $code = shift( @_ ) || return;
#   my $formal_msg = $self->get_status_line( $code );
#   $formal_msg =~ s/^(\d{3})[[:blank:]]+//;
#   return( $formal_msg );
# }
sub get_http_message { return( Apache2::API::Status->status_message( $_[1], $_[2] ) ); }

sub get_status_line { return( shift->_try( '_request', 'status_line', @_ ) ); }

sub header
{
    my $self = shift( @_ );
    return( $self->error( "No header field name was provided to set or retrieve its value." ) ) if( !scalar( @_ ) );
    my $field = shift( @_ );
    my $hdrs  = $self->headers || return( $self->pass_error );
    if( scalar( @_ ) > 1 )
    {
        return( $hdrs->set( "$field" => @_ ) );
    }
    else
    {
        return( $hdrs->get( "$field" ) );
    }
}

sub headers { return( shift->_headers( 'err_headers_out', @_ ) ); }

sub headers_out { return( shift->_headers( 'headers_out', @_ ) ); }

# <https://perl.apache.org/docs/2.0/api/Apache2/SubRequest.html#toc_C_internal_redirect_>
sub internal_redirect
{
    my $self = shift( @_ );
    my $uri = shift( @_ );
    $uri = $uri->path if( Scalar::Util::blessed( $uri ) && $uri->isa( 'URI' ) );
    # try-catch
    local $@;
    eval
    {
        $self->_request->internal_redirect( $uri );
    };
    if( $@ )
    {
        $self->error( "An error occurred while trying to call Apache Request method \"internal_redirect\": $@" );

lib/Apache2/API/Response.pm  view on Meta::CPAN


sub request { return( shift->_set_get_object( 'request', 'Apache2::API::Request', @_ ) ); }

# <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After>
sub retry_after { return( shift->_set_get_one( 'Retry-After', @_ ) ); }

sub rflush { return( shift->_try( '_request', 'rflush' ) ); }

# e.g. send_cgi_header( $buffer )
sub send_cgi_header { return( shift->_try( '_request', 'send_cgi_header', @_ ) ); }

# e.g. sendfile( $filename );
# sendfile( $filename, $offset );
# sendfile( $filename, $offset, $len );
sub sendfile { return( shift->_try( '_request', 'sendfile', @_ ) ); }

# <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Server>
sub server { return( shift->_set_get_one( 'Server', @_ ) ); }

# <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Server-Timing>
sub server_timing { return( shift->_set_get_one( 'Server-Timing', @_ ) ); }

# e.g set_content_length( 1024 )
sub set_content_length { return( shift->_try( '_request', 'set_content_length', @_ ) ); }

# <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie>
sub set_cookie { return( shift->_set_get_one( 'Set-Cookie', @_ ) ); }

sub set_etag { return( shift->_try( '_request', 'set_etag', @_ ) ); }

sub set_keepalive { return( shift->_try( '_request', 'set_keepalive', @_ ) ); }

# <https://perl.apache.org/docs/2.0/api/Apache2/Response.html#toc_C_set_last_modified_>
sub set_last_modified { return( shift->_try( '_request', 'set_last_modified', @_ ) ); }

# Returns a APR::Socket
# See Apache2::Connection manual page
sub socket { return( shift->_try( 'connection', 'client_socket', @_ ) ); }

# <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/SourceMap>
sub sourcemap { return( shift->_set_get_one( 'SourceMap', @_ ) ); }

sub status { return( shift->_try( '_request', 'status', @_ ) ); }

sub status_line { return( shift->_try( '_request', 'status_line', @_ ) ); }

# <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security>
sub strict_transport_security { return( shift->_set_get_one( 'Strict-Transport-Security', @_ ) ); }

sub subprocess_env { return( shift->_try( '_request', 'subprocess_env' ) ); }

# <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Timing-Allow-Origin>
sub timing_allow_origin { return( shift->_set_get_multi( 'Timing-Allow-Origin', @_ ) ); }

# <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Trailer>
sub trailer { return( shift->_set_get_one( 'Trailer', @_ ) ); }

# <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Transfer-Encoding>
sub transfer_encoding { return( shift->_set_get_one( 'Transfer-Encoding', @_ ) ); }

sub unescape { return( URI::Escape::uri_unescape( @_ ) ); }

# <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Upgrade>
sub upgrade { return( shift->_set_get_multi( 'Upgrade', @_ ) ); }

sub update_mtime { return( shift->_try( '_request', 'update_mtime', @_ ) ); }

sub uri_escape { return( shift->escape( @_ ) ); }

sub uri_unescape { return( shift->unescape( @_ ) ); }

sub url_decode { return( shift->decode( @_ ) ); }

sub url_encode { return( shift->encode( @_ ) ); }

# <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Vary>
sub vary { return( shift->_set_get_multi( 'Vary', @_ ) ); }

# <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Via>
sub via { return( shift->_set_get_multi( 'Via', @_ ) ); }

# <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Want-Digest>
sub want_digest { return( shift->_set_get_multi( 'Want-Digest', @_ ) ); }

# <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Warning>
sub warning { return( shift->_set_get_one( 'Warning', @_ ) ); }

# e.g. $cnt = $r->write($buffer);
# $cnt = $r->write( $buffer, $len );
# $cnt = $r->write( $buffer, $len, $offset );
sub write { return( shift->_try( '_request', 'write', @_ ) ); }

# <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/WWW-Authenticate>
sub www_authenticate { return( shift->_set_get_one( 'WWW-Authenticate', @_ ) ); }

# <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options>
sub x_content_type_options { return( shift->_set_get_one( 'X-Content-Type-Options', @_ ) ); }

# <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-DNS-Prefetch-Control>
sub x_dns_prefetch_control { return( shift->_set_get_one( 'X-DNS-Prefetch-Control', @_ ) ); }

# <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options>
sub x_frame_options { return( shift->_set_get_one( 'X-Frame-Options', @_ ) ); }

# <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection>
sub x_xss_protection { return( shift->_set_get_one( 'X-XSS-Protection', @_ ) ); }

sub _headers
{
    my $self = shift( @_ );
    my $type = shift( @_ ) ||
        return( $self->error({
            message => "No header type was specified.",
            want => [qw( hash )],
        }) );
    my $req = $self->_request ||
        return( $self->error({
            message => "No Apache2::RequestRec found!",
            want => [qw( hash )],
        }) );
    my $code = $req->can( $type ) ||
        return( $self->error({
            message => "Header type '$type' is unsupported by Apache2::RequestRec",
            want => [qw( hash )],
        }) );
    my $apr = $code->( $req ) ||
        return( $self->error({
            message => "Could not get an APR::Table object from Apache2::RequestRec->${type}",
            want => [qw( hash )],
        }) );

lib/Apache2/API/Response.pm  view on Meta::CPAN

    $reso->allow_origin( $origin );
    # Alt-Svc
    my $alt = $resp->alt_svc;
    my $nbytes = $resp->bytes_sent;
    # Cache-Control
    my $cache = $resp->cache_control;
    # Clear-Site-Data
    my $clear = $resp->clear_site_data;
    
    # Apache2::Connection object
    my $conn = $resp->connection;
    my $code = $resp->code;
    # Content-Disposition
    my $disp = $resp->content_disposition;
    my $encoding = $resp->content_encoding;
    # Content-Language
    my $lang = $resp->content_language;
    my $langs_array_ref = $resp->content_languages;
    # Content-Length
    my $len = $resp->content_length;
    # Content-Location
    my $location = $resp->content_location;
    # Content-Range
    my $range = $resp->content_range;
    # Content-Security-Policy
    my $policy = $resp->content_security_policy;
    my $policy = $resp->content_security_policy_report_only;
    my $ct = $resp->content_type;
    my $cookie = $resp->cookie_new(
        name => $name,
        value => $some_value,
        value => 'sid1234567',
        path => '/',
        expires => '+10D',
        # or alternatively
        maxage => 864000
        # to make it exclusively accessible by regular http request and not javascript
        http_only => 1,
        same_site => 'Lax',
        # should it be used under ssl only?
        secure => 1
    );
    $resp->cookie_replace( $cookie );
    $resp->cookie_set( $cookie );
    # Cross-Origin-Embedder-Policy
    my $policy = $resp->cross_origin_embedder_policy;
    # Cross-Origin-Opener-Policy
    my $policy = $resp->cross_origin_opener_policy;
    # Cross-Origin-Resource-Policy
    my $policy = $resp->cross_origin_resource_policy;
    my $cspro = $resp->cspro;
    $resp->custom_response( Apache2::Const::AUTH_REQUIRED, "Authenticate please" );
    my $decoded = $resp->decode( $string );
    # Digest
    my $digest = $resp->digest;
    my $encoded = $resp->encode( $string );
    # APR::Table object
    my $env = $resp->env;
    my $headers = $resp->err_headers;
    my $headers = $resp->err_headers_out;
    my $escaped = $resp->escape( $string );
    my $etag = $resp->etag;
    # Expires
    my $expires = $resp->expires;
    # Access-Control-Expose-Headers
    my $expose_headers = $resp->expose_headers;
    $resp->flush;
    my $msg = $resp->get_http_message( 429 => 'ja_JP' );
    my $string = $resp->get_status_line;
    my $content_type = $resp->headers( 'Content-Type' );
    # or (since it is case insensitive)
    my $content_type = $resp->headers( 'content-type' );
    # or
    my $content_type = $resp->headers->{'Content-Type'};
    $resp->header( 'Content-Type' => 'text/plain' );
    # or
    $resp->headers->{'Content-Type'} = 'text/plain';
    # APR::Table object
    my $headers = $resp->headers;
    my $headers = $resp->headers_out;
    $resp->internal_redirect( $uri );
    $resp->internal_redirect_handler( $uri );
    my $rv = $resp->is_info(100);
    my $rv = $resp->is_success(200);
    my $rv = $resp->is_redirect(302);
    my $rv = $resp->is_error(400);
    my $rv = $resp->is_client_error(401);
    my $rv = $resp->is_server_error(500);
    # Keep-Alive
    my $keep_alive = $resp->keep_alive;
    # Last-Modified
    my $http_date = $resp->last_modified;
    # Last-Modified-Date
    my $http_date = $resp->last_modified_date;
    # The number of bytes sent. Actually calls bytes_sent()
    my $nbytes = $resp->length;
    # Location
    my $loc = $resp->location;
    my $rv = $resp->lookup_uri( $uri );
    my $etag = $resp->make_etag( $force_weak );
    # Access-Control-Max-Age
    my $max_age = $resp->max_age;
    my $rv = $resp->meets_conditions;
    # NEL
    my $nel = $resp->nel;
    $resp->no_cache(1);
    $resp->no_local_copy(1);
    $resp->print( @some_data );
    $resp->printf( $template, $param1, $param2 );
    my $puts = $resp->puts;
    my $rv = $resp->redirect( $uri );
    # Referrer-Policy
    my $policy = $resp->referrer_policy;
    my $r = $resp->request;
    # Retry-After
    my $retry_after = $resp->retry_after;
    $resp->rflush;
    $resp->send_cgi_header;
    $resp->sendfile( $filename, $offset, $len );
    $resp->sendfile( $filename );
    # Server
    my $server = $resp->server;
    my $server_timing = $resp->server_timing;
    $resp->set_content_length(1024);
    # Set-Cookie
    $resp->set_cookie( $cookie );
    $resp->set_last_modified;
    $resp->set_keepalive(1);
    my $socket = $resp->socket;
    my $sourcemap = $resp->sourcemap;
    my $status = $resp->status;
    my $status_line = $resp->status_line;
    # Strict-Transport-Security
    my $policy = $resp->strict_transport_security;
    # APR::Table object
    my $env = $resp->subprocess_env;
    # Timing-Allow-Origin
    my $origin = $resp->timing_allow_origin;
    # Trailer
    my $trailerv = $resp->trailer;
    my $enc = $resp->transfer_encoding;
    my $unescape = $resp->unescape( $string );
    # Upgrade
    my $upgrade = $resp->upgrade;
    $resp->update_mtime( $seconds );
    my $uri = $resp->uri_escape( $uri );
    my $uri = $resp->uri_unescape( $uri );
    my $decoded = $resp->url_decode( $uri );
    my $encoded = $resp->url_encode( $uri );
    # Vary
    my $vary = $resp->vary;
    # Via
    my $via = $resp->via;
    # Want-Digest
    my $want = $resp->want_digest;
    # Warning
    my $warn = $resp->warning;
    $resp->write( $buffer, $len, $offset );
    # WWW-Authenticate
    my $auth = $resp->www_authenticate;
    # X-Content-Type-Options
    my $opt = $resp->x_content_type_options;
    # X-DNS-Prefetch-Control
    my $proto = $resp->x_dns_prefetch_control;
    # X-Frame-Options
    my $opt = $resp->x_frame_options;
    # X-XSS-Protection
    my $xss = $resp->x_xss_protection; 

=head1 VERSION

    v0.2.0

=head1 DESCRIPTION

The purpose of this module is to provide an easy access to various method to process and manipulate incoming request.

This is designed to work under modperl.

Normally, one would need to know which method to access across various Apache2 mod perl modules, which makes development more time consuming and even difficult, because of the scattered documentation and even sometime outdated.

This module alleviate this problem by providing all the necessary methods in one place. Also, at the contrary of C<Apache2> modules suit, all the methods here are die safe. When an error occurs, it will always return undef() and the error will be abl...

Fo its alter ego to manipulate outgoing HTTP response, use the L<Apache2::API::Response> module.

=head1 CONSTRUCTORS

=head2 new

This initiates the package and take the following parameters:

=over 4

=item * C<checkonly>

If true, it will not perform the initialisation it would usually do under modperl.

=item * C<debug>

Optional. If set with a positive integer, this will activate verbose debugging message

=item * C<request>

This is a required parameter to be sent with a value set to a L<Apache2::RequestRec> object

=back

lib/Apache2/API/Response.pm  view on Meta::CPAN


=head2 digest

Sets or gets the HTTP header field C<Digest>

See L<https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Digest>

=head2 encode

Given a string, this returns its url-encoded version

This uses L<APR::Request> XS method.

=head2 env

    my $val = $resp->env( $name );
    $resp->env( $name, $value );

Using the Apache C<subprocess_env> table, this sets or gets environment variables. This is the equivalent of this:

                 $resp->subprocess_env;
    $env_table = $resp->subprocess_env;

           $resp->subprocess_env( $key => $val );
    $val = $resp->subprocess_env( $key );

where C<$resp> is this module object.

If one argument is provided, it will return the corresponding environment value.

If one or more sets of key-value pair are provided, they are set accordingly.

If nothing is provided, it returns a L<APR::Table> object.

=head2 err_headers

Given one or more name => value pair, this will set them in the HTTP header using the L</err_headers_out> method.

=head2 err_headers_out

Get or sets HTTP response headers, which are printed out even on errors and persist across internal redirects.

According to the L<Apache2::RequestRec> documentation:

The difference between L</headers_out> (L<Apache2::RequestRec/headers_out>) and L</err_headers_out> (L<Apache2::RequestRec/err_headers_out>), is that the latter are printed even on error, and persist across internal redirects (so the headers printed ...

For example, if a handler wants to return a C<404> response, but nevertheless to set a cookie, it has to be:

    $resp->err_headers_out->add( 'Set-Cookie' => $cookie );
    return( Apache2::Const::NOT_FOUND );

If the handler does:

    $resp->headers_out->add( 'Set-Cookie' => $cookie );
    return( Apache2::Const::NOT_FOUND );

the C<Set-Cookie> header will not be sent.

See L<Apache2::RequestRec> for more information.

=head2 escape

Provided with a value and this will return it uri escaped by calling L<URI::Escape/uri_escape>.

=head2 etag

Sets or gets the HTTP header field C<Etag>

=head2 expires

Sets or gets the HTTP header field C<Expires>

See L<https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Expires>

=head2 expose_headers

Sets or gets the HTTP header field C<Access-Control-Expose-Headers>

e.g.: Access-Control-Expose-Headers: Content-Encoding, X-Kuma-Revision

See L<https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers>

=head2 flush

Flush any buffered data to the client, by calling L<Apache2::RequestIO/rflush>

    $resp->flush();

Unless STDOUT stream's C<$|> is false, data sent via C<< $resp->print() >> is buffered. This method flushes that data to the client.

For example if your script needs to perform a relatively long-running operation (e.g. a slow db lookup) and the client may timeout if it receives nothing right away, you may want to start the handler by setting the C<Content-Type> header, following b...

    $resp->content_type('text/html');
    $resp->flush; # send the headers out

    $resp->print( long_operation() );
    return( Apache2::Const::OK );

[1] mod_perl2 documentation L<https://perl.apache.org/docs/2.0/user/coding/coding.html#toc_Forcing_HTTP_Response_Headers_Out>

=head2 get_http_message

Given an HTTP code integer, and optionally a language code, this returns the HTTP status message in the language given.

If no language is provided, this returns the message by default in C<en_GB>, i.e. British English.

See also L<Apache2::API::Status>

=head2 get_status_line

Return the C<Status-Line> for a given status code (excluding the HTTP-Version field), by calling L<Apache2::RequestRec/status_line>

For example:

    print( $resp->get_status_line( 400 ) );

will print:

    400 Bad Request

See also L</status_line>

=head2 header

lib/Apache2/API/Response.pm  view on Meta::CPAN

Here 499 is the new response code, and We have been FooBared is the custom response message.

=head2 strict_transport_security

Sets or gets the HTTP header field C<Strict-Transport-Security>

See L<https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security>

=head2 subprocess_env

Get or sets the L<Apache2::RequestRec> C<subprocess_env> table, or optionally set the value of a named entry.

From the L<Apache2::RequestRec> documentation:

When called in void context with no arguments, it populate C<%ENV> with special variables (e.g. C<$ENV{QUERY_STRING}>) like mod_cgi does.

When called in a non-void context with no arguments, it returns an C<APR::Table object>.

When the $key argument (string) is passed, it returns the corresponding value (if such exists, or C<undef>. The following two lines are equivalent:

     $val = $resp->subprocess_env( $key );
     $val = $resp->subprocess_env->get( $key );

When the $key and the $val arguments (strings) are passed, the value is set. The following two lines are equivalent:

     $resp->subprocess_env( $key => $val );
     $resp->subprocess_env->set( $key => $val );

The C<subprocess_env> C<table> is used by L<Apache2::SubProcess>, to pass environment variables to externally spawned processes. It is also used by various Apache modules, and you should use this table to pass the environment variables. For example i...

      $resp->subprocess_env( MyLanguage => "de" );

you can then deploy C<mod_include> and write in C<.shtml> document:

      <!--#if expr="$MyLanguage = en" -->
      English
      <!--#elif expr="$MyLanguage = de" -->
      Deutsch
      <!--#else -->
      Sorry
      <!--#endif -->

=head2 timing_allow_origin

Sets or gets the HTTP header field C<Timing-Allow-Origin>

See L<https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Timing-Allow-Origin>

=head2 trailer

Sets or gets the HTTP header field C<Trailer>

See L<https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Trailer>

=head2 transfer_encoding

Sets or gets the HTTP header field C<Transfer-Encoding>

See L<https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Transfer-Encoding>

=head2 unescape

Unescape the given data chunk by calling L<URI::Escape/uri_unescape>

=head2 update_mtime

Set the C<< $resp->mtime >> field to the specified value if it is later than what is already there, by calling L<Apache2::Response/update_mtime>

    $resp->update_mtime( $mtime );

=head2 upgrade

Sets or gets the HTTP header field C<Upgrade>

See L<https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Upgrade>

=head2 uri_escape

Provided with a string and this uses L<URI::Escape> to return an uri-escaped string.

=head2 uri_unescape

Provided with an uri-escaped string and this will decode it and return its original string, by calling L<URI::Escape/uri_unescape>

=head2 url_decode

Provided with an url-encoded string and this will return its decoded version, by calling L<APR::Request/decode>

=head2 url_encode

Provided with a string and this will return an url-encoded version, by calling L<APR::Request/encode>

=head2 vary

Sets or gets the HTTP header field C<Vary>

See L<https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Vary>

=head2 via

Sets or gets the HTTP header field C<Via>

See L<https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Via>

=head2 want_digest

Sets or gets the HTTP header field C<Want-Digest>

See L<https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Want-Digest>

=head2 warning

Sets or gets the HTTP header field C<Warning>

See L<https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Warning>

=head2 write

Send partial string to the client, by calling L<Apache2::RequestIO/write>

     $cnt = $resp->write( $buffer );
     $cnt = $resp->write( $buffer, $len );
     $cnt = $resp->write( $buffer, $len, $offset );

It returns How many bytes were sent (or buffered).

See L<Apache2::RequestIO> for more information.

=head2 www_authenticate

Sets or gets the HTTP header field C<WWW-Authenticate>

See L<https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/WWW-Authenticate>

=head2 x_content_type_options

Sets or gets the HTTP header field C<X-Content-Type-Options>

See L<https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options>

=head2 x_dns_prefetch_control

Sets or gets the HTTP header field C<X-DNS-Prefetch-Control>



( run in 2.203 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )