1
0
mirror of https://github.com/webrecorder/pywb.git synced 2025-03-20 02:39:13 +01:00
pywb/wombat/test/helpers/initServer.js
John Berlin 94784d6e5d wombat overhaul! fixes #449 (#451)
wombat:
 - I: function overrides applied by wombat now better appear to be the original new function name same as originals when possible
 - I: WombatLocation now looks and behaves more like the original Location interface
 - I: The custom storage class now looks and behaves more like the original Storage
 - I: SVG image rewriting has been improved: both the href and xlink:href deprecated since SVG2 now rewritten always
 - I: document.open now handles the case of creation of a new window
 - I: Request object rewriting of the readonly href property is now correctly handled
 - I: EventTarget.addEventListener, removeEventListener overrides now preserve the original this argument of the wrapped listener
 - A: document.close override to ensure wombat is initialized after write or writeln usage
 - A: reconstruction of <doctype...> in rewriteHTMLComplete IFF it was included in the original string of HTML
 - A: document.body setter override to ensure rewriting of the new body or frameset
 - A: Attr.[value, nodeValue, textContent] added setter override to perform URL rewrites
 - A: SVGElements rewriting of the filter, style, xlink:href, href, and src attributes
 - A: HTMLTrackElement rewriting of the src attribute of the
 - A: HTMLQuoteElement and HTMLModElement rewriting of the cite attribute
 - A: Worklet.addModule: Loads JS module specified by a URL.
 - A: HTMLHyperlinkElementUtils overrides to the areaelement
 - A: ShadowRootoverrides to: innerHTML even though inherites from DocumentFragement and Node it still has innerHTML getter setter.
 - A: ShadowRoot, Element, DocumentFragment append, prepend: adds strings of HTML or a new Node inherited from ParentNode
 - A: StylePropertyMap override: New way to access and set CSS properties.
 - A: Response.redirecthttps rewriting of the URL argument.
 - A:  UIEvent, MouseEvent, TouchEvent, KeyboardEvent, WheelEvent, InputEvent, and CompositionEven constructor and init{even-name} overrides in order to ensure that wombats JS Proxy usage does not affect their defined behaviors
 - A: XSLTProcessor override to ensure its usage is not affected by wombats JS Proxy usage.
 - A: navigator.unregisterProtocolHandler: Same override as existing navigator.registerProtocolHandler but from the inverse operation
 - A: PresentationRequest: Constructor takes a URL or an array of URLs.
 - A: EventSource and WebSocket override in order to ensure that they do not cause live leaks
 - A: overrides for the child node interface
 - Fix: autofetch worker creatation of the backing worker when it is operating within an execution context with a null origin
tests:
  - A: 559 tests specific to wombat and client side rewritting
pywb:
  - Fix: a few broken tests due to iana.org requiring a user agent in its requests
rewrite:
  - introduced a new JSWorkerRewriter class in order to support rewriting via wombat workers in the context of all supported worker variants via
  - ensured rewriter app correctly sets the static prefix
ci:
 - Modified travis.yml to specifically enumerate jobs
documentation:
  - Documented new wombat, wombat proxy moded, wombat workers
auto-fetch:
 - switched to mutation observer when in proxy mode so that the behaviors can operate in tandem with the autofetcher
2019-05-15 11:42:51 -07:00

145 lines
4.4 KiB
JavaScript

const path = require('path');
const fs = require('fs-extra');
const createServer = require('fastify');
const host = '127.0.0.1';
const port = 3030;
const gracefullShutdownTimeout = 50000;
const shutdownOnSignals = ['SIGINT', 'SIGTERM', 'SIGHUP'];
const assetsPath = path.join(__dirname, '..', 'assets');
const httpsSandboxPath = path.join(assetsPath, 'sandbox.html');
const theyFoundItPath = path.join(assetsPath, 'it.html');
function promiseResolveReject() {
const prr = { promise: null, resolve: null, reject: null };
prr.promise = new Promise((resolve, reject) => {
let to = setTimeout(
() => reject(new Error('wait for request timed-out')),
15000
);
prr.resolve = () => {
clearTimeout(to);
resolve();
};
prr.reject = reason => {
clearTimeout(to);
reject(reason);
};
});
return prr;
}
/**
* @return {Promise<fastify.FastifyInstance>}
*/
async function initServer() {
const serverOpts = { logger: false };
const requestSubscribers = new Map();
const checkReqSubscribers = (pathName, request, reply) => {
const handler = requestSubscribers.get(pathName);
if (handler) {
handler.resolve(request);
requestSubscribers.delete(pathName);
}
};
const fastify = createServer(serverOpts);
fastify
.get(
'/live/20180803160549wkr_/https://tests.wombat.io/testWorker.js',
async (request, reply) => {
const init = `new WBWombat({'prefix': 'http://localhost:${port}/live/20180803160549', 'prefixMod': 'http://localhost:${port}/live/20180803160549wkr_/', 'originalURL': 'https://tests.wombat.io/testWorker.js'});`;
reply
.code(200)
.type('application/javascript; charset=UTF-8')
.send(
`self.importScripts('/testWorker.js');(function() { self.importScripts('/wombatWorkers.js'); ${init}})();`
);
}
)
.get(
'/live/20180803160549sw_/https://tests.wombat.io/testServiceWorker.js',
(request, reply) => {
reply
.code(200)
.type('application/javascript; charset=UTF-8')
.header(
'Service-Worker-Allowed',
`${address}/live/20180803160549mp_/https://tests.wombat.io/`
)
.send('console.log("hi")');
}
)
.get(
'/live/20180803160549mp_/https://tests.wombat.io/it',
async (request, reply) => {
reply.type('text/html').status(200);
return fs.createReadStream(theyFoundItPath);
}
)
.get(
'/live/20180803160549mp_/https://tests.wombat.io/',
async (request, reply) => {
reply.type('text/html').status(200);
return fs.createReadStream(httpsSandboxPath);
}
)
.get(
'/live/20180803160549mp_/https://tests.wombat.io/test',
async (request, reply) => {
reply.type('application/json; charset=utf-8').status(200);
return { headers: request.headers, url: request.raw.originalUrl };
}
)
.decorate('reset', () => {
const error = new Error('Static Server has been reset');
for (const prr of requestSubscribers.values()) {
prr.reject.call(null, error);
}
requestSubscribers.clear();
})
.decorate('stop', () => {
fastify.reset();
return fastify.close();
})
.decorate('testPage', `http://localhost:${port}/testPage.html`)
.decorate('waitForRequest', route => {
let prr = requestSubscribers.get(route);
if (prr) return prr.promise;
prr = promiseResolveReject();
requestSubscribers.set(route, prr);
return prr.promise;
})
.addHook('onRequest', (request, reply, next) => {
checkReqSubscribers(request.raw.url, request, reply);
// console.log(`${request.raw.method} ${request.raw.url}`);
next();
})
.register(require('fastify-favicon'))
.register(require('fastify-static'), {
root: assetsPath,
etag: false,
lastModified: false
});
shutdownOnSignals.forEach(signal => {
process.once(signal, () => {
setTimeout(() => {
console.error(
`received ${signal} signal, terminate process after timeout of ${gracefullShutdownTimeout}ms`
);
process.exit(1);
}, gracefullShutdownTimeout).unref();
console.log(`received ${signal} signal, triggering close hook`);
fastify.stop().then(() => {
process.exit(0);
});
});
});
const address = await fastify.listen(port, host);
return fastify;
}
module.exports = initServer;