Apache2-API

 view release on metacpan or  search on metacpan

lib/Apache2/API/Headers/AcceptCommon.pm  view on Meta::CPAN

{
    die( ref( $_[0] ) . "::_full_match() not implemented\n" );
}

# Abstract – must be overridden by subclasses.
sub _is_wildcard
{
    die( ref( $_[0] ) . "::_is_wildcard() not implemented\n" );
}

# Abstract – must be overridden by subclasses.
sub _normalize_supported
{
    die( ref( $_[0] ) . "::_normalize_supported() not implemented\n" );
}

# Abstract – must be overridden by subclasses.
sub _parse
{
    die( ref( $_[0] ) . "::_parse() not implemented\n" );
}

# Optional – subclasses may override. Default: no partial match.
sub _partial_match { return(0); }

sub _sorted
{
    my $self = shift( @_ );
    # Cached
    return( $self->{_sorted} ) if( $self->{_sorted} );

    # Decreasing sort
    my @s = sort{ $b->{quality} <=> $a->{quality} } @{$self->{parsed_header}};
    $self->{_sorted} = \@s;
    return( $self->{_sorted} );
}

# Optional – subclasses may override. Default specificity = 0 (languages
# utiliseront 2/1/0 implicitement via ordre; Accept l’overridera).
sub _specificity { return(0); }

1;
# NOTE: POD
__END__

=encoding utf-8

=head1 NAME

Apache2::API::Headers::AcceptCommon - Common base class for parsing HTTP Accept and Accept-Language headers

=head1 SYNOPSIS

    use Apache2::API::Headers::Accept;
    use Apache2::API::Headers::AcceptLanguage;

    my $accept = Apache2::API::Headers::Accept->new( 'text/html;q=0.9,application/json' );
    my $mime = $accept->match( ['text/html', 'application/json'] ); # => 'text/html'

    my $al = Apache2::API::Headers::AcceptLanguage->new( 'fr-FR;q=0.9,en;q=0.8' );
    my $locale = $lang->match( ['en', 'fr-FR'] ); # => 'fr-FR'

=head1 DESCRIPTION

L<Apache2::API::Headers::AcceptCommon> implements a base class for parsing, sorting, and matching rules for HTTP headers that carry I<quality values> (C<q>), such as C<Accept> and C<Accept-Language>. Subclasses provide the domain-specific details:

=over 4

=item * how to parse a token, such as C<type/subtype> vs. language tags

=item * what counts as a full match vs partial match

=item * how to detect wildcards and how C<specificity> is scored

=back

This base class guarantees:

=over 4

=item * Stable, decreasing sort by C<q> (highest first)

=item * Duplicate tokens keep the highest C<q>

=item * C<q=0> excludes a token

=item * Empty/absent header means “everything acceptable” → first supported wins

=item * Return values: empty string on “no match”, C<undef> on error (with L<Module::Generic/error>)

=back

=head1 CONSTRUCTOR

=head2 new( $header, %opts )

Creates a new matcher. C<$header> may be an empty string, but must always be provided. It returns a new object.

If an error occurred, it sets an error that can be retrieved with the L<error method|Module::Generic/error>, and it returns C<undef> in scalar context, or an empty list in list context.

=head1 METHODS

=head2 header

Read-only

Returns the header value initially provided during object instantiation.

=head2 match( \@supported_tokens )

Given an array reference of server-supported tokens, returns the best match as a string, based on quality and specificity.

If none could be found, it returns an empty string, or if an error occurred, it sets an error that can be retrieved with the L<error method|Module::Generic/error>, and it returns C<undef> in scalar context, or an empty list in list context. 

Semantics:

=over 4

=item * If no usable header was provided, the first entry in the array reference of supported tokens is returned.

=item * For each client preference (sorted by C<q> desc), exact matches are preferred over partial ones (as defined by the subclass), and then by specificity (subclasses implement C<_specificity>).



( run in 0.638 second using v1.01-cache-2.11-cpan-5735350b133 )