Creator HTTP Parser

goedemiddag/link-header-parser

Simple way to parse the HTTP Link header.

HTTP Link header parser

A PHP package for parsing the HTTP Link header (RFC 8288).

Requirements#

This package requires PHP 8.3+.

Installation#

You can install the package via composer:

composer require goedemiddag/link-header-parser

Usage#

Parsing a header string#

Pass the raw Link header value to LinkHeaderFactory::fromHeader(). It returns a LinkHeader object keyed by relation type.

use Goedemiddag\LinkHeaderParser\LinkHeaderFactory;

$header = '<https://api.example.com/items?page=2>; rel="next", '
        . '<https://api.example.com/items?page=5>; rel="last"';

$linkHeader = LinkHeaderFactory::fromHeader($header);

$next = $linkHeader->getLink('next'); // Link object, or null
$last = $linkHeader->getLink('last');

echo $next->uri; // https://api.example.com/items?page=2

The full HTTP header line (including the Link: prefix) is accepted as well:

$linkHeader = LinkHeaderFactory::fromHeader('Link: <https://example.com/page/2>; rel="next"');

Each Link carries the URI, the relation type, and any extra parameters such as type, title, or hreflang.

$linkHeader = LinkHeaderFactory::fromHeader(
    '<https://example.com/feed>; rel="alternate"; type="application/rss+xml"; title="RSS"'
);

$link = $linkHeader->getLink('alternate');

echo $link->uri;                       // https://example.com/feed
echo $link->rel;                       // alternate
echo $link->getAttribute('type');      // application/rss+xml
echo $link->getAttribute('title');     // RSS
echo $link->getAttribute('missing');   // null

$link->hasAttribute('type');           // true
$link->hasAttribute('missing');        // false

Dependency injection#

If you want to inject the parser rather than call the static method directly, typehint against LinkHeaderParserInterface:

use Goedemiddag\LinkHeaderParser\LinkHeaderParserInterface;

class MyApiClient
{
    public function __construct(private readonly LinkHeaderParserInterface $parser) {}

    public function nextPageUrl(string $linkHeaderValue): ?string
    {
        return $this->parser->parse($linkHeaderValue)->getLink('next')?->uri;
    }
}

// Wire it up:
$client = new MyApiClient(new LinkHeaderFactory());

Real-world example — GitHub pagination#

// $response is a PSR-7 ResponseInterface
$raw = $response->getHeaderLine('Link');
$linkHeader = LinkHeaderFactory::fromHeader($raw);

if ($next = $linkHeader->getLink('next')) {
    // fetch $next->uri for the next page
}

Behaviour notes#

  • Relation types are case-insensitive. rel="Next" and rel="next" both resolve via getLink('next').
  • Duplicate relation types. When the same rel appears more than once, the last entry wins.
  • Bare token parameters (e.g. ; nocache) have no value and are silently ignored; only name=value pairs are stored as attributes.
  • Attribute names are normalised to lowercase. Type="text/html" is accessible as getAttribute('type').

Testing#

To run the tests, you can use the following command:

composer test

Security#

If you discover any security related issues in this or other packages of Goedemiddag, please email dev@goedemiddag.nl instead of using the issue tracker.