Skip to content

Instantly share code, notes, and snippets.

Last active July 6, 2023 20:24
Show Gist options
  • Save aslushnikov/c3e9d7f2e0f931a52be1242ba81fadb6 to your computer and use it in GitHub Desktop.
Save aslushnikov/c3e9d7f2e0f931a52be1242ba81fadb6 to your computer and use it in GitHub Desktop.
import pptr from 'puppeteer';
import http from 'http';
const createServer = (port, handler) => {
const server = http.createServer(handler);
return new Promise(x => server.listen(port, x));
// 1. Create a server that serves the main page.
// NOTE: this page will create an EventSource to the `/sse` endpoint, but this server DOES NOT
// accept requests to the URL.
await createServer(3000, (req, res) => {
if (req.url.startsWith('/sse'))
return res.end(503);
res.setHeader('content-type', 'text/html');
<!doctype html>
<script type="text/javascript">
const h1 = document.querySelector('h1');
h1.textContent = 'sse: initializing...';
const evtSource = new EventSource("/sse");
evtSource.onerror = () => h1.textContent = 'sse: error';
evtSource.onopen = () => h1.textContent = 'sse: opened';
evtSource.onmessage = () => h1.textContent = 'sse: message received';
// 2. Create another server that serves `/sse` endpoint.
await createServer(4321, (req, res) => {
res.statusCode = 200;
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('connection', 'keep-alive');
res.setHeader('Content-Type', 'text/event-stream');
res.write(`id: ${(new Date()).toLocaleTimeString()}\ndata: hello, world!\n\n`);
// 3. Launch a browser and open a page.
const browser = await pptr.launch();
const page = await browser.newPage();
// 4. Setup request interception for the `/sse` URL to redirect request to the second server.
await page.setRequestInterception(true);
page.on('request', (request) => {
if (request.url().match(/sse/)) {
console.log('intercepted!', request.url());
request.continue({ url: `http://localhost:4321/sse` });
} else {
// 5. Navigate to the page from the first server.
// NOTE: The url has to have the query parameters to reproduce the bug; removing query params fixes the issue.
await page.goto(`http://localhost:3000?foo=bar`);
// 6. Expect the EventSource in the page to successfully connect.
// Actual: EventSource yields error when trying to connect
// Expected: EventSource connects and receives events just fine
await page.waitForSelector('h1');
// Wait until H1 has a proper text value.
while (true) {
const header = await page.$eval('h1', el => el.textContent);
if (/message received/.test(header))
await new Promise(x => setTimeout(x, 1000));
await browser.close();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment