Skip to content

feat: add support for custom HTTP headers via cfg.customHeaders#21

Open
duydvnganluong wants to merge 3 commits intoDigicreon:mainfrom
duydvnganluong:feature/custom-headers
Open

feat: add support for custom HTTP headers via cfg.customHeaders#21
duydvnganluong wants to merge 3 commits intoDigicreon:mainfrom
duydvnganluong:feature/custom-headers

Conversation

@duydvnganluong
Copy link
Copy Markdown

  • 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

- 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
@Amaury
Copy link
Copy Markdown
Contributor

Amaury commented Apr 30, 2026

Thanks for the contribution! This is a useful and practical addition, and you've kept it nicely minimal at just a handful of lines.

Before merging, we'd like to ask for a few adjustments:

1. Scope of the feature

This is purely a configuration-level shortcut. It's worth noting that the same effect can already be achieved today through the mu:before-fetch event, which exposes the config (including headers) on event.detail. That said, listing headers in the config is much more ergonomic for the common case (auth tokens, CSRF, Accept-Language, etc.), so the syntactic sugar fully justifies itself. We just want this to be clear in the documentation: it complements, rather than replaces, the event-based approach.

2. Rename customHeaders to headers

Since we're already in the µJS config namespace (mu.init({...})), there's no risk of confusion with native fetch headers. headers is shorter and aligns with the rest of the API naming conventions.

3. Drop the typeof === "object" checks

µJS doesn't validate at internal boundaries, only at HTML/user-input boundaries. If a developer passes garbage to mu.init(), the resulting weirdness is on them. A simple if (mu._cfg.headers) is enough; Object.assign won't crash on truthy non-object values, it just does something quirky. Removing these checks is consistent with the rest of the codebase.

4. Invert the merge order in _loadExec

Currently the user's headers are merged after µJS's own headers, meaning a misconfigured headers: {"X-Mu-Mode": "..."} could silently break the server contract. We should merge user headers first, then let µJS's internal headers (X-Requested-With, X-Mu-Mode, X-Mu-Method) take precedence:

var fetchOpts = {
    signal: abortCtrl.signal,
    headers: {}
};
if (mu._cfg.headers)
    Object.assign(fetchOpts.headers, mu._cfg.headers);
fetchOpts.headers["X-Requested-With"] = "XMLHttpRequest";
fetchOpts.headers["X-Mu-Mode"] = cfg.mode;
// ...

This keeps µJS's internal protocol headers safe from accidental override, while still allowing the user to add anything else.

5. Restore the trailing newline

The trailing newline at the end of lib/mu.js was removed; could you put it back? It's a convention and avoids noisy diffs in some tools.

6. Documentation

Please add the new option to README.md. The natural place is in the existing HTTP headers section. We suggest something like:


Custom headers

You can send additional HTTP headers with every request by setting the headers
option in the configuration:

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.


Once these adjustments are in, we'll be happy to merge. Thanks again!

@duydvnganluong
Copy link
Copy Markdown
Author

Hi @Amaury
Thanks for the feedback! I’ve addressed the suggested changes and updated the code accordingly.
Could you please take another look when you have a moment?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants