Skip to content

Instantly share code, notes, and snippets.

@KernelDeimos
Last active July 19, 2022 14:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save KernelDeimos/951509688f0b1b4a98ed5bd7fd879151 to your computer and use it in GitHub Desktop.
Save KernelDeimos/951509688f0b1b4a98ed5bd7fd879151 to your computer and use it in GitHub Desktop.
Nested iframe pushes message to root page (bad)
const express = require('express');
const dedent = require('dedent');
const scripts = {
TerminalPage: ({ app, route }) => {
document.addEventListener('DOMContentLoaded', () => {
document.getElementById('action').addEventListener('click', () => {
const val = document.getElementById('message').value;
const ori = document.getElementById('origin').value;
console.log(`[${app.name}/${route}] sending message: ` + val)
// Please DO NOT actually ever do this!
// A page expecting to receive messages from an iframe will
// suddenly stop receiving those messages if it happens to
// be included in another iframe. Use window.parent instead.
let w = window.top;
// ^ I repeat, DON'T DO IT
w.postMessage(val, (ori || undefined));
});
});
},
IFrameHolder: ({ app, route }) => {
document.addEventListener('DOMContentLoaded', () => {
console.log(`[${app.name}/${route}] registering listener`);
window.addEventListener('message', val => {
console.log(`[${app.name}/${route}] received message: ` + val.data);
// const line = document.createElement('div')
// line.innerText = 'message: ' + val
// document.body.appendChild(line)
});
});
}
}
const routeTypes = {
TerminalPage: ({ app, route, params }) => {
app.express.get('/'+route, function (req, res) {
res.set('Content-Type', 'text/html');
res.send(Buffer.from(dedent`
<!DOCTYPE html>
<html>
<head>
<title>terminal</title>
<script>(${scripts.TerminalPage.toString()})(${
JSON.stringify({ app, route })})</script>
</head>
<body>
message: <input id="message" type="text">
origin: <input id="origin" type="text">
<input id="action" type="button" value="postMessage" />
</body>
</html>
`));
});
},
IFrameHolder: ({ apps, app, route, params }) => {
app.express.get('/'+route, function (req, res) {
const originApp = apps.find(a => a.name == params.origin);
const url = 'http://127.0.0.1:' + originApp.port +
'/' + params.page;
res.set('Content-Type', 'text/html');
res.send(Buffer.from(dedent`
<!DOCTYPE html>
<html>
<head>
<title>has iframe</title>
<style>
iframe { resize: both; width: 80%; height: 80%; }
</style>
<script>(${scripts.IFrameHolder.toString()})(${
JSON.stringify({ app, route })})</script>
</head>
<body>
<iframe src="${url}" resizable=true />
</body>
</html>
`));
});
}
};
const App = {}
App.install = function (x, app) {
for ( const route in app.routes ) {
const routeSpec = { ...app.routes[route] };
const routeType = routeSpec.$;
delete routeSpec.$;
routeTypes[routeType]({ ...x, app, route, params: routeSpec });
}
};
const apps = [
{ name: 'app0', port: 3020, routes: {
end: { $: 'TerminalPage' }
} },
{ name: 'app1', port: 3021, routes: {
middle: { $: 'IFrameHolder', origin: 'app0', page: 'end' },
// demo: { $: 'IFrameHolder', origin: 'app1', page: 'wizard' },
} },
{ name: 'app2', port: 3022, routes: {
// wizard: { $: 'IFrameHolder', origin: 'app0', page: 'end' },
top: { $: 'IFrameHolder', origin: 'app1', page: 'middle' },
} },
];
for ( const app of apps ) { app.express = express(); }
for ( const app of apps ) { App.install({ apps }, app); }
for ( const app of apps ) { app.express.listen(app.port); }
{
"dependencies": {
"dedent": "^0.7.0",
"express": "^4.18.1"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment