Skip to content

Commit

Permalink
Create listener service and matcher service (partial) (#14)
Browse files Browse the repository at this point in the history
* Create listener service and matcher service (partial)

* Add Cache service

---------

Co-authored-by: Baghdasaryan <[email protected]>
  • Loading branch information
vvmgev and Baghdasaryan authored Aug 10, 2023
1 parent 2cfbf76 commit 28c2ead
Show file tree
Hide file tree
Showing 18 changed files with 558 additions and 306 deletions.
160 changes: 78 additions & 82 deletions src/cotentScript/cotentScript.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// @ts-nocheck
import { NAMESPACE } from 'src/models/contants';
import { MatchType } from 'src/models/formFieldModel';
import MatcherService from 'src/services/MatcherService';

((NAMESPACE) => {
window[NAMESPACE] = window[NAMESPACE] || {};
Expand All @@ -10,103 +10,99 @@ import { MatchType } from 'src/models/formFieldModel';
window[NAMESPACE].start = () => {
if(window[NAMESPACE].gotRules) return;
window[NAMESPACE].gotRules = true;
};

const getAbsoluteUrl = (url: string): string => {
const dummyLink = document.createElement("a");
dummyLink.href = url;
return dummyLink.href;
};

const getMatchedRuleByUrl = url => {
const absoluteUrl = getAbsoluteUrl(url);
return window[NAMESPACE].rules.find(rule => {
if(rule.matchType === MatchType.CONTAIN) {
return absoluteUrl.includes(rule.source);
}
if(rule.matchType === MatchType.EQUAL) {
return absoluteUrl === rule.source;
}
});
startIntercept();
};

const startIntercept = () => {
const getAbsoluteUrl = (url: string): string => {
const dummyLink = document.createElement("a");
dummyLink.href = url;
return dummyLink.href;
};

const getMatchedRuleByUrl = url => {
const absoluteUrl = getAbsoluteUrl(url);
return window[NAMESPACE].rules.find(rule => MatcherService.isUrlsMatch(rule.source, absoluteUrl, rule.matchType));
};

// Fetch interceptor
const originalFetch = window.fetch;
window.fetch = async (...args) => {
const [resource, options = {}] = args;
const getOriginalResponse = () => originalFetch(...args);
// Fetch interceptor
const originalFetch = window.fetch;
window.fetch = async (...args) => {
const [resource, options = {}] = args;
const getOriginalResponse = () => originalFetch(...args);

let request;
let request;

if (resource instanceof Request) {
request = resource.clone();
} else {
request = new Request(resource.toString(), options);
}
if (resource instanceof Request) {
request = resource.clone();
} else {
request = new Request(resource.toString(), options);
}

const matchedRule = getMatchedRuleByUrl(request.url);
const matchedRule = getMatchedRuleByUrl(request.url);

if(["GET", "HEAD"].includes(request.method.toUpperCase()) || !matchedRule) {
try{
return await getOriginalResponse();
if(["GET", "HEAD"].includes(request.method.toUpperCase()) || !matchedRule) {
try{
return await getOriginalResponse();
} catch (error) {
return Promise.reject(error);
}
}

request = new Request(request.url, {
method: request.method,
body: matchedRule.editorValue,
headers: request.headers,
referrer: request.referrer,
referrerPolicy: request.referrerPolicy,
mode: request.mode,
credentials: request.credentials,
cache: request.cache,
redirect: request.redirect,
integrity: request.integrity,
signal: request.signal,
});

try {
return await originalFetch(request.clone());
} catch (error) {
return Promise.reject(error);
}
}

request = new Request(request.url, {
method: request.method,
body: matchedRule.editorValue,
headers: request.headers,
referrer: request.referrer,
referrerPolicy: request.referrerPolicy,
mode: request.mode,
credentials: request.credentials,
cache: request.cache,
redirect: request.redirect,
integrity: request.integrity,
signal: request.signal,
// XMLHttpRequest interceptor
const XHR = XMLHttpRequest;
XMLHttpRequest = function () {
const xhr = new XHR();
return xhr;
};
XMLHttpRequest.prototype = XHR.prototype;
Object.entries(XHR).map(([key, val]) => {
XMLHttpRequest[key] = val;
});

try {
return await originalFetch(request.clone());
} catch (error) {
return Promise.reject(error);
}
}
const open = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function (method, url) {
this.method = method;
this.requestURL = url;
open.apply(this, arguments);
};

// XMLHttpRequest interceptor
const XHR = XMLHttpRequest;
XMLHttpRequest = function () {
const xhr = new XHR();
return xhr;
};
XMLHttpRequest.prototype = XHR.prototype;
Object.entries(XHR).map(([key, val]) => {
XMLHttpRequest[key] = val;
});
const send = XMLHttpRequest.prototype.send;
XMLHttpRequest.prototype.send = function (data) {
const matchedRule = getMatchedRuleByUrl(this.requestURL);
const requestBody = matchedRule ? matchedRule.editorValue : data;
this.requestData = requestBody;
send.call(this, requestBody);
};

const open = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function (method, url) {
this.method = method;
this.requestURL = url;
open.apply(this, arguments);
};

const send = XMLHttpRequest.prototype.send;
XMLHttpRequest.prototype.send = function (data) {
const matchedRule = getMatchedRuleByUrl(this.requestURL);
const requestBody = matchedRule ? matchedRule.editorValue : data;
this.requestData = requestBody;
send.call(this, requestBody);
};

const setRequestHeader = XMLHttpRequest.prototype.setRequestHeader;
XMLHttpRequest.prototype.setRequestHeader = function (header, value) {
this.requestHeaders = this.requestHeaders || {};
this.requestHeaders[header] = value;
setRequestHeader.apply(this, arguments);
const setRequestHeader = XMLHttpRequest.prototype.setRequestHeader;
XMLHttpRequest.prototype.setRequestHeader = function (header, value) {
this.requestHeaders = this.requestHeaders || {};
this.requestHeaders[header] = value;
setRequestHeader.apply(this, arguments);
};
};


})(NAMESPACE);
4 changes: 3 additions & 1 deletion src/models/WebRequestModel.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
// TODO move the relevant folder
export enum WebRequestClients {
MAIN = 'main',
WINDOW = 'window',
DEVTOOL = 'devtool'
}

export enum ListenerType {
// TODO move the relevant folder
export enum WebRequestListenerType {
BEFOREREQUEST = 'beforeRequest',
BEFORESENDHEADERS = 'beforeSendHeaders',
HEADERSRECEIVED = 'headersReceived',
Expand Down
2 changes: 1 addition & 1 deletion src/models/formFieldModel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export interface IRuleData {
type: string,
requestMethods: RequestMethod[],
resourceTypes: ResourceType[],
id?: number,
id: number,
destination?: string,
editorValue?: string,
editorLang?: string,
Expand Down
1 change: 1 addition & 0 deletions src/options/constant/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const excludedUrls: string[] = ['chrome://', 'chrome-extension', 'https://chrome.google.com'];
8 changes: 4 additions & 4 deletions src/options/pages/httpLogger/httpLogger.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useEffect, useState, useRef } from 'react';
import { ListenerType, WebRequestClients } from 'src/models/WebRequestModel';
import { WebRequestListenerType, WebRequestClients } from 'src/models/WebRequestModel';
import ColorCover from 'components/common/colorCover/colorCover';
import Input from 'components/common/input/input';
import CrossSVG from 'assets/icons/cross.svg';
Expand All @@ -23,15 +23,15 @@ const HTTPLogger = ({ clientName, showOpenWindowBtn = true }) => {
newRequest.url = url;
newRequest.type = type;

if(messageType === ListenerType.BEFORESENDHEADERS ) {
if(messageType === WebRequestListenerType.BEFORESENDHEADERS ) {
newRequest.requestHeaders = requestHeaders;
}

if(messageType === ListenerType.HEADERSRECEIVED ) {
if(messageType === WebRequestListenerType.HEADERSRECEIVED ) {
newRequest.responseHeaders = responseHeaders;
}

if(messageType === ListenerType.COMPLETED ) {
if(messageType === WebRequestListenerType.COMPLETED ) {
newRequest.ip = ip;
newRequest.fromCache = fromCache;
newRequest.statusCode = statusCode;
Expand Down
1 change: 1 addition & 0 deletions src/options/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './regExp';
export * from './timeDifference';
export const encode = (mimi, value = '') => `data:${mimi};charset=UTF-8;base64,${btoa(unescape(encodeURIComponent(value)))}`;
export const decode = (value = '') => decodeURIComponent(escape(atob(value.substring(value.indexOf('base64,') + 7))));
export const structuredClone = (object: any) => (typeof window?.structuredClone === 'function' && window.structuredClone(object)) || JSON.parse(JSON.stringify(object));
19 changes: 19 additions & 0 deletions src/options/utils/timeDifference.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
export const getTimeDifference = (startDate, endDate) => {
const startTime = startDate.getTime();
const endTime = endDate.getTime();
const timeDifferenceInMilliseconds = endTime - startTime; // milliseconds
const timeDifferenceInSeconds = timeDifferenceInMilliseconds / 1000; // seconds
const timeDifferenceInMinutes = timeDifferenceInMilliseconds / (1000 * 60); // minutes
const timeDifferenceInHours = timeDifferenceInMilliseconds / (1000 * 60 * 60); // hours
return {
milliseconds: timeDifferenceInMilliseconds,
seconds: timeDifferenceInSeconds,
minutes: timeDifferenceInMinutes,
hours: timeDifferenceInHours,
};
}





Loading

0 comments on commit 28c2ead

Please sign in to comment.