{"id":20942199,"url":"https://github.com/getstation/electron-better-web-request","last_synced_at":"2025-05-13T23:32:39.911Z","repository":{"id":37217538,"uuid":"164005276","full_name":"getstation/electron-better-web-request","owner":"getstation","description":"Extended behaviour for Electron WebRequest : add multiple listeners capabilities.","archived":false,"fork":false,"pushed_at":"2023-03-02T18:25:31.000Z","size":140,"stargazers_count":3,"open_issues_count":5,"forks_count":2,"subscribers_count":4,"default_branch":"master","last_synced_at":"2023-04-10T02:33:56.417Z","etag":null,"topics":["electron","listener-pattern","webrequest"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/getstation.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-01-03T17:51:47.000Z","updated_at":"2023-04-10T02:33:56.418Z","dependencies_parsed_at":"2023-01-25T13:00:43.220Z","dependency_job_id":null,"html_url":"https://github.com/getstation/electron-better-web-request","commit_stats":null,"previous_names":[],"tags_count":null,"template":null,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/getstation%2Felectron-better-web-request","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/getstation%2Felectron-better-web-request/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/getstation%2Felectron-better-web-request/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/getstation%2Felectron-better-web-request/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/getstation","download_url":"https://codeload.github.com/getstation/electron-better-web-request/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225266565,"owners_count":17447005,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["electron","listener-pattern","webrequest"],"created_at":"2024-11-18T23:24:27.353Z","updated_at":"2024-11-18T23:24:27.919Z","avatar_url":"https://github.com/getstation.png","language":"TypeScript","readme":"# Electron Better Web Request\n\nThis module aims to extend the usage of `electron-web-request` by allowing to bind different listeners to the lifecycle events proposed by Electron. It aligns with the base usage found [here](https://electronjs.org/docs/api/web-request), but work around [this issue](https://github.com/electron/electron/issues/10478) by proposing a multi-listeners mechanism.\n\nIt can be used as a drop-in replacement, and needs to be applied to `Electron.session` (override the default `webRequest`, see [usage](https://github.com/getstation/electron-better-web-request#usage)) to work identically. If used as is, it only uses the last registered listener for a method (retro-compatible). On top of that, the [API](https://github.com/getstation/electron-better-web-request#api) offers ways to add/remove listeners, give them context and define a custom merging strategy for all applicable listeners.\n\n## Getting started\n\n### Install\n\n```bash\nnpm install electron-better-web-request\n```\n\n### Usage\n\n**Override Electron web request**\n```js\nenhanceWebRequest(session)\n```\nCalling `enhanceWebRequest()` with the target `session` will override its `webRequest` with this module. From there, you can keep using it as usual, with all the new benefits.\n\n*⚠ Note :* If you call `enchanceWebRequest` on a session that has already been enhanced, it does NOT override the module again, preserving all the listeners that you previously registered.\n\n**Basic drop in replacement**\n```js\nconst filter = {\n  urls: ['https://*.github.com/*', '*://electron.github.io']\n}\n\nsession.webRequest.onBeforeSendHeaders(filter, (details, callback) =\u003e {\n  details.requestHeaders['User-Agent'] = 'MyAgent'\n  callback({cancel: false, requestHeaders: details.requestHeaders})\n})\n```\n\n**With merging strategy**\n```js\nconst filter = {\n  urls: ['https://*.github.com/*', '*://electron.github.io']\n}\n\n// Add more than one listener...\nsession.webRequest.onBeforeSendHeaders(filter, (details, callback) =\u003e {\n  details.requestHeaders['User-Agent'] = 'MyAgent'\n  callback({cancel: false, requestHeaders: details.requestHeaders})\n})\n\nsession.webRequest.onBeforeSendHeaders(filter, (details, callback) =\u003e {\n  // Alter the web request in another way\n  callback({cancel: false, [...]})\n})\n\n[...]\n\n// ... then define a resolver with your own strategy\nsession.webRequest.setResolver('onBeforeSendHeaders', (listeners) =\u003e {\n  // \"listeners\" is an array of objects representing matching listeners for the current web request\n  // Use context and results to decide what to execute and how to merge\n  // Return your final result\n  \n  // Example : Default resolver implementation\n  // -\u003e modify the web request only with the last registered listener\n  const sorted = listeners.sort((a, b) =\u003e b.context.order - a.context.order)\n  const last = sorted[0]\n  return last.apply()\n})\n```\nCheck the `setResolver()` API details below to see what the array `listeners` is made of.\n\n# API\n\nThis module is built on a set of [new methods](https://github.com/getstation/electron-better-web-request#new-methods) that offer more capabilities with `webRequest`. It also exposes [alias methods](https://github.com/getstation/electron-better-web-request#alias-methods) that comply with the original `webRequest` API (to be retro-compatible). All those aliases are using the new methods under the hood so that you can use either of them indistinctly.  \nBesides, you can find [helper methods](https://github.com/getstation/electron-better-web-request#helper-methods) to help manage the multiple listeners.\n\n## New methods\n\nTo extend the behavior of web requests listeners, the module adds the following methods :\n\n**`addListener(method, filter, action, [context])`**\n- `method` *string*  \n  Name of the targeted method event (onBeforeRequest, onCompleted, etc.)  \n\n- `filter` *Object*  \n  - `urls` *string[]* : An array of URL patterns that is used to filter out the requests which do not match the URL patterns. Same structure as the original filters.\n\n- `action` *Function*  \n  This function is called when the method event has happened. It matches the original signature and is passed with `action(details, [callback])`.\n  - `details` *Object* : Describes the request.\n  - `callback` *Function* : Passed only if the method uses callback (cf with/without callback). Should be called when the listener has done its work, with a `response` object.\n\n- `context` *Object* (optional)  \n  Holds information to tie in the listener context. You can add any properties you need to help your merging strategy (ex: `priority` or `origin`). It is automatically populated with an `order` that indicates the order in which listeners are added. The context is available in the resolver (see below).\n\n  Example :\n  ```\n  {\n    origin: 'pluginX',\n    priority: 10,\n  }\n  ```  \n\n  ---\n  📄 Check [electron webRequest documentation](https://electronjs.org/docs/api/web-request) for more details about `filter`, `actions` (aka `listener` in the doc), `details` and `callback` parameters.\n\nThis function is the primary layer added to the web request. The exposed [alias methods](https://github.com/getstation/electron-better-web-request#alias-methods) are relying on this one to add and keep track of listeners under the hood.\n\nWhen a listener is added (to a method event), it registers it to an internal map, merges the new filters with all pre-existing filters (other listeners), and update the bind with the underlying `electron.webRequest` (injected dependency).\n\nWhen an event happens, the web request (caught in `electron.webRequest`) is passed to the module which sorts the listeners that match the URL and apply all of them.\n\n- If the event method doesn't have a callback, all listeners are applied.\n\n- If the event method has a callback, the web request can be modified, and the resolver is used to determine how the web request should be modified, and send the final result. See the `setResolver()` below for more details.\n\nThe method `addListener()` returns an object describing a listener, such as :  \n```js\n{\n  id: '\u003cgenerated listener id\u003e',\n  urls: [\n    'pattern A',\n    'pattern B',\n  ],\n  action: (details, [callback]) =\u003e {\n    // listener passed as argument\n  },\n  context: {\n    // custom context passed as argument\n    order: 1 // automatically added order\n  }\n}\n```\n\n**`removeListener(method, id)`**  \n- `method` *string*  \n  Targeted method event\n\n- `id` *string*  \n  Listener ID, check the `addListener` method for more details.\n\nStop a listener from being triggered again: remove it from its associated method and remove its filter from the web request event.\n\n**`clearListeners(method)`**  \n- `method` *string*\n  Targeted method event\n\nRemove ALL listeners of a method, clear all associated filters and unsubscribe from this web request event.\n\n**`setResolver(method, resolver)`**\n- `method` *string*  \n  Targeted method event\n\n- `resolver` *Function*  \n  This function will be called with `resolver(listeners)` when the event has happened, and listeners have been matched.  \n  - `listeners` *listeners[]* : Array of object describing listeners with 2 properties :\n    - `context` *Object* : Holds the context previously set when the listener was added.\n    - `apply()` *Function* : Returns a `Promise` that resolves with the modified web request.   \n      The modifications are applied on the original web request received in the event.  \n      The results are isolated from any other applied listener.\n\nRegister a function that is used as a resolver for the given method. It is the role of the resolver to determine how to merge different listener's result into one final result.\n\nThe resolver is used only on event method with a callback. When such a method is triggered, the module sorts all the matching listeners and then calls the resolver with an array of items representing each of them.\n\nThe resolver must return the final `response` object.\n\nExample :\n\n```js\n// Merge all listener modifications and propagate cancel if it occurs\nsetResolver('onBeforeRequest', (listeners) =\u003e {\n  const response = listeners.reduce(async (accumulator, element) =\u003e {\n    if (accumulator.cancel) {\n      return accumulator\n    }\n\n    const result = await element.apply()\n    return { ...accumulator, ...result }\n  }, { cancel: false })\n  \n  return response\n})\n```\n\n## Helper methods\n\n**`hasCallback(method)`**  \n- `method` *string*  \n  Targeted method event\n\nReturn `true` if the given method name has a callback.\n\n**`getListeners()`**  \n\nGet all the listeners, sorted by method.\n\n**`getListenersFor(method)`**  \n- `method` *string*  \n  Targeted method event\n\nGet all the listeners associated with a method.\n\n**`getFilters()`**  \n\nGet all the filters, sorted by method.\n\n**`getFiltersFor(method)`**  \n- `method` *string*  \n  Targeted method event\n\nGet all the filters associated with a method.\n\n## Alias methods\n\nAll the original web request methods are available :\n\nWith callback : `onBeforeRequest` `onBeforeSendHeaders` `onHeadersReceived`  \nWithout callback : `onSendHeaders` `onResponseStarted` `onBeforeRedirect` `onCompleted` `onErrorOccurred`\n\nThey all use the same original signature, plus an additional (and optional) set of options. Under the hood, they rely on [`addListener()`](https://github.com/getstation/electron-better-web-request#new-methods). See an example below for `onBeforeRequest` :\n\n**`onBeforeRequest([filters ,] listener, [context])`**\n\n- `filters` *Object* (optional)\n  - `urls` *string[]* : Array of URL patterns that will be used to filter out the requests that do not match the URL patterns.\n\n  If the `filter` is omitted then all requests will be matched.\n\n- `listener` *Function*  \n  This function will be called with `listener(details, [callback])` when the API's event has happened :\n  - `details` *Object* : describes the request\n  - `listener` *Function* : is passed with a `callback` (for certain events only, cf with/without callback), which should be called with a `response` object when listener has done its work.\n\n- `context` *Object* (optional)  \n  Holds information to tie in the listener context. You can add any properties you need to help your merging strategy (ex: `priority` or `origin`). It is automatically populated with an `order` that indicates the order in which listeners are added. The context is available in the resolver (see above).\n\nOnce again, for more details about `filters` or `listener` please refer to [Electron Web Request documentation](https://electronjs.org/docs/api/web-request).\n\n## Resources\n\n[Electron Web Request documentation](https://electronjs.org/docs/api/web-request)  \nAs you might have guessed since then, this module is based on electron web request and extends it. Most of its mechanics come from there. So the documentation is a good read! Did I say that already?\n\n[Issue about web requests](https://github.com/electron/electron/issues/10478)  \nThis module was first thought to solve this issue and allow more than one listener per event.\n\n[Chrome URL Match Patterns](https://developer.chrome.com/extensions/match_patterns)  \nThe patterns used to match URL is based on Chrome URL pattern matching.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgetstation%2Felectron-better-web-request","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgetstation%2Felectron-better-web-request","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgetstation%2Felectron-better-web-request/lists"}