-
Notifications
You must be signed in to change notification settings - Fork 30
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add trsuted-replace-fetch-response scriptlet
- Loading branch information
1 parent
932ff82
commit f96716d
Showing
1 changed file
with
172 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
import { | ||
hit, | ||
getFetchData, | ||
objectToString, | ||
parseMatchProps, | ||
validateParsedData, | ||
getMatchPropsData, | ||
noopPromiseResolve, | ||
getWildcardSymbol, | ||
// following helpers should be imported and injected | ||
// because they are used by helpers above | ||
toRegExp, | ||
isValidStrPattern, | ||
escapeRegExp, | ||
isEmptyObject, | ||
getRequestData, | ||
getObjectEntries, | ||
getObjectFromEntries, | ||
} from '../helpers/index'; | ||
|
||
/* eslint-disable max-len */ | ||
/** | ||
* @scriptlet trusted-replace-fetch-response | ||
* | ||
* @description // FIXME | ||
* Prevents `fetch` calls if **all** given parameters match | ||
* | ||
* Related UBO scriptlet: | ||
* https://github.com/gorhill/uBlock/wiki/Resources-Library#no-fetch-ifjs- | ||
* | ||
* **Syntax** | ||
* ``` | ||
* example.org#%#//scriptlet('prevent-fetch'[, propsToMatch[, responseBody]]) | ||
* ``` | ||
* | ||
* - `propsToMatch` - optional, string of space-separated properties to match; possible props: | ||
* - string or regular expression for matching the URL passed to fetch call; empty string, wildcard `*` or invalid regular expression will match all fetch calls | ||
* - colon-separated pairs `name:value` where | ||
* - `name` is [`init` option name](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#parameters) | ||
* - `value` is string or regular expression for matching the value of the option passed to fetch call; invalid regular expression will cause any value matching | ||
* - responseBody - optional, string for defining response body value, defaults to `emptyObj`. Possible values: | ||
* - `emptyObj` - empty object | ||
* - `emptyArr` - empty array | ||
* > Usage with no arguments will log fetch calls to browser console; | ||
* which is useful for debugging but permitted for production filter lists. | ||
* | ||
* **Examples** | ||
* 1. Log all fetch calls | ||
* ``` | ||
* example.org#%#//scriptlet('prevent-fetch') | ||
* ``` | ||
* | ||
* 2. Prevent all fetch calls | ||
* ``` | ||
* example.org#%#//scriptlet('prevent-fetch', '*') | ||
* OR | ||
* example.org#%#//scriptlet('prevent-fetch', '') | ||
* ``` | ||
* | ||
* 3. Prevent fetch call for specific url | ||
* ``` | ||
* example.org#%#//scriptlet('prevent-fetch', '/url\\.part/') | ||
* ``` | ||
* | ||
* 4. Prevent fetch call for specific request method | ||
* ``` | ||
* example.org#%#//scriptlet('prevent-fetch', 'method:HEAD') | ||
* ``` | ||
* | ||
* 5. Prevent fetch call for specific url and request method | ||
* ``` | ||
* example.org#%#//scriptlet('prevent-fetch', '/specified_url_part/ method:/HEAD|GET/') | ||
* ``` | ||
* | ||
* 6. Prevent fetch call and specify response body value | ||
* ``` | ||
* ! Specify response body for fetch call to a specific url | ||
* example.org#%#//scriptlet('prevent-fetch', '/specified_url_part/ method:/HEAD|GET/', 'emptyArr') | ||
* | ||
* ! Specify response body for all fetch calls | ||
* example.org#%#//scriptlet('prevent-fetch', '', 'emptyArr') | ||
* ``` | ||
*/ | ||
/* eslint-enable max-len */ | ||
export function trustedReplaceFetchResponse(source, pattern = '', replacement = '', propsToMatch = '') { | ||
// do nothing if browser does not support fetch or Proxy (e.g. Internet Explorer) | ||
// https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch | ||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy | ||
if (typeof fetch === 'undefined' | ||
|| typeof Proxy === 'undefined' | ||
|| typeof Response === 'undefined') { | ||
return; | ||
} | ||
|
||
if (typeof pattern === 'undefined' || typeof replacement === 'undefined') { | ||
return; | ||
} | ||
|
||
// eslint-disable-next-line no-console | ||
const log = console.log.bind(console); | ||
const nativeFetch = window.fetch; | ||
|
||
let shouldPrevent = false; | ||
let fetchData; | ||
|
||
const handlerWrapper = (target, thisArg, args) => { | ||
fetchData = getFetchData(args); | ||
|
||
if (typeof propsToMatch === 'undefined') { | ||
// log if no propsToMatch given | ||
const logMessage = `log: fetch( ${objectToString(fetchData)} )`; | ||
log(source, logMessage); | ||
} else if (propsToMatch === '' || propsToMatch === getWildcardSymbol()) { | ||
// prevent all fetch calls | ||
shouldPrevent = true; | ||
} else { | ||
const parsedData = parseMatchProps(propsToMatch); | ||
if (!validateParsedData(parsedData)) { | ||
// eslint-disable-next-line no-console | ||
console.log(`Invalid parameter: ${propsToMatch}`); | ||
shouldPrevent = false; | ||
} else { | ||
const matchData = getMatchPropsData(parsedData); | ||
// prevent only if all props match | ||
shouldPrevent = Object.keys(matchData) | ||
.every((matchKey) => { | ||
const matchValue = matchData[matchKey]; | ||
return Object.prototype.hasOwnProperty.call(fetchData, matchKey) | ||
&& matchValue.test(fetchData[matchKey]); | ||
}); | ||
} | ||
} | ||
|
||
if (shouldPrevent) { | ||
// REPLACE CONTENT HERE | ||
|
||
|
||
hit(source); | ||
} | ||
|
||
return Reflect.apply(target, thisArg, args); | ||
}; | ||
|
||
const fetchHandler = { | ||
apply: handlerWrapper, | ||
}; | ||
|
||
fetch = new Proxy(fetch, fetchHandler); // eslint-disable-line no-global-assign | ||
} | ||
|
||
trustedReplaceFetchResponse.names = [ | ||
'trusted-replace-fetch-response', | ||
|
||
]; | ||
|
||
trustedReplaceFetchResponse.injections = [ | ||
hit, | ||
getFetchData, | ||
objectToString, | ||
parseMatchProps, | ||
validateParsedData, | ||
getMatchPropsData, | ||
noopPromiseResolve, | ||
getWildcardSymbol, | ||
toRegExp, | ||
isValidStrPattern, | ||
escapeRegExp, | ||
isEmptyObject, | ||
getRequestData, | ||
getObjectEntries, | ||
getObjectFromEntries, | ||
]; |