Apache2-API
view release on metacpan or search on metacpan
lib/Apache2/API/Response.pm view on Meta::CPAN
##----------------------------------------------------------------------------
## Apache2 API Framework - ~/lib/Apache2/API/Response.pm
## Version v0.2.0
## Copyright(c) 2025 DEGUEST Pte. Ltd.
## Author: Jacques Deguest <jack@deguest.jp>
## Created 2023/05/30
## Modified 2025/11/02
## All rights reserved
##
##
## This program is free software; you can redistribute it and/or modify it
## under the same terms as Perl itself.
##----------------------------------------------------------------------------
package Apache2::API::Response;
BEGIN
{
use strict;
use warnings;
warnings::register_categories( 'Apache2::API' );
use parent qw( Module::Generic );
use vars qw( $VERSION );
use Apache2::Request;
use Apache2::Const -compile => qw( :common :http );
use Apache2::Log ();
use Apache2::Response ();
use Apache2::RequestIO ();
use Apache2::RequestRec ();
use Apache2::SubRequest ();
use APR::Request ();
# use APR::Request::Cookie;
use Apache2::API::Status;
use Cookie::Jar;
use Scalar::Util;
use URI::Escape ();
our $VERSION = 'v0.2.0';
};
use strict;
use warnings;
sub init
{
my $self = shift( @_ );
my $r;
$r = shift( @_ ) if( @_ % 2 );
# Which is an Apache2::Request, but inherits everything from Apache2::RequestRec and APR::Request::Apache2
$self->{request} = '';
$self->{checkonly} = 0;
$self->SUPER::init( @_ );
$r ||= $self->{request};
unless( $self->{checkonly} )
{
return( $self->error( "No Apache2::API::Request was provided." ) ) if( !$r );
return( $self->error( "Apache2::API::Request provided ($r) is not an object!" ) ) if( !Scalar::Util::blessed( $r ) );
return( $self->error( "I was expecting an Apache2::API::Request, but instead I got \"$r\"." ) ) if( !$r->isa( 'Apache2::API::Request' ) );
}
return( $self );
}
# Response header: <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Credentials>
sub allow_credentials { return( shift->_set_get_one( 'Access-Control-Allow-Credentials', @_ ) ); }
# Response header <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Headers>
sub allow_headers { return( shift->_set_get_one( 'Access-Control-Allow-Headers', @_ ) ); }
# <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Methods>
sub allow_methods { return( shift->_set_get_one( 'Access-Control-Allow-Methods', @_ ) ); }
# <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin>
sub allow_origin { return( shift->_set_get_one( 'Access-Control-Allow-Origin', @_ ) ); }
# <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Alt-Svc>
sub alt_svc { return( shift->_set_get_multi( 'Alt-Svc', @_ ) ); }
sub bytes_sent { return( shift->_try( '_request', 'bytes_sent' ) ); }
# <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control>
sub cache_control { return( shift->_set_get_one( 'Cache-Control', @_ ) ); }
sub call { return( shift->_try( 'request', @_ ) ); }
# <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Clear-Site-Data>
sub clear_site_data { return( shift->_set_get_multi( 'Clear-Site-Data', @_ ) ); }
# Apache2::Connection
sub connection { return( shift->_try( '_request', 'connection' ) ); }
# Set the http code to be returned, e.g,:
# return( $resp->code( Apache2::Const:HTTP_OK ) );
sub code { return( shift->_try( '_request', 'status', @_ ) ); }
# <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition>
# TODO: More work to be done here like create a disposition method to parse its content
sub content_disposition { return( shift->_set_get_one( 'Content-Disposition', @_ ) ); }
# sub content_encoding { return( shift->_request->content_encoding( @_ ) ); }
sub content_encoding
{
my $self = shift( @_ );
my( $pack, $file, $line ) = caller;
my $sub = ( caller( 1 ) )[3];
# try-catch
local $@;
my $rv = eval
{
return( $self->_request->content_encoding( @_ ) );
};
if( $@ )
{
return( $self->error( "An error occurred while trying to access Apache Request method \"content_encoding\": $@" ) );
}
return( $rv );
}
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Language
sub content_language { return( shift->headers( 'Content-Language', @_ ) ); }
sub content_languages { return( shift->_try( '_request', 'content_languages', @_ ) ); }
# sub content_length { return( shift->headers( 'Content-Length', @_ ) ); }
# https://perl.apache.org/docs/2.0/api/Apache2/Response.html#toc_C_set_content_length_
lib/Apache2/API/Response.pm view on Meta::CPAN
sub _try
{
my $self = shift( @_ );
my $pack = shift( @_ ) || return( $self->error( "No Apache package name was provided to call method" ) );
my $meth = shift( @_ ) || return( $self->error( "No method name was provided to try!" ) );
my $r = Apache2::RequestUtil->request;
# $r->log_error( "Apache2::API::Response::_try to call method \"$meth\" in package \"$pack\"." );
# try-catch
local $@;
my( @rv, $rv );
if( wantarray() )
{
@rv = eval
{
return( $self->$pack->$meth() ) if( !scalar( @_ ) );
return( $self->$pack->$meth( @_ ) );
};
}
else
{
$rv = eval
{
return( $self->$pack->$meth() ) if( !scalar( @_ ) );
return( $self->$pack->$meth( @_ ) );
};
}
if( $@ )
{
return( $self->error( "An error occurred while trying to call Apache ", ucfirst( $pack ), " method \"$meth\": $@" ) );
}
return( wantarray() ? @rv : $rv );
}
# NOTE: sub FREEZE is inherited
sub STORABLE_freeze { CORE::return( CORE::shift->FREEZE( @_ ) ); }
sub STORABLE_thaw { CORE::return( CORE::shift->THAW( @_ ) ); }
# NOTE: sub THAW is inherited
1;
# NOTE: POD
__END__
=encoding utf8
=head1 NAME
Apache2::API::Response - Apache2 Outgoing Response Access and Manipulation
=head1 SYNOPSIS
use Apache2::API::Response;
# $r is the Apache2::RequestRec object
my $resp = Apache2::API::Response->new( request => $r, debug => 1 );
# or, to test it outside of a modperl environment:
my $resp = Apache2::API::Response->new( request => $r, debug => 1, checkonly => 1 );
# Access-Control-Allow-Credentials
my $cred = $resp->allow_credentials;
# Access-Control-Allow-Headers
$resp->allow_headers( $custom_header );
# Access-Control-Allow-Methods
$resp->allow_methods( $method );
$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 );
lib/Apache2/API/Response.pm view on Meta::CPAN
# 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
=head1 METHODS
=head2 allow_credentials
Sets or gets the HTTP header field C<Access-Control-Allow-Credentials>
See L<https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Credentials>
=head2 allow_headers
Sets or gets the HTTP header field C<Access-Control-Allow-Credentials>
See L<https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Headers>
=head2 allow_methods
Sets or gets the HTTP header field C<Access-Control-Allow-Methods>
See L<https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Methods>
=head2 allow_origin
Sets or gets the HTTP header field C<Access-Control-Allow-Origin>
See L<https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin>
=head2 alt_svc
Sets or gets the HTTP header field C<Alt-Svc>
See L<https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Alt-Svc>
=head2 bytes_sent
The number of bytes sent to the client, handy for logging, etc.
This calls L<Apache2::RequestRec/bytes_sent>
=head2 cache_control
Sets or gets the HTTP header field C<Cache-Control>
See L<https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control>
=head2 call
Provided with an Apache2 API method name, and optionally with some additional arguments, and this will call that Apache2 method and return its result.
This is designed to allow you to call arbitrary Apache2 method that, possibly, are not covered here.
For example:
$resp->call( 'send_error_response' );
It returns whatever value this call returns.
=head2 clear_site_data
Sets or gets the HTTP header field C<Clear-Site-Data>
See L<https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Clear-Site-Data>
=head2 code
( run in 0.741 second using v1.01-cache-2.11-cpan-140bd7fdf52 )