Request Headers API: Reference Examples

This reference provides two concrete examples for dynamic request header manipulation via iodesktop.customHeaders.

Prerequisite

Enable header manipulation in the app definition:

{
  "allowHeadersManipulation": true
}

Example 1: Different REST Endpoints From the Same App Split by Request Type

Scenario

A single app sends requests to two REST endpoints:

  • endpoint A is called via fetch();

  • endpoint B is called via XMLHttpRequest.

Rule Design

Use a single header rule if both requests are network XHR-class requests.

  • The filter supports types, including "xhr".

  • There is no separate "fetch" request type value.

  • Therefore, both fetch and XMLHttpRequest requests are matched with types: ["xhr"].

Use separate rules only when header values or URL targeting must differ.

Single-Rule Example

const header = {
  "X-Channel": "market-data"
};

const filter = {
  applications: ["clientlist"],
  urls: [
    "http://localhost:3000/api/fetch-endpoint", // called via fetch
    "http://localhost:3000/api/xhr-endpoint"  // called via XMLHttpRequest
  ],
  types: ["xhr"]
};

const ruleId = await iodesktop.customHeaders.set(header, filter);

Request Calls Example (Fetch + XMLHttpRequest)

// Example request made with fetch().
const fetchResponse = await fetch("http://localhost:3000/api/fetch-endpoint", {
  method: "GET"
});

const fetchData = await fetchResponse.json();

// Example request made with XMLHttpRequest.
const xhrData = await new Promise((resolve, reject) => {
  const xhr = new XMLHttpRequest();

  xhr.open("GET", "http://localhost:3000/api/xhr-endpoint", true);

  xhr.onload = () => {
    if (xhr.status >= 200 && xhr.status < 300) {
      try {
        resolve(JSON.parse(xhr.responseText));
      } catch {
        resolve(xhr.responseText);
      }
      return;
    }

    reject(new Error(`XHR request failed with status ${xhr.status}`));
  };

  xhr.onerror = () => reject(new Error("Network error during XHR request"));
  xhr.send();
});

Both calls are matched by types: ["xhr"] and will receive the custom headers from the same rule.

When Separate Rules Are Needed

Create separate rules if:

  • each endpoint needs different header values;

  • each endpoint needs a different target scope (for example, URL pattern differences).

Example 2: Multiple Header Rules Matching the Same Request

Scenario

Two custom header rules match the same outgoing request.

Behavior

When multiple rules match:

  • all matching rules are applied;

  • header keys are merged;

  • if multiple rules set the same header key, the later-added rule overwrites the earlier value.

Overlapping-Rules Example

// Rule 1
const id1 = await iodesktop.customHeaders.set(
  {
    "X-Tenant": "alpha",
    "X-Trace": "rule-1"
  },
  {
    applications: ["clientlist"],
    urls: ["https://api.example.com/*"],
    types: ["xhr"]
  }
);

// Rule 2 (also matches some of the same requests)
const id2 = await iodesktop.customHeaders.set(
  {
    "X-Trace": "rule-2", // same key as Rule 1
    "X-Region": "eu-west-1"
  },
  {
    applications: ["clientlist"],
    urls: ["https://api.example.com/orders/*"],
    types: ["xhr"]
  }
);

For a request to https://api.example.com/orders/123, the effective headers are:

  • X-Tenant: alpha

  • X-Trace: rule-2 (overwritten by the later-added rule)

  • X-Region: eu-west-1

Optional Cleanup

await iodesktop.customHeaders.remove(id1);
await iodesktop.customHeaders.remove(id2);

Notes

  • applications filtering works for app type "window".

  • For non-window app types, use urls filtering.

  • Passing an empty array for a filter property prevents matches for that property.

Related Documentation

io.Connect Desktop Documentation - More > APIs