PHPackages                             lucinda/headers - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [HTTP &amp; Networking](/categories/http)
4. /
5. lucinda/headers

ActiveLibrary[HTTP &amp; Networking](/categories/http)

lucinda/headers
===============

API encapsulating HTTP request and response headers, useful also for cache/cors validation

v3.0.0(1mo ago)01.1k23MITPHPPHP ^8.1

Since Dec 14Pushed 1mo ago1 watchersCompare

[ Source](https://github.com/aherne/headers-api)[ Packagist](https://packagist.org/packages/lucinda/headers)[ Docs](https://github.com/aherne/headers-api)[ RSS](/packages/lucinda-headers/feed)WikiDiscussions master Synced 1w ago

READMEChangelogDependencies (3)Versions (22)Used By (3)

HTTP Headers API
================

[](#http-headers-api)

Table of contents:

- [About](#about)
- [Configuration](#configuration)
- [Binding Points](#binding-points)
- [Execution](#execution)
    - [Initialization](#initialization)
    - [Validation](#validation)
        - [Cache Validation](#cache-validation)
        - [CORS Validation](#cors-validation)
    - [Display](#display)
- [Unit Tests](#unit-tests)
- [Examples](#unit-tests)
- [Reference Guide](#reference-guide)

About
-----

[](#about)

This API encapsulates HTTP request headers received from client and response headers to send back, offering an ability to bind them for cache and CORS validation.

[![diagram](https://camo.githubusercontent.com/86fe7fe7ce24c5f106f2c0536fa32d70dcbe62ba6d884542b97d7b8644b1be2c/68747470733a2f2f7777772e6c7563696e64612d6672616d65776f726b2e636f6d2f686561646572732d6170692e737667)](https://camo.githubusercontent.com/86fe7fe7ce24c5f106f2c0536fa32d70dcbe62ba6d884542b97d7b8644b1be2c/68747470733a2f2f7777772e6c7563696e64612d6672616d65776f726b2e636f6d2f686561646572732d6170692e737667)

That task can be achieved using following steps:

- **[configuration](#configuration)**: setting up an XML file where cache/CORS validation policies are configured
- **[binding points](#binding-points)**: binding user-defined components defined in XML/code to API prototypes in order to gain necessary abilities
- **[initialization](#initialization)**: using [Wrapper](https://github.com/aherne/headers-api/blob/master/src/Wrapper.php) to read above XML into a [Policy](https://github.com/aherne/headers-api/blob/master/src/Policy.php), read HTTP request headers into a [Request](#class-request) then initialize [Response](#class-response), encapsulating HTTP response headers logic.
- **[validation](#validation)**: using above to perform cache/CORS validation and set [Response](#class-response) accordingly
- **[display](#display)**: sending back response to caller using [Response](#class-response) headers compiled above (or set individually by user)

API is fully PSR-4 compliant, only requiring PHP8.1+ interpreter and SimpleXML extension. To quickly see how it works, check:

- **[installation](#installation)**: describes how to install API on your computer, in light of steps above
- **[unit tests](#unit-tests)**: API has 100% Unit Test coverage, using [UnitTest API](https://github.com/aherne/unit-testing) instead of PHPUnit for greater flexibility
- **[examples](#examples)**: shows a deep example of API functionality based on unit tests

All classes inside belong to **Lucinda\\Headers** namespace!

Configuration
-------------

[](#configuration)

To configure this API you must have a XML with following tags inside:

- **[headers](#headers)**: (mandatory) configures the api globally
- **[routes](#routes)**: (optional) configures API based on route requested, required for CORS requests validation

### Headers

[](#headers)

Maximal syntax of this tag is:

```

```

Where:

- **headers**: (mandatory) holds global header validation policies
    - *no\_cache*: (optional) disables HTTP caching for all pages in site (can be 0 or 1; 0 is default), unless specifically activated in [route](#routes) matching page requested
    - *cache\_expiration*: (optional) duration in seconds all page responses in site will be cached without revalidation (must be a positive number)
    - *allow\_credentials*: (optional) whether or not credentials are allowed in CORS requests (can be 0 or 1; 0 is default)
    - *cors\_max\_age*: (optional) duration in seconds CORS responses will be cached (must be a positive number)
    - *allowed\_request\_headers*: (~optional) list of non-standard request headers your site support separated by commas. If none are provided and a CORS *Access-Control-Request-Headers* is requested, headers listed there are assumed as supported!
    - *allowed\_response\_headers*: (optional) list of response headers to expose separated by commas

Example:

```

```

### Routes

[](#routes)

Minimal syntax of this tag is:

```

    ...

```

Where:

- **routes**: (mandatory) holds list of site routes, each identified by a **route** tag
    - **route**: (mandatory) holds policies about a specific route
        - *id*: (mandatory) page relative url (eg: administration)
        - *no\_cache*: (optional) disables HTTP caching for respective route (can be 0 or 1; 0 is default)
        - *cache\_expiration*: (optional) duration in seconds respective route responses in site will be cached without revalidation (must be a positive number)
        - *allowed\_methods*: (optional) list of HTTP request methods supported by respective route. If none are provided and a CORS *Access-Control-Request-Method* is requested, that method is assumed as supported! Example:

```

```

Binding Points
--------------

[](#binding-points)

In order to remain flexible and achieve highest performance, API takes no more assumptions than those absolutely required! It offers developers instead an ability to bind programmatically to its prototypes via validateCache method of [Wrapper](#initialization):

Class PrototypeAbility Gained[Cacheable](#interface-cacheable)(mandatory) HTTP caching by etag or unix time representationsExecution
---------

[](#execution)

### Initialization

[](#initialization)

Now that policies have been configured, they can be bound to request and response using [Wrapper](https://github.com/aherne/headers-api/blob/master/src/Wrapper.php), which creates then works with three objects:

- [Policy](https://github.com/aherne/headers-api/blob/master/src/Policy.php): encapsulates validation policies detected from XML
- [Request](#class-request): encapsulates HTTP request headers received from client in accordance to [RFC-7231](https://tools.ietf.org/html/rfc7231) specification
- [Response](#class-response): encapsulates HTTP response headers to send back to client in accordance to [RFC-7231](https://tools.ietf.org/html/rfc7231) specification

Once set, [Policy](https://github.com/aherne/headers-api/blob/master/src/Policy.php) and [Request](#class-request) become immutable (since *the past cannot be changed*). [Policy](https://github.com/aherne/headers-api/blob/master/src/Policy.php) will only be used internally while [Request](#class-request) will only expose getters. [Response](#class-response), on the other hand, is only instanced while setting remains in developer's responsibility. This is because there is no default linking between request and response headers, unless you are performing **[validation](#validation)**. In light of above, public methods defined by [Wrapper](https://github.com/aherne/headers-api/blob/master/src/Wrapper.php) are:

MethodArgumentsReturnsDescription\_\_construct\\SimpleXMLElement $xml, string $requestedPage, array $requestHeadersvoidCreates Policy based on XML and requested page, sets up Request object based on request headers and initializes Response objectgetRequestvoid[Request](#class-request)Gets object encapsulating HTTP request headers receivedvalidateCache[Cacheable](#interface-cacheable) $cacheable, string $requestMethodintPerforms HTTP cache validation based on user-defined Cacheable representation of requested resourcevalidateCORSstring $origin = nullvoidPerforms CORS request validation based on user-defined origin (*PROTOCOL://HOSTNAME*, eg: ). If none provided, *Access-Control-Allow-Origin* will equal "\*" (all origins supported)!getResponsevoid[Response](#class-response)Gets object encapsulating HTTP response headers to send backObviously, developers need to *know* headers received from client and *set* headers to send back in response, but the way they link depends on your application. There are some particular cases, however, in which request and response headers (and HTTP status) are bound logically:

- **[cache validation](#cache-validation)**: validating [Request](#class-request) headers based on [Policy](https://github.com/aherne/headers-api/blob/master/src/Policy.php) in order to *communicate with client browser cache* and set [Response](#class-response) headers in accordance to
- **[CORS validation](#CORS-validation)**: validating [Request](#class-request) headers based on [Policy](https://github.com/aherne/headers-api/blob/master/src/Policy.php) in order to *answer a CORS request* and set [Response](#class-response) headers in accordance to [CORS](https://fetch.spec.whatwg.org/#cors-protocol) protocol specifications

### Cache Validation

[](#cache-validation)

The purpose of cache validation is to communicate with client browser's cache based on headers and make your site display instantly whenever possible. The language of communication is identified by [RFC-7232](https://tools.ietf.org/html/rfc7232) and [RFC-7234](https://tools.ietf.org/html/rfc7234) specifications both your site (via this API) and your browser must obey.

#### How Cache Validation Works

[](#how-cache-validation-works)

The way it works is too complex to be written here, so what follows next only covers the typical use case. HTTP standard allows you following simple method of communication based on conditional headers:

- client-server: give me X page @ your site
- server-client: here is my response to page X using [200 OK](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/200) status header, identified uniquely by value of [ETag](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag) response header (or last modified at GMT date defined by value of [Last-Modified](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Last-Modified) response header)
- client: ok, I've received response and saved to my cache and link request with [ETag](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag) (or [Last-Modified](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Last-Modified)).
- ...(some time passes)...
- client-server: give me X page @ your site once again. I'll also send formerly received [ETag](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag)/[Last-Modified](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Last-Modified) that matched it as [If-None-Match](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-None-Match)/[If-Modified-Since](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-Modified-Since) request headers, so that you check if page has changed or not!
- server-client: response remained the same, so I'll save your bandwidth and only answer with a [304 Not Modified](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/304) status header and no response body
- client: ok, so I'll display page from my browser's cache
- ...(some time passes)...
- client-server: give me X page @ your site once again plus same request headers
- server-client: response has changed, so this time I'll answer with a [200 OK](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/200) status header, full response body, along with the new [ETag](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag) (or [Last-Modified](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Last-Modified)
- client: ok, I've received response and saved to my cache and link request with the new [ETag](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag) (or [Last-Modified](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Last-Modified)).

Above method has a disadvantage by assuming cache to be *stale*, thus requiring a server roundtrip to check if requested resource has changed (*revalidation*). HTTP standard thus comes with an alternate fastest solution that uses [Cache-Control](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control) response header:

- client-server: give me X page @ your site
- server-client: here is my response to page X and assume it as *fresh* for X seconds defined by **max-age** directive of [Cache-Control](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control)
- client: ok, I've received response and saved to my cache. On future requests to same page, I won't ask server unless X seconds have passed and display response from cache!

The two methods of communication described above are not mutually exclusive. Mature applications use both, with different policies based on page requested: some pages can be assumed to be stale by default, others allow some freshness and finally a few may not even be compatible with caching because output changes on every request

#### How Is Cache Validation Implemented

[](#how-is-cache-validation-implemented)

To set cache-related response headers, using following [Response](#class-response) methods:

HeaderMethod[Cache-Control](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control)setCacheControl[ETag](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag)setEtag[Last-Modified](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Last-Modified)setLastModifiedTimeTo read cache-related request headers, using following [Request](#class-request) methods:

HeaderMethod[Cache-Control](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control)getCacheControl[If-Match](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-Match)getIfMatch[If-None-Match](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-None-Match)getIfNoneMatch[If-Modified-Since](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-Modified-Since)getIfModifiedSince[If-Unmodified-Since](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-Unmodified-Since)getIfUnmodifiedSinceFortunately, all of this is done automatically by API once you are running validateCache method of [Wrapper](https://github.com/aherne/headers-api/blob/master/src/Wrapper.php) object. This method:

- configures [Cache-Control](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control) response header based on namesake request header and XML settings encapsulated by [Policy](https://github.com/aherne/headers-api/blob/master/src/Policy.php)
- sets [ETag](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag) response header based on [Cacheable](#interface-cacheable) representation of requested resource, if exists
- sets [Last-Modified](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Last-Modified) response header based on [Cacheable](#interface-cacheable) representation of requested resource, if exists
- reads cache-related request headers, matches them with [Cacheable](#interface-cacheable) representations and returns [HTTP status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status) according to RFC specifications

So from developers' perspective you only need to:

- (optional) set up *no\_cache* and *cache\_expiration* XML tag attributes according to **[configuration](#configuration)** stage
- (mandatory) implement a [Cacheable](#interface-cacheable) representation of requested resource (the way it can be converted to an etag or last time it was modified)
- (mandatory) use http status code returned by *validateCache* when response is rendered

Possible http status codes returned are:

- [200](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/200): this means response is ok and must come along with a body
- [304](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/304): this means response has not modified and must come without a body
- [412](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/412): this means a conditional header has failed, thus application should exit with an error

### CORS Validation

[](#cors-validation)

**[CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS)** preliminary request is triggered automatically by client browser when it encounteres a situation where *preflight* is mandated by security reasons.

#### How CORS Validation Works

[](#how-cors-validation-works)

What triggers a preflight request falls outside the scope of this API documentation. If you want to learn more, check:

- [simple requests](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#Simple_requests), to understand how can a preflight request be avoided
- [preflighted requests](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#Preflighted_requests), to understand what triggers a preflight request and what happens next

#### How Is CORS Validation Implemented

[](#how-is-cors-validation-implemented)

To set CORS-related response headers, using following [Response](#class-response) methods:

HeaderMethod[Access-Control-Allow-Credentials](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Credentials)setAccessControlAllowCredentials[Access-Control-Allow-Headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Headers)addAccessControlAllowHeader[Access-Control-Allow-Methods](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Methods)addAccessControlAllowMethod[Access-Control-Allow-Origin](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin)setAccessControlAllowOrigin[Access-Control-Expose-Headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers)addAccessControlExposeHeaders[Access-Control-Max-Age](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Max-Age)setAccessControlMaxAgeTo read CORS-related request headers, using following [Request](#class-request) methods:

HeaderMethod[Access-Control-Request-Headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Request-Headers)getAccessControlRequestHeaders[Access-Control-Request-Method](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Request-Method)getAccessControlRequestMethod[Origin](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Origin)getOriginFortunately, all of this is done automatically by API once you are running validateCORS method of [Wrapper](https://github.com/aherne/headers-api/blob/master/src/Wrapper.php) object. This method:

- requires developers to put origin hostname (eg: ) as argument. This cannot be set in XML since it may differ by development environment! If none is provided, any [Origin](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Origin) is considered valid!
- sets CORS response headers based on *allow\_credentials*, *cors\_max\_age*, *allowed\_request\_headers*, *allowed\_response\_headers* XML attributes encapsulated by [Policy](https://github.com/aherne/headers-api/blob/master/src/Policy.php) and CORS request headers received

### Display

[](#display)

Once response headers, status and body (if any) become available, you are finally able to send headers back to client. Example:

```
$wrapper = new Lucinda\Headers\Wrapper("configuration.xml", $_SERVER["REQUEST_URI"], getallheaders());
// developer now reads request headers, sets response headers, compiles $responseBody then applies cache validation:
$httpStatus = $wrapper->validateCache(new MyCacheable($responseBody), $_SERVER["REQUEST_METHOD"]);
// now response is ready for display
http_response_code(httpStatus);
$headers = $wrapper->getResponse()->toArray();
foreach ($headers as $name=>$value) {
    header($name.": ".$value);
}
if ($httpStatus!=304) {
    echo $responseBody;
}
```

Installation
------------

[](#installation)

First choose a folder, associate it to a domain then write this command there using console:

```
composer require lucinda/headers
```

Then create a *configuration.xml* file holding configuration settings (see [configuration](#configuration) above) and a *index.php* file (see [initialization](#initialization) and [display](#display)) in project root with following code:

```
$wrapper = new Lucinda\Headers\Wrapper("configuration.xml", $_SERVER["REQUEST_URI"], getallheaders());
// if request is CORS, response can be done immediately
if ($_SERVER["REQUEST_METHOD"]=="OPTIONS") {
    $wrapper->validateCORS((!empty($_SERVER['HTTPS'])?"https":"http")."://".$_SERVER["SERVER_NAME"]);
    $headers = $wrapper->getResponse()->toArray();
    foreach ($headers as $name=>$value) {
        header($name.": ".$value);
    }
    exit();
}
// developer reads request headers, sets response headers, compiles $responseBody
// developer creates a Cacheable instance (MyCacheable), able to convert $responseBody into an ETag string, then performs cache validation
$httpStatus = $wrapper->validateCache(new MyCacheable($responseBody), $_SERVER["REQUEST_METHOD"]);
// now response is ready for display
http_response_code(httpStatus);
$headers = $wrapper->getResponse()->toArray();
foreach ($headers as $name=>$value) {
    header($name.": ".$value);
}
if ($httpStatus!=304) {
    echo $responseBody;
}
```

Then make sure domain is available to world-wide-web and all request that point to it are rerouted to index.php:

```
RewriteEngine on
RewriteRule ^(.*)$ index.php

```

Unit Tests
----------

[](#unit-tests)

For tests and examples, check following files/folders in API sources:

- [test.php](https://github.com/aherne/headers-api/blob/master/test.php): runs unit tests in console
- [unit-tests.xml](https://github.com/aherne/headers-api/blob/master/unit-tests.xml): sets up unit tests and mocks "loggers" tag
- [tests](https://github.com/aherne/headers-api/blob/master/tests): unit tests for classes from [src](https://github.com/aherne/headers-api/blob/master/src) folder

Examples
--------

[](#examples)

To see examples how request headers are parsed by [Request](#class-request), check its matching [UnitTest](https://github.com/aherne/headers-api/blob/master/tests/RequestTest.php). To see how response headers are set by [Response](#class-response), check its matching [UnitTest](https://github.com/aherne/headers-api/blob/master/tests/ResponseTest.php). To see detailed examples of each headers and understand them in greatest detail, there is no better documentation than the one provided by [Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers)!

Reference Guide
---------------

[](#reference-guide)

### Class Request

[](#class-request)

Class [Request](https://github.com/aherne/headers-api/blob/master/src/Request.php) encapsulates HTTP request headers received from client. Each method inside (minus *\_\_construct*) corresponds to a header:

MethodArgumentsReturnsDescriptionHeader\_\_constructarray $headersvoidReads headers received from client-getAccept()voidarrayGets content types accepted by client[Accept](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept)getAcceptCharset()voidarrayGets charsets accepted by client[Accept-Charset](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Charset)getAcceptEncoding()voidarrayGets encodings accepted by client[Accept-Encoding](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Encoding)getAcceptLanguage()voidarrayGets languages accepted by client[Accept-Language](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Language)getTE()voidarrayGets transfer encodings accepted by client[TE](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/TE)getAuthorization()void?[Request\\Authorization](https://github.com/aherne/headers-api/blob/master/src/Request/Authorization.php)Gets credentials for user authentication[Authorization](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Authorization)getCacheControl()void?[Request\\CacheControl](https://github.com/aherne/headers-api/blob/master/src/Request/CacheControl.php)Gets HTTP caching settings requested by client[Cache-Control](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control)getDNT()voidboolGets whether or not client does not want to be tracked[DNT](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/DNT)getDate()void?intGets UNIX timestamp of date request came with[Date](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Date)getExpect()voidboolGets whether client is about to send a large request[Expect](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Expect)getSaveData()voidbool...[Save-Data](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Save-Data)getForwardedIP()void?stringGets origin IP that got forwarded by proxy[X-Forwarded-For](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For)getForwardedProxy()void?stringGets proxy IP that forwarded client, if present[X-Forwarded-For](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For)getForwardedHost()void?stringGets origin Host that got forwarded by proxy[X-Forwarded-Host](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Host)getForwardedProtocol()void?stringGets origin protocol that got forwarded by proxy[X-Forwarded-Proto](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Proto)getFrom()void?stringGets email address of client[From](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/From)getHost()void?stringGets hostname requested by client[Host](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Host)getIfRangeDate()void?intGets UNIX timestamp of range condition, if present[If-Range](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-Range)getIfRangeEtag()void?stringGets ETag of range condition, if present[If-Range](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-Range)getRange()void?[Request\\Range](https://github.com/aherne/headers-api/blob/master/src/Request/Range.php)Gets bytes range requested by client from a big document[Range](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Range)getReferer()void?stringGets address of the previous web page from which a link to the currently requested page was followed[Referer](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referer)getUserAgent()void?stringGets signature of client browser[User-Agent](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent)getWantDigest()voidarrayGets details of digest client wants in response[Want-Digest](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Want-Digest)getIfMatch()void?stringGets ETag that must condition response to be sent only if matches that of requested resource[If-Match](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-Match)getIfNoneMatch()void?stringGets ETag that must condition response to be sent only if it does not match that of requested resource[If-None-Match](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-None-Match)getIfModifiedSince()void?intGets UNIX timestamp that must condition response to be sent only if matches that of requested resource[If-Modified-Since](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-Modified-Since)getIfUnmodifiedSince()void?intGets UNIX timestamp that must condition response to be sent only if it does not match that of requested resource[If-Unmodified-Since](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-Unmodified-Since)getAccessControlRequestHeaders()voidarrayGets headers that will be requested later as part of a **CORS** preliminary request[Access-Control-Request-Headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Request-Headers)getAccessControlRequestMethod()void?stringGets HTTP method that will be used later as part of a **CORS** preliminary request[Access-Control-Request-Method](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Request-Method)getOrigin()void?stringGets client hostname to validate access to requested resource, sent automatically in **CORS** preliminary request[Origin](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Origin)getCustomHeaders()voidarrayGets all non-standard headers requested by client as header name:value array(any)Following limitations apply:

- multiple ETags are not supported

### Class Response

[](#class-response)

Class [Response](https://github.com/aherne/headers-api/blob/master/src/Response.php) encapsulates HTTP response headers to send back. Each method inside (minus *toArray*) corresponds to a header:

MethodArgumentsReturnsDescriptionHeaderaddAcceptPatchstring $mimeType, string $charset=nullvoidAdds a content type for whom PATCH requests are accepted[Accept-Patch](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Patch)setAcceptRangesbool $valuevoidSets whether or not range requests are accepted[Accept-Ranges](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Ranges)addAllowstring $requestMethodvoidSets a request method server accepts for requested resource[Allow](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Allow)addClearSiteDatastring $directive = "\*"voidSets a browsing data (cookies, storage, cache) to be cleared on client[Clear-Site-Data](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Clear-Site-Data)setCacheControlvoid[Response\\CacheControl](https://github.com/aherne/headers-api/blob/master/src/Response/CacheControl.php)Sets HTTP caching settings to be used by client[Cache-Control](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control)setContentDispositionstring $type[Response\\ContentDisposition](https://github.com/aherne/headers-api/blob/master/src/Response/ContentDisposition.php)Sets how content will be displayed (inline or attachment)[Content-Disposition](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition)addContentEncodingstring $contentEncodingvoidAdds an encoding applied in compressing response[Content-Encoding](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding)addContentLanguagestring $languagevoidAdds a language to associate response with[Content-Language](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Language)setContentLengthint $lengthvoidSets byte length of response[Content-Length](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Length)setContentLocationstring $urlvoidSets alternate uri for the returned data[Content-Location](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Location)setContentRangestring $unit = "bytes", int $start = null, int $end = null, int $size = nullvoidSets returning document range[Content-Range](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Range)setContentTypestring $mimeType, string $charset = nullvoidSets content type of response[Content-Type](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type)setContentTypeOptionsvoidvoidIndicates that content types should not be changed or followed (anti-sniffing solution)[X-Content-Type-Options](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options)setCrossOriginResourcePolicystring $optionvoidSets policy to block no-cors cross-origin/cross-site requests to the given resource[Cross-Origin-Resource-Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Resource-Policy)addDigeststring $algorithm, string $valuevoidAdds a digest to response[Digest](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Digest)setEtagstring $valuevoidSets ETag to associate response to requested resource with[ETag](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag)setExpirationTimeint $unixTimevoidSets UNIX time by which response to be cached by client browser should require revalidation (**deprecated**)[Expires](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Expires)setLastModifiedTimeint $unixTimevoidSets UNIX time requested resource was last modified, to associate response with[Last-Modified](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Last-Modified)setLocationstring $urlvoidSets url client should redirect to.[Location](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Location)setReferrerPolicystring $optionvoidSets much Referer information should be included with requests.[Referrer-Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy)setRentryAfterDateint $unixTimevoidSets UNIX time client should wait before making a follow-up request[Rentry-After](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Rentry-After)setRentryAfterDelayint $delayvoidSets seconds client should wait before making a follow-up request[Rentry-After](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Rentry-After)setSourceMapstring $urlvoidLinks response to a source map enabling the browser to present the reconstructed original in the debugger.[SourceMap](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/SourceMap)setStrictTransportSecurityvoid[Response\\StrictTransportSecurity](https://github.com/aherne/headers-api/blob/master/src/Response/StrictTransportSecurity.php)Informs client that current website only accepts HTTPS[Strict-Transport-Security](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security)addTimingAllowOriginstring $url = "\*"voidAdds an origins allowed to see values from Resource Timing API[Timing-Allow-Origin](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Timing-Allow-Origin)setTkstring $statusvoidSets tracking status that applied to the corresponding request[Tk](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Tk)setTrailerstring $headerNamesvoidAllows the sender to include additional fields at the end of chunked messages[Trailer](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Trailer)addTransferEncodingstring $contentEncodingvoidAdds form of encoding used to safely transfer the payload body to the user.[Transfer-Encoding](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Transfer-Encoding)addVarystring $headerName = "\*"voidAdds a request header to decide in future whether a cached response can be used[Vary](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Vary)setWWWAuthenticatestring $type, string $realm=""[Response\\WwwAuthenticate](https://github.com/aherne/headers-api/blob/master/src/Response/WwwAuthenticate.php)Defines the authentication method that should be used to gain access to a resource[WWW-Authenticate](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/WWW-Authenticate)setDNSPrefetchControlbool $value = truevoidActivates DNS prefetching on client[X-DNS-Prefetch-Control](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-DNS-Prefetch-Control)setFrameOptionsstring $optionvoidIndicates whether or not a browser should be allowed to render a page in a frame / iframe / embed / object[X-Frame-Options](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options)setAccessControlAllowCredentialsvoidvoidAnswers to **CORS** request by signaling credentials are to be exposed[Access-Control-Allow-Credentials](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Credentials)addAccessControlAllowHeaderstring $headerNamevoidAdds allowed request header to answer a **CORS** request[Access-Control-Allow-Headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Headers)addAccessControlAllowMethodstring $requestMethodvoidAdds allowed request method to answer a **CORS** request[Access-Control-Allow-Methods](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Methods)setAccessControlAllowOriginstring $origin = "\*"voidSets allowed origin to answer a **CORS** request[Access-Control-Allow-Origin](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin)addAccessControlExposeHeaderstring $headerName = "\*"voidAdds response header client should expose to answer a **CORS** request[Access-Control-Expose-Headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers)setAccessControlMaxAgeint $durationvoidSets how long response to a CORS request should be cached (in seconds)[Access-Control-Max-Age](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Max-Age)setCustomHeaderstring $name, string $valuevoidSets a custom header by name and value (this **may trigger CORS requests**)(any)toArrayvoidarrayConverts all headers set to a name:value array ready to be sent back to client-Following limitations apply:

- multiple ETags are not supported

### Interface Cacheable

[](#interface-cacheable)

Class [Cacheable](https://github.com/aherne/headers-api/blob/master/src/Cacheable.php) defines blueprints for cache validation via methods:

MethodArgumentsReturnsDescriptiongetEtagvoidstringGets string representation of resource to be cachedgetTimevoidintGets unix time representation of resource to be cachedUsage example:

###  Health Score

53

—

FairBetter than 97% of packages

Maintenance92

Actively maintained with recent releases

Popularity18

Limited adoption so far

Community13

Small or concentrated contributor base

Maturity75

Established project with proven stability

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~115 days

Recently: every ~388 days

Total

21

Last Release

37d ago

Major Versions

v1.1.2 → v2.0.02021-12-28

v1.1.3 → v2.0.12022-01-09

v2.0.3 → v3.0.x-dev2026-04-11

PHP version history (3 changes)v1.0.0PHP ^7.1

v2.0.0PHP ^8.1

v1.0.x-devPHP ^7.1|^8.0

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/3382770?v=4)[Lucian Gabriel Popescu](/maintainers/aherne)[@aherne](https://github.com/aherne)

---

Top Contributors

[![aherne](https://avatars.githubusercontent.com/u/3382770?v=4)](https://github.com/aherne "aherne (41 commits)")

---

Tags

http-headershttp-cachingrequest headersresponse headerscache validationcors validation

### Embed Badge

![Health badge](/badges/lucinda-headers/health.svg)

```
[![Health](https://phpackages.com/badges/lucinda-headers/health.svg)](https://phpackages.com/packages/lucinda-headers)
```

###  Alternatives

[friendsofsymfony/rest-bundle

This Bundle provides various tools to rapidly develop RESTful API's with Symfony

2.8k73.3M319](/packages/friendsofsymfony-rest-bundle)[php-http/discovery

Finds and installs PSR-7, PSR-17, PSR-18 and HTTPlug implementations

1.3k309.5M1.2k](/packages/php-http-discovery)[pusher/pusher-php-server

Library for interacting with the Pusher REST API

1.5k94.8M293](/packages/pusher-pusher-php-server)[react/http

Event-driven, streaming HTTP client and server implementation for ReactPHP

78026.4M414](/packages/react-http)[php-http/curl-client

PSR-18 and HTTPlug Async client with cURL

48347.0M384](/packages/php-http-curl-client)[smi2/phpclickhouse

PHP ClickHouse Client

84310.1M71](/packages/smi2-phpclickhouse)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
