juliangut/negotiate

Negotiation middleware

Fund package maintenance!
juliangut

2.1 2024-03-10 21:18 UTC

README

PHP version Latest Version License

Total Downloads Monthly Downloads

Negotiate

Simple and flexible negotiation middleware using willdurand/negotiation

Installation

Composer

composer require juliangut/negotiate

Usage

Require composer autoload file

require './vendor/autoload.php';

use Jgut\Negotiate\Negotiator;
use Jgut\Negotiate\Scope\Language;
use Jgut\Negotiate\Scope\MediaType;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;

$scopes = [
    new MediaType(['text/html', 'application/json'], 'text/html'),
    new Language(['en', 'es']),
];
/* @var \Psr\Http\Message\ResponseFactoryInterface $responseFactory */

$middleware = new Negotiator($scopes, $responseFactory);
$middleware->setAttributeName('negotiationProvider');

// Request handler
new class () implements RequestHandlerInterface {
    public function handle(ServerRequestInterface $request): ResponseInterface
    {
        $negotiationProvider = $request->getAttribute('negotiationProvider');

        $negotiationProvider->get('Accept-Language'); // \Negotiation\Accept
        $negotiationProvider->getAcceptLanguage(); // \Negotiation\AcceptLanguage
        $negotiationProvider->getAcceptLanguageLine(); // Negotiated language string
        $negotiationProvider->getAcceptCharset(); // null, not defined
        
        // ...
    }
};

Scopes

Encapsulate negotiation in a context, for example media type or character set. Give it a list of priorities, and you are good to go

An optional second parameter controls behaviour if request header is empty or negotiation could not be determined successfully. If set, it will be used to create a \Negotiation\AcceptHeader, A \Jgut\Negotiation\NegotiatorException will be thrown and captured by the middleware otherwise

Middleware

Middleware requires a list of negotiation scopes. Negotiation will take place in the middleware

  • If everything goes well request will have
    • Headers of each scope overridden with negotiation result
    • An attribute with a \Jgut\Negotiate\Provider object with the result of the whole negotiation
  • If negotiation goes south
    • A 415 response will be returned if Content-Type header negotiation fails
    • A 406 response will be returned if any other negotiation fails

Migration from 1.x

  • PHP minimum required version is PHP 8.0
  • Scope's default should be specified in each constructor should it be needed
  • Scope's negotiateRequest now returns modified request (internal change)

Contributing

Found a bug or have a feature request? Please open a new issue. Have a look at existing issues before.

See file CONTRIBUTING.md

License

See file LICENSE included with the source code for a copy of the license terms.