-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This will let us intercept fetch requests (until now we're only proxying XMLHttpRequest), in order to fix the issues we're experiencing with some features. Bug: twpowertools:229 Change-Id: I277473c05479ca39bb6183a51855382124890bde
- Loading branch information
Showing
24 changed files
with
848 additions
and
92 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
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,29 @@ | ||
import FetchProxy from '../../../xhrInterceptor/fetchProxy/FetchProxy'; | ||
import InterceptorHandlerAdapter from '../../../xhrInterceptor/interceptors/InterceptorHandler.adapter'; | ||
import interceptors from '../../../xhrInterceptor/interceptors/interceptors'; | ||
import {KILL_SWITCH_LOCALSTORAGE_KEY, KILL_SWITCH_LOCALSTORAGE_VALUE} from '../../../xhrInterceptor/killSwitchHandler.js'; | ||
import MessageIdTracker from '../../../xhrInterceptor/MessageIdTracker'; | ||
import ResponseModifierAdapter from '../../../xhrInterceptor/ResponseModifier.adapter'; | ||
import createMessageRemoveParentRef from '../../../xhrInterceptor/responseModifiers/createMessageRemoveParentRef'; | ||
import flattenThread from '../../../xhrInterceptor/responseModifiers/flattenThread'; | ||
import loadMoreThread from '../../../xhrInterceptor/responseModifiers/loadMoreThread'; | ||
import { Modifier } from '../../../xhrInterceptor/responseModifiers/types'; | ||
import XHRProxy from '../../../xhrInterceptor/XHRProxy'; | ||
|
||
export const responseModifiers: Modifier[] = [ | ||
loadMoreThread, | ||
flattenThread, | ||
createMessageRemoveParentRef, | ||
]; | ||
|
||
if (window.localStorage.getItem(KILL_SWITCH_LOCALSTORAGE_KEY) !== | ||
KILL_SWITCH_LOCALSTORAGE_VALUE) { | ||
const responseModifier = new ResponseModifierAdapter(responseModifiers); | ||
const interceptorHandler = new InterceptorHandlerAdapter(interceptors.interceptors); | ||
const messageIdTracker = new MessageIdTracker(); | ||
|
||
new XHRProxy(responseModifier, messageIdTracker); | ||
|
||
const fetchProxy = new FetchProxy(responseModifier, interceptorHandler, messageIdTracker); | ||
fetchProxy.enableInterception(); | ||
} |
This file was deleted.
Oops, something went wrong.
2 changes: 1 addition & 1 deletion
2
src/presentation/standaloneScripts/mainWorldServers/MWOptionsWatcherServerScript.script.ts
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
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,7 @@ | ||
export default class MessageIdTracker { | ||
private messageId = 0; | ||
|
||
getNewId() { | ||
return this.messageId++; | ||
} | ||
} |
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
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,27 @@ | ||
import { ProtobufObject } from "../common/protojs.types"; | ||
|
||
export interface ResponseModifierPort { | ||
intercept(interception: InterceptedResponse): Promise<Result>; | ||
} | ||
|
||
/** | ||
* Represents an intercepted response. | ||
*/ | ||
export interface InterceptedResponse { | ||
/** | ||
* URL of the original request. | ||
*/ | ||
url: string; | ||
|
||
/** | ||
* Object with the response as intercepted without any modification. | ||
*/ | ||
originalResponse: ProtobufObject; | ||
} | ||
|
||
export type Result = | ||
| { wasModified: false } | ||
| { | ||
wasModified: true; | ||
modifiedResponse: ProtobufObject; | ||
}; |
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
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,12 @@ | ||
export default class FetchBody { | ||
constructor(private body: RequestInit['body'] | undefined) {} | ||
|
||
async getJSONRequestBody() { | ||
if (!this.body) return undefined; | ||
|
||
// Using Response is a hack, but it works and converts a possibly long code | ||
// into a one-liner :D | ||
// Source of inspiration: https://stackoverflow.com/a/72718732 | ||
return await new Response(this.body).json(); | ||
} | ||
} |
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,88 @@ | ||
/** | ||
* @jest-environment ./src/xhrInterceptor/fetchProxy/__environments__/fetchEnvironment.ts | ||
*/ | ||
|
||
import { describe, expect, it } from '@jest/globals'; | ||
import FetchHeaders from './FetchHeaders'; | ||
|
||
describe('FetchHeaders', () => { | ||
const dummyHeaderName = 'X-Foo'; | ||
const dummyHeaderValue = 'bar'; | ||
const dummyHeadersPerFormat: { description: string; value: HeadersInit }[] = [ | ||
{ | ||
description: 'a Headers instance', | ||
value: new Headers({ [dummyHeaderName]: dummyHeaderValue }), | ||
}, | ||
{ | ||
description: 'an object', | ||
value: { [dummyHeaderName]: dummyHeaderValue }, | ||
}, | ||
{ | ||
description: 'an array', | ||
value: [[dummyHeaderName, dummyHeaderValue]], | ||
}, | ||
]; | ||
|
||
describe.each(dummyHeadersPerFormat)( | ||
'when the headers are presented as $description', | ||
({ value }) => { | ||
describe('hasValue', () => { | ||
it('should return true when the header with the provided value is present', () => { | ||
const sut = new FetchHeaders(value); | ||
const result = sut.hasValue(dummyHeaderName, dummyHeaderValue); | ||
|
||
expect(result).toBe(true); | ||
}); | ||
|
||
it("should return true when a header with the provided value is present even if the provided name doesn't have the same case", () => { | ||
const sut = new FetchHeaders(value); | ||
const result = sut.hasValue('x-FoO', dummyHeaderValue); | ||
|
||
expect(result).toBe(true); | ||
}); | ||
|
||
it('should return false when a header with the provided value is not present', () => { | ||
const sut = new FetchHeaders(value); | ||
const result = sut.hasValue('X-NonExistent', dummyHeaderValue); | ||
|
||
expect(result).toBe(false); | ||
}); | ||
}); | ||
|
||
describe('removeHeader', () => { | ||
it('should remove the header if it is present', () => { | ||
const sut = new FetchHeaders(value); | ||
sut.removeHeader(dummyHeaderName); | ||
|
||
if (value instanceof Headers) { | ||
expect(value.has(dummyHeaderName)).toBe(false); | ||
} else if (Array.isArray(value)) { | ||
expect(value).not.toContain( | ||
expect.arrayContaining([dummyHeaderName]), | ||
); | ||
} else { | ||
expect(value).not.toHaveProperty(dummyHeaderName); | ||
} | ||
}); | ||
}); | ||
}, | ||
); | ||
|
||
describe('when the headers are presented as undefined', () => { | ||
describe('hasValue', () => { | ||
it('should return false', () => { | ||
const sut = new FetchHeaders(undefined); | ||
const result = sut.hasValue(dummyHeaderName, dummyHeaderValue); | ||
|
||
expect(result).toBe(false); | ||
}); | ||
}); | ||
|
||
describe('removeHeader', () => { | ||
it('should not throw', () => { | ||
const sut = new FetchHeaders(undefined); | ||
expect(() => sut.removeHeader(dummyHeaderName)).not.toThrow(); | ||
}); | ||
}); | ||
}); | ||
}); |
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,47 @@ | ||
export default class FetchHeaders { | ||
constructor(private headers: HeadersInit | undefined) {} | ||
|
||
hasValue(name: string, value: string) { | ||
if (!this.headers) { | ||
return false; | ||
} else if (this.headers instanceof Headers) { | ||
return this.headers.get(name) == value; | ||
} else { | ||
const headersArray = Array.isArray(this.headers) | ||
? this.headers | ||
: Object.entries(this.headers); | ||
return headersArray.some( | ||
([candidateHeaderName, candidateValue]) => | ||
this.isEqualCaseInsensitive(candidateHeaderName, name) && | ||
candidateValue === value, | ||
); | ||
} | ||
} | ||
|
||
removeHeader(name: string) { | ||
if (!this.headers) { | ||
return; | ||
} else if (this.headers instanceof Headers) { | ||
this.headers.delete(name); | ||
} else if (Array.isArray(this.headers)) { | ||
const index = this.headers.findIndex(([candidateHeaderName]) => | ||
this.isEqualCaseInsensitive(candidateHeaderName, name), | ||
); | ||
if (index !== -1) delete this.headers[index]; | ||
} else { | ||
const headerNames = Object.keys(this.headers); | ||
const headerName = headerNames.find((candidateName) => | ||
this.isEqualCaseInsensitive(candidateName, name), | ||
); | ||
if (headerName) delete this.headers[headerName]; | ||
} | ||
} | ||
|
||
private isEqualCaseInsensitive(a: string, b: string) { | ||
return ( | ||
a.localeCompare(b, undefined, { | ||
sensitivity: 'accent', | ||
}) == 0 | ||
); | ||
} | ||
} |
Oops, something went wrong.