From 16ef210a5a315bf9475f07c71cb61b2a9df7825b Mon Sep 17 00:00:00 2001 From: Duy Dinh Date: Wed, 29 Apr 2026 16:57:26 +0700 Subject: [PATCH 1/3] feat: add support for custom HTTP headers via cfg.customHeaders MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Support global custom headers via mu.init({customHeaders: {...}}) - Support per-request custom headers in mu.load({customHeaders: {...}}) - Merge custom headers with default µJS headers in both prefetch and main fetch - Custom headers work with all injection modes and trigger types - Allows servers to receive custom headers for authentication, tracking, or API-specific requirements --- lib/mu.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/mu.js b/lib/mu.js index 46fd882..52a97ca 100644 --- a/lib/mu.js +++ b/lib/mu.js @@ -984,8 +984,12 @@ var mu = mu || new function() { return; // Store the fetch promise so _loadExec can await it (even if still in-flight) var fetchUrl = mu._cfg.urlPrefix ? mu._cfg.urlPrefix + url : url; + var prefetchHeaders = {"X-Requested-With": "XMLHttpRequest", "X-Mu-Prefetch": "1"}; + // Merge custom headers if provided + if (mu._cfg.customHeaders && typeof mu._cfg.customHeaders === "object") + Object.assign(prefetchHeaders, mu._cfg.customHeaders); var promise = fetch(fetchUrl, { - headers: {"X-Requested-With": "XMLHttpRequest", "X-Mu-Prefetch": "1"}, + headers: prefetchHeaders, priority: "low" }) .then(function(r) { return (r.ok ? r.text() : null); }) @@ -1323,6 +1327,9 @@ var mu = mu || new function() { if (cfg.postData) fetchOpts.body = cfg.postData; } + // Merge custom headers if provided + if (cfg.customHeaders && typeof cfg.customHeaders === "object") + Object.assign(fetchOpts.headers, cfg.customHeaders); resp = await fetch(fetchUrl, fetchOpts); if (!resp.ok) { mu._emit("mu:fetch-error", {url: url, fetchUrl: fetchUrl, status: resp.status, response: resp}); @@ -1723,4 +1730,3 @@ var mu = mu || new function() { return (document.dispatchEvent(ev)); }; }; - From 48e655076fffe673a0ff724e6fd29c0b078eeb7a Mon Sep 17 00:00:00 2001 From: Duy Dinh Date: Thu, 30 Apr 2026 17:56:46 +0700 Subject: [PATCH 2/3] improve the code based on suggestions --- README.md | 18 +++++++++++++++++- lib/mu.js | 19 ++++++++++--------- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index e162357..b266101 100644 --- a/README.md +++ b/README.md @@ -341,6 +341,23 @@ Supported values: `get`, `post`, `put`, `patch`, `delete`, `sse`. These headers allow the server to detect µJS requests and adapt its response (e.g. return a fragment instead of a full page, skip analytics, return lighter content on prefetch). +### Custom headers + +You can send additional HTTP headers with every request by setting the `headers` option in the configuration: + +```javascript +mu.init({ + headers: { + "Authorization": "Bearer " + myToken, + "Accept-Language": "fr-FR" + } +}); +``` + +These headers are merged into both regular and prefetch requests. µJS's internal headers (`X-Requested-With`, `X-Mu-Mode`, `X-Mu-Method`, `X-Mu-Prefetch`) always take precedence and cannot be overridden through this option. + +For per-request or dynamic headers (e.g. a fresh CSRF token on each request), listen to the `mu:before-fetch` event and modify `event.detail.config` instead. + ## Triggers @@ -773,4 +790,3 @@ DOM morphing requires a separate library (idiomorph recommended). Without it, µ **µJS** is developed by [Digicreon](https://github.com/Digicreon). Website: [mujs.org](https://mujs.org) - diff --git a/lib/mu.js b/lib/mu.js index 52a97ca..90c8ffc 100644 --- a/lib/mu.js +++ b/lib/mu.js @@ -984,10 +984,12 @@ var mu = mu || new function() { return; // Store the fetch promise so _loadExec can await it (even if still in-flight) var fetchUrl = mu._cfg.urlPrefix ? mu._cfg.urlPrefix + url : url; - var prefetchHeaders = {"X-Requested-With": "XMLHttpRequest", "X-Mu-Prefetch": "1"}; + var prefetchHeaders = {}; // Merge custom headers if provided - if (mu._cfg.customHeaders && typeof mu._cfg.customHeaders === "object") - Object.assign(prefetchHeaders, mu._cfg.customHeaders); + if (mu._cfg.headers) + Object.assign(prefetchHeaders, mu._cfg.headers); + prefetchHeaders["X-Requested-With"] = "XMLHttpRequest"; + prefetchHeaders["X-Mu-Prefetch"] = "1"; var promise = fetch(fetchUrl, { headers: prefetchHeaders, priority: "low" @@ -1317,10 +1319,7 @@ var mu = mu || new function() { // Build fetch options var fetchOpts = { signal: abortCtrl.signal, - headers: { - "X-Requested-With": "XMLHttpRequest", - "X-Mu-Mode": cfg.mode - } + headers: {} }; if (method !== "get") { fetchOpts.headers["X-Mu-Method"] = fetchOpts.method = method.toUpperCase(); @@ -1328,8 +1327,10 @@ var mu = mu || new function() { fetchOpts.body = cfg.postData; } // Merge custom headers if provided - if (cfg.customHeaders && typeof cfg.customHeaders === "object") - Object.assign(fetchOpts.headers, cfg.customHeaders); + if (cfg.headers) + Object.assign(fetchOpts.headers, cfg.headers); + fetchOpts.headers["X-Requested-With"] = "XMLHttpRequest"; + fetchOpts.headers["X-Mu-Mode"] = cfg.mode; resp = await fetch(fetchUrl, fetchOpts); if (!resp.ok) { mu._emit("mu:fetch-error", {url: url, fetchUrl: fetchUrl, status: resp.status, response: resp}); From f93d5fa04399b218157f77fa2acf04c736e539e6 Mon Sep 17 00:00:00 2001 From: Duy Dinh Date: Thu, 30 Apr 2026 17:58:47 +0700 Subject: [PATCH 3/3] Restore the trailing newline --- README.md | 1 + lib/mu.js | 1 + 2 files changed, 2 insertions(+) diff --git a/README.md b/README.md index b266101..e807069 100644 --- a/README.md +++ b/README.md @@ -790,3 +790,4 @@ DOM morphing requires a separate library (idiomorph recommended). Without it, µ **µJS** is developed by [Digicreon](https://github.com/Digicreon). Website: [mujs.org](https://mujs.org) + diff --git a/lib/mu.js b/lib/mu.js index 90c8ffc..794f6b3 100644 --- a/lib/mu.js +++ b/lib/mu.js @@ -1731,3 +1731,4 @@ var mu = mu || new function() { return (document.dispatchEvent(ev)); }; }; +