Apache2-API

 view release on metacpan or  search on metacpan

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

    }
}

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\": $@" );
        return( Apache2::Const::HTTP_INTERNAL_SERVER_ERROR );
    }
    return( Apache2::Const::HTTP_OK );
}

# <https://perl.apache.org/docs/2.0/api/Apache2/SubRequest.html#toc_C_internal_redirect_handler_>
sub internal_redirect_handler
{
    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_handler( $uri );
    };
    if( $@ )
    {
        $self->error( "An error occurred while trying to call Apache Request method \"internal_redirect_handler\": $@" );
        return( Apache2::Const::HTTP_INTERNAL_SERVER_ERROR );
    }
    return( Apache2::Const::HTTP_OK );
}

sub is_info         { return( Apache2::API::Status->is_info( $_[1] ) ); }

sub is_success      { return( Apache2::API::Status->is_success( $_[1] ) ); }

sub is_redirect     { return( Apache2::API::Status->is_redirect( $_[1] ) ); }

sub is_error        { return( Apache2::API::Status->is_error( $_[1] ) ); }

sub is_client_error { return( Apache2::API::Status->is_client_error( $_[1] ) ); }

sub is_server_error { return( Apache2::API::Status->is_server_error( $_[1] ) ); }

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

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

sub last_modified_date { return( shift->headers( 'Last-Modified-Date', @_ ) ); }

# Number of bytes sent
sub length { return( shift->_try( 'request', 'bytes_sent' ) ); }

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

# <https://perl.apache.org/docs/2.0/api/Apache2/SubRequest.html#toc_C_run_>
sub lookup_uri
{
    my $self = shift( @_ );
    my $uri = shift( @_ );
    $uri = $uri->path if( Scalar::Util::blessed( $uri ) && $uri->isa( 'URI' ) );
    # try-catch
    local $@;
    my $rv = eval
    {
        my $subr = $self->_request->lookup_uri( $uri, @_ );
        # Returns Apache2::Const::OK, Apache2::Const::DECLINED, etc.
        return( $subr->run );
    };
    if( $@ )
    {
        $self->error( "An error occurred while trying to call Apache Request method \"internal_redirect_handler\": $@" );
        return( Apache2::Const::HTTP_INTERNAL_SERVER_ERROR );
    }
    return( $rv );
}

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

# <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Max-Age>
sub max_age { return( shift->_set_get_number( 'Access-Control-Max-Age', @_ ) ); }

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

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

# This adds the following to the outgoing headers:
# Pragma: no-cache
# Cache-control: no-cache
sub no_cache { return( shift->_try( '_request', 'no_cache', @_ ) ); }

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

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

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

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

sub redirect
{
    my $self = shift( @_ );
    # I have to die if nothing was provided, because our return value is the http code. We can't just return undef()
    my $uri = shift( @_ ) || die( "No uri provided to redirect\n" );
    # Stringify
    $self->headers->set( 'Location' => "$uri" );
    $self->code( Apache2::Const::HTTP_MOVED_TEMPORARILY );
    return( Apache2::Const::HTTP_MOVED_TEMPORARILY );
}

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

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', @_ ) ); }

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

        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

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

    });
    # To prepare a table of 20 elements, but the table can still grow
    my $table = APR::Table::make( $resp->pool, 20 );
    my $table2 = $resp2->headers;
    # overwrite any existing keys in our table $table
    $table->overlap( $table2, APR::Const::OVERLAP_TABLES_SET );
    # key, value pairs are added, regardless of whether there is another element with the same key in $table
    $table->overlap( $table2, APR::Const::OVERLAP_TABLES_MERGE );
    my $table3 = $table->overlay( $table2, $pool3 );

See L<APR::Table> for more information.

=head2 headers_out

Returns or sets the C<< key => value >> pairs of outgoing HTTP headers, only on 2xx responses.

See also L</err_headers_out>, which allows to set headers for non-2xx responses and persist across internal redirects.

More information at L<Apache2::RequestRec>

=head2 internal_redirect

Given a C<URI> object or a uri path string, this redirect the current request to some other uri internally.

If a C<URI> object is given, its C<path> method will be used to get the path string.

    $resp->internal_redirect( $new_uri );

In case that you want some other request to be served as the top-level request instead of what the client requested directly, call this method from a handler, and then immediately return L<Apache2::Const::OK>. The client will be unaware the a differe...

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

=head2 internal_redirect_handler

Identical to L</internal_redirect>, plus automatically sets C<< $resp->content_type >> is of the sub-request to be the same as of the main request, if C<< $resp->handler >> is true.

=head2 is_info

Given a HTTP code integer, this will return true if the code is comprised between C<100> and less than C<200>, false otherwise.

=head2 is_success

Given a HTTP code integer, this will return true if the code is comprised between C<200> and less than C<300>, false otherwise.

=head2 is_redirect

Given a HTTP code integer, this will return true if the code is comprised between C<300> and less than C<400>, false otherwise.

=head2 is_error

Given a HTTP code integer, this will return true if the code is comprised between C<400> and less than C<600>, false otherwise.

=head2 is_client_error

Given a HTTP code integer, this will return true if the code is comprised between C<400> and less than C<500>, false otherwise.

=head2 is_server_error

Given a HTTP code integer, this will return true if the code is comprised between C<500> and less than C<600>, false otherwise.

=head2 keep_alive

Sets or gets the HTTP header field C<Keep-Alive>

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

=head2 last_modified

Sets or gets the HTTP header field C<Last-Modified>

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

=head2 last_modified_date

Sets or gets the HTTP header field C<Last-Modified-Date>

=head2 length

Read only.

This returns the number of bytes sent by calling L<Apache2::RequestRec/bytes_sent>

=head2 location

Sets or gets the HTTP header field C<Location>

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

=head2 lookup_uri

Create a sub request from the given URI, by calling L<Apache2::SubRequest/lookup_uri>

This sub request can be inspected to find information about the requested URI.

     $ret = $resp->lookup_uri( $new_uri );
     $ret = $resp->lookup_uri( $new_uri, $next_filter );
     $ret = $resp->lookup_uri( $new_uri, $next_filter, $handler );

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

=head2 make_etag

Provided with a boolean value, this constructs an entity tag from the resource information, by calling L<Apache2::Response/make_etag>

If it is a real file, build in some of the file characteristics.

    $etag = $resp->make_etag( $force_weak );

It returns the etag as a string.

=head2 max_age

Sets or gets the HTTP header field C<Access-Control-Max-Age>

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

=head2 meets_conditions

Implements condition C<GET> rules for HTTP/1.1 specification. This function inspects the client headers and determines if the response fulfills the specified requirements.

    $status = $resp->meets_conditions();

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

Parse the header, by calling L<Apache2::Response/send_cgi_header>

    $resp->send_cgi_header( $buffer );

This method is really for back-compatibility with mod_perl 1.0. It is very inefficient to send headers this way, because of the parsing overhead.

If there is a response body following the headers it will be handled too (as if it was sent via L</print>).

Notice that if only HTTP headers are included they will not be sent until some body is sent (again the C<send> part is retained from the mod_perl 1.0 method).

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

=head2 sendfile

Provided with a file path, an optional offset and an optional length, and this will send a file or a part of it, by calling L<Apache2::RequestIO/sendfile>

     $rc = $resp->sendfile( $filename );
     $rc = $resp->sendfile( $filename, $offset );
     $rc = $resp->sendfile( $filename, $offset, $len );

It returns a L<APR::Const> constant.

On success, L<APR::Const::SUCCESS> is returned.

In case of a failure, a failure code is returned, in which case normally it should be returned to the caller

=head2 server

Sets or gets the HTTP header field C<Server>

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

=head2 server_timing

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

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

=head2 set_content_length

Set the content length for this request, by calling L<Apache2::Response/set_content_length>

    $resp->set_content_length( $length );

It does not return any value.

=head2 set_cookie

Sets or gets the HTTP header field C<Set-Cookie>

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

=head2 set_etag

    $resp->set_etag;

Set automatically the C<E-tag> outgoing header.

It does not return any value.

=head2 set_keepalive

    $ret = $resp->set_keepalive;

Returns the keepalive status for this request, by calling L<Apache2::Response/set_keepalive>

It returns true if keepalive can be set, false otherwise.

=head2 set_last_modified

Sets the C<Last-Modified> response header field to the value of the mtime field in the request structure, rationalized to keep it from being in the future, by calling L<Apache2::Response/set_last_modified>

    $resp->set_last_modified( $mtime );

If the C<$mtime> argument is passed, C<< $resp->update_mtime >> will be first run with that argument.

=head2 socket

    my $socket      = $resp->socket;
    my $prev_socket = $resp->socket( $new_socket );

Get or set the client socket and returns a L<APR::Socket> object, by calling L<Apache2::Connection/client_socket>

=head2 sourcemap

Sets or gets the HTTP header field C<SourceMap>

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

=head2 status

Get or set the reply status for the client request, by calling L<Apache2::RequestRec/status>

Normally you would use some L<Apache2::Const> constant, e.g. L<Apache2::Const::REDIRECT>.

From the L<Apache2::RequestRec> documentation:

Usually you will set this value indirectly by returning the status code as the handler's function result. However, there are rare instances when you want to trick Apache into thinking that the module returned an C<Apache2::Const:OK> status code, but ...

    $resp->status( $some_code );
    return( Apache2::Const::OK );

See also C<< $resp->status_line >>, which. if set, overrides C<< $resp->status >>.

=head2 status_line

    my $status_line      = $resp->status_line();
    my $prev_status_line = $resp->status_line( $new_status_line );

Get or sets the response status line. The status line is a string like C<200 Document follows> and it will take precedence over the value specified using the C<< $resp->status() >> described above.

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

When discussing C<< $resp->status >> we have mentioned that sometimes a handler runs to a successful completion, but may need to return a different code, which is the case with the proxy server. Assuming that the proxy handler forwards to the client ...

     $resp->status_line( $response->code() . ' ' . $response->message() );
     return( Apache2::Const::OK );

In this example C<$response> could be for example an L<HTTP::Response> object, if L<LWP::UserAgent> was used to implement the proxy.

This method is also handy when you extend the HTTP protocol and add new response codes. For example you could invent a new error code and tell Apache to use that in the response like so:

     $resp->status_line( "499 We have been FooBared" );
     return( Apache2::Const::OK );

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



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