Skip to content

Commit

Permalink
Add Live Proxy Example + injectScripts via query args (#136)
Browse files Browse the repository at this point in the history
* README: cleanup readme, point to new examples dir
- add live proxy rewriting example in ./examples/live-proxy/
- demonstrates minimum functionality for using wabac.js as a live proxy, including with custom inject scripts

* config: support passing injectScripts as query params to sw.js, eg. sw.js?injectScripts=path/to/script-1.js,path/another-script.js
  • Loading branch information
ikreymer authored Jul 27, 2023
1 parent 4f16da4 commit 85b3987
Show file tree
Hide file tree
Showing 8 changed files with 169 additions and 10 deletions.
23 changes: 15 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,34 @@
**wabac.js** provides a full web archive replay system, or 'wayback machine', using
[Service Workers](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers)

**wabac.js** is a core component of <img src="https://replayweb.page/assets/logo.svg" width="24" height="24"> [ReplayWeb.page](https://replayweb.page).
**wabac.js** is a core part of <img src="https://replayweb.page/assets/logo.svg" width="24" height="24"> [ReplayWeb.page](https://replayweb.page).

The rest of the ReplayWeb.page is located at [webrecorder/replayweb.page](https://github.com/webrecorder/replayweb.page)
This library provides the 'server-side' portion for web archive replay, and an API for managing web archive collections,
and is designed to be run as service worker (or web worker). The system handles URL rewriting and preparing web archive
pages to be replayed. This rewriting system complements the [wombat.js](https://github.com/webrecorder/wombat)
client-side rewriting system which runs on the client (injected into each page).

This library provides a 'server' component for web archive replay, and an API for managing web archive collections,
to be run within a service worker environment.
## ReplayWeb.page

Besides ReplayWeb.page, the wabac.js service worker system also be used directly or with custom UI.
The user-facing UI for ReplayWeb.page is located at [webrecorder/replayweb.page](https://github.com/webrecorder/replayweb.page)

It includes a 'server' rewriting system, and can also be run in Node. This rewriting system complements the [wombat.js](https://github.com/webrecorder/wombat)
client-side rewriting system which runs in the client.
## Usage Examples

*Note: [wabac.js 1.0](https://github.com/webrecorder/wabac.js-1.0) also included a built-in UI component. This version is still available at [https://wab.ac/](https://wab.ac/)*
Using the ReplayWeb.page is only one way to use wabac.js. Additional ways to use this library as a standalone will be added below:

- [Live Proxy](./examples/live-proxy) - an example of using wabac.js to render a live, rewritten proxy of other web pages, with custom scripts injected into each page. This can be used to provide an annotation viewer to live web pages.

## API Documentation

The API provides all functionality for loading web archives and getting information about a web archive collections.

*Documentation coming soon!*

## Old Version

[wabac.js 1.0](https://github.com/webrecorder/wabac.js-1.0) also included a built-in UI component. This version is still available at [https://wab.ac/](https://wab.ac/)*


## Contributing

Contributions are welcome! As wabac.js is evolving quickly, please open an issue before submitting a pull request.
Expand Down
4 changes: 2 additions & 2 deletions dist/sw.js

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions examples/live-proxy/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
sw.js
32 changes: 32 additions & 0 deletions examples/live-proxy/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
## Live Proxy Example

This example demonstrates the minimal use of `wabac.js` set up as a live rewriting proxy using a CORS proxy, and supporting
custom script injection.

The example consists of an `index.html` which loads wabac.js in a frame and `index.js`, which includes the setup
for initializing a single collection that loads data through a CORS proxy. The service worker is assumed to be located in the root of this directory
as well.


### Usage

1. Copy the latest build of `sw.js` to this directory, eg. `cp dist/sw.js examples/live-proxy/sw.js`.

2. Start an http server, eg. `http-server -p 10001`

3. Load `http://localhost:10001/`. The page should proxy `https://example.com/` by default.

4. Specify a different URL to proxy by specifying the URL in the hashtag, eg: `http://localhost:10001/#https://iana.org/`

### CORS Proxy

All loading is done through a CORS proxy, which is presumed to be an instance of [wabac-cors-proxy](https://github.com/webrecorder/wabac-cors-proxy)

The `proxyPrefix` in index.js should be configured to the proper endpoint for this proxy. We recommend deploying your own version of this proxy for production use. (The default endpoint is accessible for testing from `http://localhost:10001` and certain Webrecorder domains)


### Custom Script Injection

The example also demonstrates injecting a custom script into each replay page, by loading `sw.js?injectScripts=custom.js`.

The custom script is not rewritten and can be used to add additional functionality to the proxy.
1 change: 1 addition & 0 deletions examples/live-proxy/custom.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
console.log("Custom Script, Location is: " + window.location.href);
23 changes: 23 additions & 0 deletions examples/live-proxy/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<!doctype html>
<html>
<head>
<style>
html {
width: 100%;
height: 100%;
display: flex;
}
body {
width: 100%;
}
iframe {
width: 100%;
height: 100%;
}
</style>
<script src="./index.js"></script>
</head>
<body>
<iframe id="content"></iframe>
</body>
</html>
89 changes: 89 additions & 0 deletions examples/live-proxy/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
const proxyPrefix = "https://wabac-cors-proxy.webrecorder.workers.dev/proxy/";


class WabacLiveProxy
{
constructor() {
this.url = "";
}

async init() {
const scope = "./";

// also add inject of custom.js as a script into each replayed page
await navigator.serviceWorker.register("./sw.js?injectScripts=./custom.js", {scope});

let initedResolve = null;

const inited = new Promise((resolve) => initedResolve = resolve);

navigator.serviceWorker.addEventListener("message", (event) => {
if (event.data.msg_type === "collAdded") {
// the replay is ready to be loaded when this message is received
initedResolve();
}
});

const baseUrl = new URL(window.location);
baseUrl.hash = "";

const msg = {
msg_type: "addColl",
name: "liveproxy",
type: "live",
file: {"sourceUrl": `proxy:${proxyPrefix}`},
skipExisting: false,
extraConfig: {
"prefix": proxyPrefix,
"isLive": true,
"baseUrl": baseUrl.href,
"baseUrlHashReplay": true,
"noPostToGet": true
},
};

if (!navigator.serviceWorker.controller) {
navigator.serviceWorker.addEventListener("controllerchange", () => {
navigator.serviceWorker.controller.postMessage(msg);
});
} else {
navigator.serviceWorker.controller.postMessage(msg);
}

if (inited) {
await inited;
}

window.addEventListener("load", () => {
this.onHashChange();
});

window.addEventListener("hashchange", () => {
this.onHashChange();
});

this.onHashChange();
}

onHashChange () {
const m = window.location.hash.slice(1).match(/\/?(?:([\d]+)\/)?(.*)/);

const url = m && m[2] || "https://example.com/";

// don't change if same url
if (url === this.url) {
return;
}

let iframeUrl = `/w/liveproxy/mp_/${url}`;

const iframe = document.querySelector("#content");
iframe.src = iframeUrl;

this.url = url;

window.location.hash = `#${url}`;
}
}

new WabacLiveProxy().init();
6 changes: 6 additions & 0 deletions src/swmain.js
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,12 @@ class SWReplay {
this.staticData.set(this.staticPrefix + "wombat.js", {type: "application/javascript", content: WOMBAT});
this.staticData.set(this.staticPrefix + "wombatWorkers.js", {type: "application/javascript", content: WOMBAT_WORKERS});

if (sp.has("injectScripts")) {
const injectScripts = sp.get("injectScripts").split(",");
defaultConfig.injectScripts = defaultConfig.injectScripts ?
[...injectScripts, ...defaultConfig.injectScripts] : injectScripts;
}

if (defaultConfig.injectScripts) {
defaultConfig.injectScripts = defaultConfig.injectScripts.map(url => this.staticPrefix + "proxy/" + url);
}
Expand Down

0 comments on commit 85b3987

Please sign in to comment.