# Application-Defined Metadata

ESS adds support for application-defined metadata/properties associated with a request; specifically, ESS supports the use of the [baggage HTTP header](https://www.w3.org/TR/baggage/) by applications. ESS further expands on this support by providing configuration to add non-baggage request headers to the baggage for propagation within its system.

With ESS’ support application-defined metadata/properties, application-defined metadata can be:

* Included in [log messages](https://docs.inrupt.com/ess/2.3/logging#application-defined-metadata);
* Included in [audit events](https://docs.inrupt.com/security/auditing#audit-event-message-internal-format);
* Returned as response headers.

## Configuration

To support this feature, ESS provides the following configuration options:

{% hint style="info" %}
**Note**\
See [Manage Application-Defined Metadata Propagation](https://docs.inrupt.com/ess/2.3/installation/customize-configurations/customization-logging/manage-app-defined-metadata) to configure using kustomization.
{% endhint %}

{% tabs %}
{% tab title="Allow Configurations" %}

| Configuration                                         | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| ----------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`INRUPT_REQUEST_METADATA_PROPAGATOR_HEADER_ALLOW`** | <p>Adds specified non-baggage request headers to the baggage for propagation (unless also specified in the corresponding <strong><code>\*\_DENY</code></strong> configuration); i.e., support propagation of non-baggage headers as application-defined properties.<br><br>This configuration is case-<strong>insensitive</strong>.</p>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| **`INRUPT_REQUEST_METADATA_REFLECTOR_HEADER_ALLOW`**  | <p>Determines which propagated properties can be returned as response headers (unless also specified in the corresponding <strong><code>\*\_DENY</code></strong> configuration). This configuration is case-<strong>sensitive</strong> to the entries in the propagated baggage.</p><div data-gb-custom-block data-tag="hint" data-style="info" class="hint hint-info"><p><strong>Tip</strong><br>To return a propagated property that was added to the baggage via <strong><code>INRUPT\_REQUEST\_METADATA\_PROPAGATOR\_HEADER\_ALLOW</code></strong>, ensure that the cases of these properties match.<br>When returning application-properties as response headers, you may need to update <strong><code>QUARKUS\_HTTP\_CORS\_EXPOSED\_HEADERS</code></strong> to extend the list of <a href="https://developer.mozilla.org/en-US/docs/Glossary/CORS-safelisted_response_header">CORS-safelisted response headers</a>.</p></div> |
| **`INRUPT_LOGGING_REQUEST_METADATA_ALLOW`**           | <p>Determines which propagated properties can be included in associated <a href="../logging#application-defined-metadata">log messages</a> (unless also specified in the corresponding <strong><code>\*\_DENY</code></strong> configuration). This configuration is case-<strong>sensitive</strong> to the propagated baggage entries.</p><div data-gb-custom-block data-tag="hint" data-style="info" class="hint hint-info"><p><strong>Tip</strong><br>To include a propagated property that was added to the baggage via <strong><code>INRUPT\_REQUEST\_METADATA\_PROPAGATOR\_HEADER\_ALLOW</code></strong>, ensure that the cases of these properties match.</p></div>                                                                                                                                                                                                                                                           |
| **`INRUPT_AUDIT_PRODUCER_REQUEST_METADATA_ALLOW`**    | <p>Determines which propagated properties can be included in associated <a href="../../../../security/auditing#audit-events">audit events</a> (unless also specified in the corresponding <strong><code>\*\_DENY</code></strong> configuration). This configuration is case-<strong>sensitive</strong> to the propagated baggage entries.</p><div data-gb-custom-block data-tag="hint" data-style="info" class="hint hint-info"><p><br><strong>Tip</strong><br>To include a propagated property that was added to the baggage via <strong><code>INRUPT\_REQUEST\_METADATA\_PROPAGATOR\_HEADER\_ALLOW</code></strong>, ensure that the cases of these properties match.</p></div>                                                                                                                                                                                                                                                    |
| {% endtab %}                                          |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |

{% tab title="Deny Configurations" %}

| Configuration                                        | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **`INRUPT_REQUEST_METADATA_PROPAGATOR_HEADER_DENY`** | <p>Excludes specified non-baggage request headers from being added to the baggage.<br><br>This configuration is case-<strong>insensitive</strong>.</p>                                                                                                                                                                                                                                                                                                                                                             |
| **`INRUPT_REQUEST_METADATA_REFLECTOR_HEADER_DENY`**  | <p>Excludes propagated properties from returning as response headers. This configuration is case-<strong>sensitive</strong> to the entries in the propagated baggage.</p><div data-gb-custom-block data-tag="hint" data-style="info" class="hint hint-info"><p><strong>Tip</strong><br>To exclude a propagated property that was added to the baggage via <strong><code>INRUPT\_REQUEST\_METADATA\_PROPAGATOR\_HEADER\_ALLOW</code></strong>, ensure that the cases of these properties match.</p></div>           |
| **INRUPT\_LOGGING\_REQUEST\_METADATA\_DENY**         | <p>Excludes propagated properties from being included in associated log messages. This configuration is case-<strong>sensitive</strong> to the propagated baggage entries.</p><div data-gb-custom-block data-tag="hint" data-style="info" class="hint hint-info"><p><strong>Tip</strong><br>To exclude a propagated property that was added to the baggage via <strong><code>INRUPT\_REQUEST\_METADATA\_PROPAGATOR\_HEADER\_ALLOW</code></strong>, ensure that the cases of these properties match.</p></div>      |
| **`INRUPT_AUDIT_PRODUCER_REQUEST_METADATA_DENY`**    | <p>Determines which propagated properties are included in associated audit events. This configuration is case-<strong>sensitive</strong> to the propagated baggage entries.</p><div data-gb-custom-block data-tag="hint" data-style="info" class="hint hint-info"><p><strong>Tip</strong><br>To exclude a propagated property that was added to the baggage via <strong><code>INRUPT\_REQUEST\_METADATA\_PROPAGATOR\_HEADER\_ALLOW</code></strong>, ensure that the cases of these properties match.<br></p></div> |
| {% endtab %}                                         |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |

{% tab title="Miscellaneous" %}

| Configuration                                             | Description                                                                                                                                                                                                                                                                                                                     |
| --------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`INRUPT_REQUEST_METADATA_PROPAGATOR_HEADER_OVERRIDES`** | <p>Determines, in cases of a property being defined both as a header and as a baggage entry, whether to keep the entry or update/override it with the header value. The default is to keep the baggage entry as is.<br>See <a href="#duplicate-property-definition">Duplicate Property Definition</a> for more information.</p> |
| {% endtab %}                                              |                                                                                                                                                                                                                                                                                                                                 |
| {% endtabs %}                                             |                                                                                                                                                                                                                                                                                                                                 |

## Considerations

### Baggage Header

ESS uses the baggage to support application-defined metadata/property. However, client requests do not need to include a baggage header. If clients send only non-baggage request headers for application-defined properties (as determined by **`INRUPT_REQUEST_METADATA_PROPAGATOR_HEADER_ALLOW`** ), ESS creates a baggage for propagation within its system. However, if a baggage request header exists, ESS adds the non-baggage requests headers (if any, as determined by ESS configuration) to the baggage, and propagates the enhanced baggage. If a property is sent both as a header and as an entry in the baggage, ESS’ default behavior is to not update the baggage entry.

See [Duplicate Property Definition](#duplicate-property-definition) for more information.

### Duplicate Property Definition

The **`INRUPT_REQUEST_METADATA_PROPAGATOR_HEADER_ALLOW`** configuration adds headers to the request’s baggage for propagation within ESS.

If a property is sent both as a header and as an entry in the baggage, ESS’ default behavior is to not replace the baggage entry with the header. To override this behavior and update the baggage entry with the header value, you can set **`INRUPT_REQUEST_METADATA_PROPAGATOR_HEADER_OVERRIDES`** option to true.

### Property Definition by Internal Requests

To process a client request, ESS may make various internal HTTP requests to its microservices. Underlying technologies (such as Kubernetes Ingress) may modify the internal HTTP request header that may affect the metadata values that are included in logs/audit events/response headers.

For example, consider an ESS deployment that uses the Ingress-NGINX controller. Ingress-NGINX itself adds an **`x-request-id`** header to its requests. If the **`INRUPT_REQUEST_METADATA_PROPAGATOR_HEADER_ALLOW`** value includes the **`x-request-id`** header:

* Scenario 1: Duplicate Property Definition
  * An application’s request includes an **`x-request-id`** header.
  * ESS adds the **`x-request-id`** (and its value) as an entry to the baggage (per **`INRUPT_REQUEST_METADATA_PROPAGATOR_HEADER_ALLOW`** ).
  * Then, Ingress-NGINX would send requests with:

    * the aforementioned baggage that contains the **`x-request-id`** entry and
    * an **`x-request-id`** header set by Ingress-NGINX.

    ESS’ default behavior is to leave the baggage **`x-request-id`** entry unchanged. To have ESS override and update the baggage entry with the header value, set **`INRUPT_REQUEST_METADATA_PROPAGATOR_HEADER_OVERRIDES`** to **`true`** .
* Scenario 2: Property Only Defined by Internal Technology
  * An application’s request does not include an **`x-request-id`** header or a baggage header with an **`x-request-id`** entry.
  * Then, Ingress-NGINX sends internal requests with the **`x-request-id`** header. ESS adds this **`x-request-id`** header from Ingress-NGINX to the baggage for propagation within its system.

### Inrupt Client Libraries Header Support

Inrupt’s client libraries ([Java](https://docs.inrupt.com/sdk/java-sdk) and [JavaScript](https://docs.inrupt.com/sdk/javascript-sdk)) support HTTP header handling:

{% hint style="info" %}
**Tip**\
Use ISO-8859-1 for the header values.
{% endhint %}

{% tabs %}
{% tab title="Java Client Lib" %}
To specify headers on all client requests, you can set the headers to the SolidClient/SolidSyncClient. For example:

```java
import com.inrupt.client.Headers;
import com.inrupt.client.solid.SolidClient;
// ...
// ...
final SolidClient mySolidClient = SolidClient.getClientBuilder()
                .headers(Headers.of(Map.of("x-request-id", List.of("7492595229158059")))).build()
                .session(session);
client.read(URI.create(resourceURL), MyExtendedRDF.class)
    .thenAccept(response -> {
       List<String> responseHeaderValues = response.getHeaders().allValues("x-request-id");
       // ...
});
```

To specify headers per request, you can set the headers at the request operation level. For example:

```java
import com.inrupt.client.Headers;
import com.inrupt.client.solid.SolidClient;
// ...
// ...
final SolidClient mySolidClient = SolidClient.getClient().session(session);
Headers myHeaders = Headers.of(Map.of("x-request-id", List.of("7492595229158059")));
mySolidClient.read(URI.create(resourceURL), myHeaders, Expense.class)
   .thenAccept(response -> {
       List<String> responseHeaderValues = response.getHeaders().allValues("x-request-id");
       // ...
});
```

{% endtab %}

{% tab title="JS Client Lib" %}

```javascript
import { Session } from "@inrupt/solid-client-authn-browser";
import { getSolidDataset } from "@inrupt/solid-client";
const session = new Session();
// ... log the session in.
const customizeHeaders = (
  customizedFetch,
  requestHeaders,
  bindResponseHeaders,
) => {
  return async (info, init) => {
    const response = await customizedFetch(info, {
      ...init,
      headers: {
        ...init?.headers,
        ...requestHeaders,
      },
    });
    bindResponseHeaders(response.headers);
    return response;
  };
};
let responseHeaders = new Headers();
const customFetch = customizeHeaders(
  session.fetch,
  {"x-request-id": "7492595229158059"},
  (headers) => {
    // Bind the headers to the current scope.
    responseHeaders = headers;
  },
);
await getSolidDataset(
   "https://storage.example.com/7865026e-5450/some-resource",
   { fetch: customFetch }
);
console.log(responseHeaders.get("x-request-id"));
```

See also:

* [fetch (solid-client-authn-browser)](https://inrupt.github.io/solid-client-authn-js/browser/classes/Session.html#fetch)
* [fetch (solid-client-authn-node)](https://inrupt.github.io/solid-client-authn-js/node/classes/Session.html#fetch)
  {% endtab %}
  {% endtabs %}

### Limits and Restrictions

* Use ISO-8859-1 for the header values.
* Per <https://www.w3.org/TR/baggage/#limits>, ESS limits the baggage string to a maximum of 8192 bytes and to a maximum of 64 list members.
