@zkp2p/reclaim-witness-sdk
Version:
<div> <div> <img src="https://raw.githubusercontent.com/reclaimprotocol/.github/main/assets/banners/Attestor-Core.png" /> </div> </div>
1,047 lines (1,046 loc) • 270 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const tls_1 = require("@reclaimprotocol/tls");
const assert_1 = __importDefault(require("assert"));
const config_1 = require("../config");
const providers_1 = require("../providers");
const http_1 = __importDefault(require("../providers/http"));
const utils_1 = require("../providers/http/utils");
const test_http_parser_1 = require("../tests/test.http-parser");
const utils_2 = require("../utils");
const v8_1 = require("v8");
jest.setTimeout(60000);
const ctx = config_1.PROVIDER_CTX;
describe('HTTP Provider Utils tests', () => {
const { hostPort, geoLocation, getResponseRedactions, createRequest, assertValidProviderReceipt } = providers_1.providers['http'];
const transcript = JSON.parse('[' +
'{"message":"KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKio=","sender":"server"},' +
'{"message":"KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKg==","sender":"server"},' +
'{"message":"KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq","sender":"server"},' +
'{"message":"KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKg==","sender":"server"},' +
'{"message":"KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKio=","sender":"server"},' +
'{"message":"KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKio=","sender":"server"},' +
'{"message":"R0VUIC8gSFRUUC8xLjENCkhvc3Q6IHhhcmdzLm9yZw0KQ29udGVudC1MZW5ndGg6IDQNCkNvbm5lY3Rpb246IGNsb3NlDQpBY2NlcHQtRW5jb2Rpbmc6IGlkZW50aXR5DQp1c2VyLWFnZW50OiBNb3ppbGxhLzUuMA0K","sender":"client"},' +
'{"message":"KioqKio=","sender":"client"},' +
'{"message":"KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKg==","sender":"client"},' +
'{"message":"KioqKio=","sender":"client"},' +
'{"message":"DQoNCnQ=","sender":"client"},' +
'{"message":"KioqKio=","sender":"client"},' +
'{"message":"Kg==","sender":"client"},' +
'{"message":"KioqKio=","sender":"client"},' +
'{"message":"c3Q=","sender":"client"},' +
'{"message":"SFRUUC8xLjEgMjAwIE9LKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKg0KDQo=","sender":"server"},' +
'{"message":"KioqKioqKioqKioqKioqKioqKioqKioqKioqKjx0aXRsZT5BaWtlbiAmYW1wOyBEcmlzY29sbCAmYW1wOyBXZWJiPC90aXRsZT4qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqT25lIG9mIHRoZSBmZXcgZXhjZXB0aW9ucyBpcyBhIHNlcmllcyBvZiBkb2N1bWVudHMgdGhhdCBJJ3ZlIHdyaXR0ZW4KICAgIGJyZWFraW5nIGRvd24gY3J5cHRvZ3JhcGhpYyBhbmQgbmV0d29yayBwcm90b2NvbHMgYnl0ZS1ieS1ieXRlLiBJJ20KICAgIGFsd2F5cyBoZWFyaW5nIGZyb20gdGVhY2hlcnMsIHN0dWRlbnRzLCBhbmQgZmVsbG93IHNvZnR3YXJlIGRldmVsb3BlcnMKICAgIHdobyB1c2UgdGhlc2UgdG8gbGVhcm4sIHRvIGZpeCwgYW5kIHRvIHVuZGVyc3RhbmQuIEknbSB2ZXJ5IHByb3VkIG9mIHRoYXQuKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq","sender":"server"},{"message":"Kio=","sender":"server"}]')
.map((x) => ({
...x,
message: Buffer.from(x.message, 'base64'),
}));
it('should parse xpath & JSON path', () => {
const json = (0, utils_1.extractHTMLElement)(html, "//script[@data-component-name='Navbar']", true);
const val = (0, utils_1.extractJSONValueIndex)(json, '$.hasBookface');
const rm = '"hasBookface":true';
const regexp = new RegExp(rm, 'gim');
expect(regexp.test(json.slice(val.start, val.end))).toBe(true);
});
it('should extract complex JSON path', () => {
const json = `{
"items":[
{
"name": "John Doe",
"country": "USA"
},
{
"country": "USA",
"age":25
}
]
}`;
const val = (0, utils_1.extractJSONValueIndex)(json, '$.items[?(@.name.match(/.*oe/))].name');
const rm = '"name": "John Doe"';
const regexp = new RegExp(rm, 'gim');
expect(regexp.test(json.slice(val.start, val.end))).toBe(true);
});
it('should get inner & outer tag contents', () => {
const html = `<body>
<div id="content123">This is <span>some</span> text!</div>
<div id="content456">This is <span>some</span> other text!</div>
<div id="content789">This is <span>some</span> irrelevant text!</div>
</body>`;
let content = (0, utils_1.extractHTMLElement)(html, "//div[contains(@id, 'content123')]", true);
expect(content).toEqual('This is <span>some</span> text!');
content = (0, utils_1.extractHTMLElement)(html, "//div[contains(@id, 'content456')]", false);
expect(content).toEqual('<div id="content456">This is <span>some</span> other text!</div>');
});
it('should get multiple elements', () => {
const html = `<body>
<div id="content123">This is <span>some</span> text!</div>
<div id="content456">This is <span>some</span> other text!</div>
<div id="content789">This is <span>some</span> irrelevant text!</div>
</body>`;
const contents = (0, utils_1.extractHTMLElements)(html, '//body/div', true);
expect(contents).toEqual(['This is <span>some</span> text!', 'This is <span>some</span> other text!', 'This is <span>some</span> irrelevant text!']);
});
it('should get multiple JSONPaths', () => {
const jsonData = `{
"firstName": "John",
"lastName": "doe",
"age": 26,
"address": {
"streetAddress": "naist street",
"city": "Nara",
"postalCode": "630-0192"
},
"phoneNumbers": [
{
"type": "iPhone",
"number": "0123-4567-8888"
},
{
"type": "home",
"number": "0123-4567-8910"
}
]
}`;
const contents = (0, utils_1.extractJSONValueIndexes)(jsonData, '$.phoneNumbers[*].number');
const res = [];
for (const { start, end } of contents) {
res.push(jsonData.slice(start, end));
}
expect(res).toEqual(['"number": "0123-4567-8888"', '"number": "0123-4567-8910"']);
});
it('should error on incorrect jsonPath', () => {
expect(() => {
(0, utils_1.extractJSONValueIndex)(('{"asdf": 1}'), '(alert(origin))');
}).toThrow('loc.indexOf is not a function');
});
it('should not error on incorrect regex', () => {
expect(() => {
const regexp = (0, utils_1.makeRegex)('([a-z]+)+$');
regexp.test('a'.repeat(31) + '\x00');
}).not.toThrow();
});
it('should hide chunked parts from response', () => {
const provider = http_1.default;
const simpleChunk = Buffer.from('HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nTransfer-Encoding: chunked\r\nConnection: close\r\n\r\n9\r\nchunk 1, \r\n7\r\nchunk 2\r\n0\r\n');
if (provider.getResponseRedactions) {
const redactions = provider.getResponseRedactions({
response: simpleChunk,
params: {
method: 'GET',
url: 'https://test.com',
'responseMatches': [],
'responseRedactions': [
{
'regex': 'chunk 1, chunk 2'
}
],
},
logger: utils_2.logger,
ctx
});
expect(redactions).toEqual([
{
'fromIndex': 15,
'toIndex': 88,
},
{
'fromIndex': 92,
'toIndex': 95
},
{
'fromIndex': 104,
'toIndex': 109
},
{
'fromIndex': 116,
'toIndex': 121
}
]);
let start = 0;
let str = '';
for (const red of redactions) {
str += simpleChunk.subarray(start, red.fromIndex);
start = red.toIndex;
}
expect(str).toEqual('HTTP/1.1 200 OK\r\n\r\nchunk 1, chunk 2');
}
});
it('should perform complex redactions', () => {
const provider = http_1.default;
const response = Buffer.from('HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\ncontent-length: 222\r\nConnection: close\r\n\r\n<body> <div id="c1">{"ages":[{"age":"26"},{"age":"27"},{"age":"28"}]}</div> <div id="c2">{"ages":[{"age":"27"},{"age":"28"},{"age":"29"}]}</div> <div id="c3">{"ages":[{"age":"29"},{"age":"30"},{"age":"31"}]}</div></body>\r\n');
if (provider.getResponseRedactions) {
const redactions = provider.getResponseRedactions({
response,
params: {
method: 'GET',
url: 'https://test.com',
'responseMatches': [],
'responseRedactions': [
{
'xPath': '//body/div',
'jsonPath': '$.ages[*].age',
'regex': '(2|3)\\d'
}
],
},
logger: utils_2.logger,
ctx,
});
expect(redactions).toEqual([
{
'fromIndex': 15,
'toIndex': 81,
},
{
'fromIndex': 85,
'toIndex': 122
},
{
'fromIndex': 124,
'toIndex': 135
},
{
'fromIndex': 137,
'toIndex': 148
},
{
'fromIndex': 150,
'toIndex': 191
},
{
'fromIndex': 193,
'toIndex': 204
},
{
'fromIndex': 206,
'toIndex': 217
},
{
'fromIndex': 219,
'toIndex': 260
},
{
'fromIndex': 262,
'toIndex': 273
},
{
'fromIndex': 275,
'toIndex': 286
},
{
'fromIndex': 288,
'toIndex': 307
}
]);
let start = 0;
let str = '';
for (const red of redactions) {
str += response.subarray(start, red.fromIndex);
start = red.toIndex;
}
expect(str).toEqual('HTTP/1.1 200 OK\r\n\r\n262728272829293031');
}
});
it('should perform complex redactions 2', () => {
const provider = http_1.default;
const response = Buffer.from('HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\ncontent-length: 51\r\nConnection: close\r\n\r\n{"ages":[{"age":"26"},{"age":"27"},{"age":"28"}]}\r\n');
if (provider.getResponseRedactions) {
const redactions = provider.getResponseRedactions({
response,
params: {
method: 'GET',
url: 'https://test.com',
'responseMatches': [],
'responseRedactions': [
{
'jsonPath': '$.ages[*].age',
'regex': '(2|3)\\d'
}
],
},
logger: utils_2.logger,
ctx,
});
expect(redactions).toEqual([
{
'fromIndex': 15,
'toIndex': 80,
},
{
'fromIndex': 84,
'toIndex': 101
},
{
'fromIndex': 103,
'toIndex': 114
},
{
'fromIndex': 116,
'toIndex': 127
},
{
'fromIndex': 129,
'toIndex': 135
}
]);
let start = 0;
let str = '';
for (const red of redactions) {
str += response.subarray(start, red.fromIndex);
start = red.toIndex;
}
expect(str).toEqual('HTTP/1.1 200 OK\r\n\r\n262728');
}
});
it('should perform complex redactions 3', () => {
const provider = http_1.default;
const response = Buffer.from('HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\ncontent-length: 222\r\nConnection: close\r\n\r\n<body> <div id="c1">{"ages":[{"age":"26"},{"age":"27"},{"age":"28"}]}</div> <div id="c2">{"ages":[{"age":"27"},{"age":"28"},{"age":"29"}]}</div> <div id="c3">{"ages":[{"age":"29"},{"age":"30"},{"age":"31"}]}</div></body>\r\n');
if (provider.getResponseRedactions) {
const redactions = provider.getResponseRedactions({
response,
params: {
method: 'GET',
url: 'https://test.com',
'responseMatches': [],
'responseRedactions': [
{
'xPath': '//body/div',
'regex': '"age":"\\d{2}"'
}
],
},
logger: utils_2.logger,
ctx,
});
expect(redactions).toEqual([
{
'fromIndex': 15,
'toIndex': 81,
},
{
'fromIndex': 85,
'toIndex': 115
},
{
'fromIndex': 125,
'toIndex': 184
},
{
'fromIndex': 194,
'toIndex': 253
},
{
'fromIndex': 263,
'toIndex': 307
}
]);
let start = 0;
let str = '';
for (const red of redactions) {
str += response.subarray(start, red.fromIndex);
start = red.toIndex;
}
expect(str).toEqual('HTTP/1.1 200 OK\r\n\r\n"age":"26""age":"27""age":"29"');
}
});
it('should get redactions from chunked response', () => {
const provider = http_1.default;
if (provider.getResponseRedactions) {
const redactions = provider.getResponseRedactions({
response: chunkedResp,
params: {
method: 'GET',
url: 'https://bookface.ycombinator.com/home',
'responseMatches': [],
'responseRedactions': [
{
'xPath': "//script[@id='js-react-on-rails-context']",
'jsonPath': '$.currentUser',
},
{
'xPath': "//script[@data-component-name='BookfaceCsrApp']",
'jsonPath': '$.hasBookface',
},
{
'regex': 'code_version:\\s"[0-9a-f]{40}\\sruby'
}
],
},
logger: utils_2.logger,
ctx,
});
expect(redactions).toEqual([
{
'fromIndex': 15,
'toIndex': 17
},
{
'fromIndex': 52,
'toIndex': 4290,
},
{
'fromIndex': 4294,
'toIndex': 4760
},
{
'fromIndex': 4820,
'toIndex': 53268
},
{
'fromIndex': 53507,
'toIndex': 58705
},
{
'fromIndex': 58723,
'toIndex': 64093
}
]);
}
});
it('should hash provider params consistently', () => {
const params = {
url: 'https://xargs.org/',
responseMatches: [
{
type: 'regex',
value: '<title.*?(?<name>Aiken & Driscoll & Webb)<\\/title>'
}
],
method: 'GET',
responseRedactions: [{ xPath: './html/head/title' }],
geoLocation: 'US',
};
const hash = (0, utils_2.hashProviderParams)(params);
expect(hash).toEqual('0xe9624d26421a4d898d401e98821ccd645c25b06de97746a6c24a8b12d9aec143');
const paramsEx = {
'geoLocation': '',
'url': 'https://www.linkedin.com/dashboard/',
'method': 'GET',
'body': '',
'responseMatches': [
{
'value': 'TOTAL_FOLLOWERS","$recipeTypes":["com.linkedin.c123aee2ba3dfeb6a4580e7effdf5d3f"],"analyticsTitle":{"textDirection":"USER_LOCALE","text":"581"',
'type': 'contains'
}
],
'responseRedactions': [{
'xPath': '{{xpath}}',
'jsonPath': '',
'regex': 'TOTAL_FOLLOWERS","\\$recipeTypes":(.*?),"analyticsTitle":{"textDirection":"USER_LOCALE","text":"(.*?)"'
}]
};
expect((0, utils_2.hashProviderParams)(paramsEx)).toEqual('0x6fb81ebab0fb5dca0356abfd8726af97675e4a426712377bfc6ad9a0271c913b');
});
it('should match redacted strings', () => {
const testCases = [
{
a: 'aaa',
b: 'aaa'
},
{
a: '{{abc}}',
b: '************'
},
{
a: '{{abc}}d',
b: '*d'
},
{
a: 'd{{abc}}',
b: 'd*******************************************'
},
{
a: 'd{{abc}}d{{abwewewewec}}',
b: 'd*d*'
},
{
a: '{{abc}}x{{abwewewewec}}',
b: '*x*'
}
];
for (const { a, b } of testCases) {
expect((0, utils_1.matchRedactedStrings)((0, tls_1.strToUint8Array)(a), (0, tls_1.strToUint8Array)(b))).toBeTruthy();
}
});
it('should not match bad redacted strings', () => {
const testCases = [
{
a: 'aaa',
b: 'aab'
},
{
a: '{{abc}}',
b: ''
},
{
a: '',
b: '*****'
},
{
a: '{{abc}}{{abc}}d',
b: '*d'
},
{
a: '{{yy',
b: '*'
},
{
a: '{{abc}}d{{abwewewewec}}',
b: 'a*d*'
},
{
a: '{abc}}',
b: '************'
}
];
for (const { a, b } of testCases) {
expect((0, utils_1.matchRedactedStrings)((0, tls_1.strToUint8Array)(a), (0, tls_1.strToUint8Array)(b))).toBeFalsy();
}
});
it('should throw on invalid URL', () => {
expect(() => ((0, utils_2.getProviderValue)({
url: 'abc',
responseMatches: [],
responseRedactions: [],
method: 'GET'
}, hostPort))).toThrow('Invalid URL');
});
it('should throw on invalid params', () => {
expect(() => {
(0, utils_2.assertValidateProviderParams)('http', { a: 'b', body: 2 });
}).toThrow(/^Params validation failed/);
});
it('should throw on invalid secret params', () => {
expect(() => {
createRequest({
cookieStr: undefined,
authorisationHeader: undefined,
headers: undefined
}, {
url: 'abc',
responseMatches: [],
responseRedactions: [],
method: 'GET'
}, utils_2.logger);
}).toThrow('auth parameters are not set');
});
it('should return empty redactions', () => {
const res = `HTTP/1.1 200 OK\r
Content-Length: 0\r
Connection: close\r
Content-Type: text/html; charset=utf-8\r
\r
`;
const redactions = (getResponseRedactions) ?
getResponseRedactions({
response: (0, tls_1.strToUint8Array)(res),
params: {
url: 'abc',
responseMatches: [],
responseRedactions: [],
method: 'GET'
},
logger: utils_2.logger,
ctx
})
: undefined;
expect(redactions).toHaveLength(0);
});
it('should throw on empty body', () => {
const res = `HTTP/1.1 200 OK\r
Content-Length: 0\r
Connection: close\r
Content-Type: text/html; charset=utf-8\r
\r
`;
expect(() => {
if (getResponseRedactions) {
getResponseRedactions({
response: (0, tls_1.strToUint8Array)(res),
params: {
url: 'abc',
responseMatches: [],
responseRedactions: [{
regex: 'abc'
}],
method: 'GET'
},
logger: utils_2.logger,
ctx,
});
}
}).toThrow('Failed to find response body');
});
it('should throw on bad xpath', () => {
const res = `HTTP/1.1 200 OK\r
Content-Length: 1\r
Connection: close\r
Content-Type: text/html; charset=utf-8\r
\r
1`;
expect(() => {
if (getResponseRedactions) {
getResponseRedactions({
response: (0, tls_1.strToUint8Array)(res),
params: {
url: 'abc',
responseMatches: [],
responseRedactions: [{
xPath: 'abc'
}],
method: 'GET'
},
logger: utils_2.logger,
ctx
});
}
}).toThrow('Failed to find XPath: \"abc\"');
});
it('should throw on bad jsonPath', () => {
const res = `HTTP/1.1 200 OK\r
Content-Length: 1\r
Connection: close\r
Content-Type: text/html; charset=utf-8\r
\r
1`;
expect(() => {
if (getResponseRedactions) {
getResponseRedactions({
response: (0, tls_1.strToUint8Array)(res),
params: {
url: 'abc',
responseMatches: [],
responseRedactions: [{
jsonPath: 'abc'
}],
method: 'GET'
},
logger: utils_2.logger,
ctx,
});
}
}).toThrow('jsonPath not found');
});
it('should throw on bad regex', () => {
const res = `HTTP/1.1 200 OK\r
Content-Length: 1\r
Connection: close\r
Content-Type: text/html; charset=utf-8\r
\r
1`;
expect(() => {
if (getResponseRedactions) {
getResponseRedactions({
response: (0, tls_1.strToUint8Array)(res),
params: {
url: 'abc',
responseMatches: [],
responseRedactions: [{
regex: 'abc'
}],
method: 'GET'
},
logger: utils_2.logger,
ctx,
});
}
}).toThrow('regexp abc does not match found element \'MQ==\'');
});
it('should throw on bad method', async () => {
await expect(async () => {
await assertValidProviderReceipt({
receipt: transcript,
params: {
url: 'abc',
responseMatches: [],
responseRedactions: [],
method: 'POST'
},
logger: utils_2.logger,
ctx
});
}).rejects.toThrow('Invalid method: get');
});
it('should throw on bad protocol', async () => {
await expect(async () => {
await assertValidProviderReceipt({
receipt: transcript,
params: {
url: 'http://xargs.com',
responseMatches: [],
responseRedactions: [],
method: 'GET'
},
logger: utils_2.logger,
ctx,
});
}).rejects.toThrow('Expected protocol: https, found: http:');
});
it('should throw on duplicate groups', async () => {
await expect(async () => {
await assertValidProviderReceipt({
receipt: transcript,
params: {
url: 'https://xargs.{{abc}}',
responseMatches: [{
type: 'regex',
value: '(?<abc>.)'
}],
responseRedactions: [],
method: 'GET',
paramValues: {
'abc': 'org'
}
},
logger: utils_2.logger,
ctx
});
}).rejects.toThrow('Duplicate parameter abc');
});
it('should throw on bad path', async () => {
await expect(async () => {
await assertValidProviderReceipt({
receipt: transcript,
params: {
url: 'https://xargs.com/abc',
responseMatches: [],
responseRedactions: [],
method: 'GET'
},
logger: utils_2.logger,
ctx
});
}).rejects.toThrow('Expected path: /abc, found: /');
});
it('should throw on bad host', async () => {
await expect(async () => {
await assertValidProviderReceipt({
receipt: transcript,
params: {
url: 'https://abc.com/',
responseMatches: [],
responseRedactions: [],
method: 'GET'
},
logger: utils_2.logger,
ctx,
});
}).rejects.toThrow('Expected host: abc.com, found: xargs.org');
});
it('should throw on bad OK string', async () => {
const temp = cloneObject(transcript);
// changes the status ("OK") text to something else
// it'll be in the first server response packet
const firstServerMsg = temp.find((x, index) => x.sender === 'server' && index !== 0);
firstServerMsg.message[0] = 32;
await expect(async () => {
await assertValidProviderReceipt({
receipt: temp,
params: {
url: 'https://xargs.org/',
responseMatches: [],
responseRedactions: [],
method: 'GET'
},
logger: utils_2.logger,
ctx,
});
}).rejects.toThrow('Response did not start with \"HTTP/1.1 2XX\"');
});
it('should throw on bad close header', async () => {
const temp = cloneObject(transcript);
const clientMsgWithClose = temp.find((x) => {
if (x.sender !== 'client') {
return false;
}
return (0, utils_2.uint8ArrayToStr)(x.message)
.includes('Connection: close');
});
clientMsgWithClose.message[68] = 102;
await expect(async () => {
await assertValidProviderReceipt({
receipt: temp,
params: {
url: 'https://xargs.org/',
responseMatches: [],
responseRedactions: [],
method: 'GET'
},
logger: utils_2.logger,
ctx
});
}).rejects.toThrow('Connection header must be \"close\"');
});
it('should throw on bad body', async () => {
await expect(async () => {
await assertValidProviderReceipt({
receipt: transcript,
params: {
url: 'https://xargs.org/',
responseMatches: [],
responseRedactions: [],
method: 'GET',
body: 'abc'
},
logger: utils_2.logger,
ctx
});
}).rejects.toThrow('request body mismatch');
});
it('should throw on bad regex match', async () => {
await expect(async () => {
await assertValidProviderReceipt({
receipt: transcript,
params: {
url: 'https://xargs.org/',
responseMatches: [{
type: 'regex',
value: 'abc'
}],
responseRedactions: [],
method: 'GET',
},
logger: utils_2.logger,
ctx
});
}).rejects.toThrow('Invalid receipt. Regex \"abc\" didn\'t match');
});
it('should throw on bad contains match', async () => {
await expect(async () => {
await assertValidProviderReceipt({
receipt: transcript,
params: {
url: 'https://xargs.org/',
responseMatches: [{
type: 'contains',
value: 'abc'
}],
responseRedactions: [],
method: 'GET',
},
logger: utils_2.logger,
ctx,
});
}).rejects.toThrow('Invalid receipt. Response does not contain \"abc\"');
});
it('should get geo', () => {
const geo = (0, utils_2.getProviderValue)({
geoLocation: '{{geo}}',
paramValues: {
'geo': 'US'
}
}, geoLocation);
expect(geo).toEqual('US');
});
it('should throw on bad geo param', () => {
expect(() => {
// @ts-ignore
geoLocation({
geoLocation: '{{geo}}',
paramValues: {
'geo1': 'US'
}
});
}).toThrow('parameter "geo" value not found in templateParams');
});
it('should return empty geo', () => {
expect(// @ts-ignore
geoLocation({
geoLocation: '',
})).toEqual(undefined);
});
it('should throw on bad param in url', () => {
expect(() => {
// @ts-ignore
return hostPort({
url: 'https://xargs.{{param1}}'
});
})
.toThrow('parameter "param1" value not found in templateParams');
});
it('should throw on bad url', () => {
expect(() => {
// @ts-ignore
hostPort({
url: 'file:///C:/path'
});
})
.toThrow('url is incorrect');
});
it('should throw on bad match type', async () => {
await expect(async () => {
const params = {
url: 'https://xargs.org/',
responseMatches: [{
type: 'abc',
value: 'abc'
}],
responseRedactions: [],
method: 'GET',
};
await assertValidProviderReceipt({
receipt: transcript,
// @ts-ignore
params,
logger: utils_2.logger,
ctx,
});
}).rejects.toThrow('Invalid response match type abc');
});
it('should throw on no non present params', async () => {
await expect(async () => {
await assertValidProviderReceipt({
receipt: transcript,
params: {
url: 'https://xargs.{{org}}/',
responseMatches: [{
type: 'contains',
value: 'abc'
}],
responseRedactions: [],
method: 'GET',
},
logger: utils_2.logger,
ctx
});
}).rejects.toThrow('Expected host: xargs.{{org}}, found: xargs.org');
});
it('should throw on non present secret params', () => {
expect(() => {
createRequest({
cookieStr: 'abc',
}, {
url: 'https://xargs.{{com}}',
responseMatches: [],
responseRedactions: [],
method: 'GET'
}, utils_2.logger);
}).toThrow('parameter\'s \"com\" value not found in paramValues and secret parameter\'s paramValues');
});
it('should replace params in body correctly', () => {
const params = {
url: 'https://example.{{param1}}/',
method: 'GET',
body: 'hello {{h}} {{b}} {{h1h1h1h1h1h1h1}} {{h2}} {{a}} {{h1h1h1h1h1h1h1}} {{h}} {{a}} {{h2}} {{a}} {{b}} world',
geoLocation: 'US',
responseMatches: [{
type: 'regex',
value: '<title.*?(?<domain>{{param2}} Domain)<\\/title>',
}],
responseRedactions: [{
xPath: './html/head/{{param3}}',
}, {
xPath: '/html/body/div/p[1]/text()'
}],
paramValues: {
param1: 'com',
param2: 'Example',
param3: 'title',
what: 'illustrative',
a: '{{b}}',
b: 'aaaaa'
},
headers: {
'user-agent': 'Mozilla/5.0',
}
};
const secretParams = {
cookieStr: '<cookie-str>',
paramValues: {
h: 'crazy',
h1h1h1h1h1h1h1: 'crazy1',
h2: 'crazy2',
},
authorisationHeader: 'abc'
};
const req = createRequest(secretParams, params, utils_2.logger);
const reqText = (0, utils_2.uint8ArrayToStr)(req.data);
expect(reqText).toContain('hello crazy aaaaa crazy1 crazy2 {{b}} crazy1 crazy {{b}} crazy2 {{b}} aaaaa world');
expect(req.redactions.length).toEqual(7);
expect(getRedaction(0)).toEqual('Cookie: <cookie-str>\r\nAuthorization: abc');
expect(getRedaction(1)).toEqual('crazy');
expect(getRedaction(2)).toEqual('crazy1');
expect(getRedaction(3)).toEqual('crazy2');
expect(getRedaction(4)).toEqual('crazy1');
expect(getRedaction(5)).toEqual('crazy');
expect(getRedaction(6)).toEqual('crazy2');
function getRedaction(index) {
return (0, utils_2.uint8ArrayToStr)(req.data.slice(req.redactions[index].fromIndex, req.redactions[index].toIndex));
}
});
it('should replace params in body correctly case 2', () => {
const params = {
'body': '{"includeGroups":{{REQ_DAT}},"includeLogins":{{REQ_SECRET}},"includeVerificationStatus":false}',
'geoLocation': '',
'method': 'POST',
'paramValues': {
'REQ_DAT': 'false',
'username': 'testyreclaim'
},
'responseMatches': [
{
'type': 'contains',
'value': '"userName":"{{username}}"'
}
],
'responseRedactions': [
{
'jsonPath': '$.userName',
'regex': '"userName":"(.*)"',
'xPath': ''
}
],
'url': 'https://www.kaggle.com'
};
const secretParams = {
'paramValues': {
'REQ_SECRET': 'false'
},
authorisationHeader: 'abc'
};
const req = createRequest(secretParams, params, utils_2.logger);
const reqText = (0, utils_2.uint8ArrayToStr)(req.data);
expect(reqText).toContain('{\"includeGroups\":false,\"includeLogins\":false,\"includeVerificationStatus\":false}');
expect(req.redactions.length).toEqual(2);
expect(getRedaction(0)).toEqual('Authorization: abc');
expect(getRedaction(1)).toEqual('false');
function getRedaction(index) {
return (0, utils_2.uint8ArrayToStr)(req.data.slice(req.redactions[index].fromIndex, req.redactions[index].toIndex));
}
});
describe('OPRF', () => {
it('should handle OPRF replacements', async () => {
const params = {
url: 'https://example.com/',
method: 'GET',
responseMatches: [
{
type: 'regex',
value: '<title>(?<domain>.+)<\\/title>',
}
],
responseRedactions: [
{
regex: '<title>(?<domain>.+)<\\/title>',
hash: 'oprf'
}
],
};
const res = Buffer.from('SFRUUC8xLjEgMjAwIE9LDQpBY2NlcHQtUmFuZ2VzOiBieXRlcw0KQWdlOiAzNzIxNDcNCkNhY2hlLUNvbnRyb2w6IG1heC1hZ2U9NjA0ODAwDQpDb250ZW50LVR5cGU6IHRleHQvaHRtbDsgY2hhcnNldD1VVEYtOA0KRGF0ZTogVGh1LCAyMSBOb3YgMjAyNCAwNTozOTo0NiBHTVQNCkV0YWc6ICIzMTQ3NTI2OTQ3Ig0KRXhwaXJlczogVGh1LCAyOCBOb3YgMjAyNCAwNTozOTo0NiBHTVQNCkxhc3QtTW9kaWZpZWQ6IFRodSwgMTcgT2N0IDIwMTkgMDc6MTg6MjYgR01UDQpTZXJ2ZXI6IEVDQWNjIChsYWMvNTVCNSkNClZhcnk6IEFjY2VwdC1FbmNvZGluZw0KWC1DYWNoZTogSElUDQpDb250ZW50LUxlbmd0aDogMTI1Ng0KQ29ubmVjdGlvbjogY2xvc2UNCg0KPCFkb2N0eXBlIGh0bWw+CjxodG1sPgo8aGVhZD4KICAgIDx0aXRsZT5FeGFtcGxlIERvbWFpbjwvdGl0bGU+CgogICAgPG1ldGEgY2hhcnNldD0idXRmLTgiIC8+CiAgICA8bWV0YSBodHRwLWVxdWl2PSJDb250ZW50LXR5cGUiIGNvbnRlbnQ9InRleHQvaHRtbDsgY2hhcnNldD11dGYtOCIgLz4KICAgIDxtZXRhIG5hbWU9InZpZXdwb3J0IiBjb250ZW50PSJ3aWR0aD1kZXZpY2Utd2lkdGgsIGluaXRpYWwtc2NhbGU9MSIgLz4KICAgIDxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+CiAgICBib2R5IHsKICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjZjBmMGYyOwogICAgICAgIG1hcmdpbjogMDsKICAgICAgICBwYWRkaW5nOiAwOwogICAgICAgIGZvbnQtZmFtaWx5OiAtYXBwbGUtc3lzdGVtLCBzeXN0ZW0tdWksIEJsaW5rTWFjU3lzdGVtRm9udCwgIlNlZ29lIFVJIiwgIk9wZW4gU2FucyIsICJIZWx2ZXRpY2EgTmV1ZSIsIEhlbHZldGljYSwgQXJpYWwsIHNhbnMtc2VyaWY7CiAgICAgICAgCiAgICB9CiAgICBkaXYgewogICAgICAgIHdpZHRoOiA2MDBweDsKICAgICAgICBtYXJnaW46IDVlbSBhdXRvOwogICAgICAgIHBhZGRpbmc6IDJlbTsKICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmRmZGZmOwogICAgICAgIGJvcmRlci1yYWRpdXM6IDAuNWVtOwogICAgICAgIGJveC1zaGFkb3c6IDJweCAzcHggN3B4IDJweCByZ2JhKDAsMCwwLDAuMDIpOwogICAgfQogICAgYTpsaW5rLCBhOnZpc2l0ZWQgewogICAgICAgIGNvbG9yOiAjMzg0ODhmOwogICAgICAgIHRleHQtZGVjb3JhdGlvbjogbm9uZTsKICAgIH0KICAgIEBtZWRpYSAobWF4LXdpZHRoOiA3MDBweCkgewogICAgICAgIGRpdiB7CiAgICAgICAgICAgIG1hcmdpbjogMCBhdXRvOwogICAgICAgICAgICB3aWR0aDogYXV0bzsKICAgICAgICB9CiAgICB9CiAgICA8L3N0eWxlPiAgICAKPC9oZWFkPgoKPGJvZHk+CjxkaXY+CiAgICA8aDE+RXhhbXBsZSBEb21haW48L2gxPgogICAgPHA+VGhpcyBkb21haW4gaXMgZm9yIHVzZSBpbiBpbGx1c3RyYXRpdmUgZXhhbXBsZXMgaW4gZG9jdW1lbnRzLiBZb3UgbWF5IHVzZSB0aGlzCiAgICBkb21haW4gaW4gbGl0ZXJhdHVyZSB3aXRob3V0IHByaW9yIGNvb3JkaW5hdGlvbiBvciBhc2tpbmcgZm9yIHBlcm1pc3Npb24uPC9wPgogICAgPHA+PGEgaHJlZj0iaHR0cHM6Ly93d3cuaWFuYS5vcmcvZG9tYWlucy9leGFtcGxlIj5Nb3JlIGluZm9ybWF0aW9uLi4uPC9hPjwvcD4KPC9kaXY+CjwvYm9keT4KPC9odG1sPgo=', 'base64');
const redactedStr = await getRedactedStr(res, params);
// the transcript contained "Example Domain" in the title
// which should be replaced with the hash
expect(redactedStr).toContain('<title>AAAAAAAAAAAAAA</title>');
});
it('should handle OPRF replacements in a chunked res', async () => {
const params = {
url: 'https://example.com/',
method: 'GET',
responseMatches: [
{
type: 'regex',
value: '\"name\":\"(?<name>.+?)\"',
}