oasys/negotiator

Strict RFC-compliant HTTP content negotiator with extended language filtering support

Maintainers

Package info

github.com/kweensey/oasys-negotiator

pkg:composer/oasys/negotiator

Statistics

Installs: 1

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.0.0 2026-03-16 15:17 UTC

This package is not auto-updated.

Last update: 2026-03-31 14:07:42 UTC


README

Tests Latest Stable Version PHP Version Require License

Strict RFC-compliant HTTP content negotiator.

Implements HTTP negotiation semantics defined in RFC 9110 and language matching defined in RFC 4647.

  • Negotiation for Accept, Accept-Language, Accept-Encoding, and Accept-Charset headers
  • Deterministic tie-breaking and stable selection
  • Basic and extended language filtering
  • Strict token and quoted-string parsing with correct handling of quoted parameters and escaped characters
  • Quality (q) weighting and wildcard handling
  • Media range specificity precedence (text/plain;charset=utf-8 > text/plain > text/* > */*)

Installation

composer require oasys/negotiator

Quick start

<?php declare(strict_types=1);

use Oasys\Http\Negotiator;

$result = Negotiator::content(
    header: 'application/json, text/html;q=0.8',
    supported: ['text/html', 'application/json']
);
'application/json'

Matching

Selection is determined by:

  1. quality
  2. match specificity
  3. header order
  4. supported list order

Accept header

$result = Negotiator::content(
    'text/*;q=0.3, text/plain;q=0.7, text/plain;format=flowed, */*;q=0.5',
    ['text/plain', 'text/plain;format=flowed', 'text/html']
);
'text/plain;format=flowed'

Accept-Language header

Extended language filtering

$result = Negotiator::language(
    'de-*-DE, fr;q=0.5',
    ['de-Latn-DE', 'fr-FR']
);
'de-Latn-DE'

Basic language filtering

$result = Negotiator::language(
    'en, fr;q=0.5',
    ['en-US', 'fr-FR'],
    extendedFiltering: false
);
'en-US'

Accept-Encoding header

$result = Negotiator::encoding(
    'gzip, br',
    ['7z']
);
'identity'

If your application does not support unencoded content, you can disable it by setting identity: false.

$result = Negotiator::encoding(
    'gzip, br',
    ['7z'],
    identity: false
);
null

Accept-Charset header

$result = Negotiator::charset(
    'utf-8, windows-1250;q=0.5, *;q=0.1',
    ['windows-1250', 'utf-8']
);
'utf-8'

Design notes

  • Matching is case-insensitive
  • Whitespace around members and separators is ignored
  • Invalid header members are dropped; invalid supported values throw an exception
  • Duplicate header members are evaluated individually; members with duplicate parameters are dropped
  • Best match is formatted exactly as listed in supported values
  • No match returns null