Skip to content

Commit 85d051d

Browse files
justin808claude
andcommitted
Add Chrome DevTools Protocol scripts for verifying early hints
These scripts connect to Chrome via the DevTools Protocol to inspect pages and verify HTTP 103 Early Hints are working: - check_early_hints.js - Node.js script using WebSocket - check_early_hints.py - Python script (requires websocket module) Both scripts: - Connect to Chrome running with --remote-debugging-port=9222 - Extract HTML from the loaded page - Search for Shakapacker Early Hints debug comments - Verify preload link headers Usage: node check_early_hints.js # or python3 check_early_hints.py 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 2a7e3d0 commit 85d051d

File tree

2 files changed

+200
-0
lines changed

2 files changed

+200
-0
lines changed

check_early_hints.js

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
const http = require('http');
2+
3+
// Fetch Chrome tabs
4+
const req = http.get('http://localhost:9222/json', (res) => {
5+
let data = '';
6+
7+
res.on('data', (chunk) => {
8+
data += chunk;
9+
});
10+
11+
res.on('end', () => {
12+
const tabs = JSON.parse(data);
13+
14+
if (tabs.length === 0) {
15+
console.log('No Chrome tabs found');
16+
return;
17+
}
18+
19+
const tab = tabs[0];
20+
console.log(`📱 Tab: ${tab.title}`);
21+
console.log(`🔗 URL: ${tab.url}\n`);
22+
23+
// Connect to WebSocket
24+
const WebSocket = require('ws');
25+
const ws = new WebSocket(tab.webSocketDebuggerUrl);
26+
27+
let msgId = 1;
28+
29+
ws.on('open', () => {
30+
console.log('✅ Connected to Chrome DevTools Protocol\n');
31+
32+
// Enable Runtime
33+
ws.send(JSON.stringify({
34+
id: msgId++,
35+
method: 'Runtime.enable'
36+
}));
37+
38+
// Get HTML content
39+
setTimeout(() => {
40+
ws.send(JSON.stringify({
41+
id: msgId++,
42+
method: 'Runtime.evaluate',
43+
params: {
44+
expression: 'document.documentElement.outerHTML'
45+
}
46+
}));
47+
}, 500);
48+
});
49+
50+
ws.on('message', (data) => {
51+
try {
52+
const msg = JSON.parse(data);
53+
54+
if (msg.result && msg.result.result && msg.result.result.value) {
55+
const html = msg.result.result.value;
56+
57+
// Look for Early Hints debug comments
58+
const earlyHintsMatch = html.match(/<!--[\s\S]*?Early Hints[\s\S]{0,500}?-->/g);
59+
60+
if (earlyHintsMatch) {
61+
console.log('🎉 Found Early Hints debug comments in HTML!\n');
62+
earlyHintsMatch.forEach(match => {
63+
console.log(match);
64+
console.log();
65+
});
66+
console.log('\n✅ SUCCESS: Early Hints are configured and working!');
67+
} else {
68+
console.log('❌ No Early Hints debug comments found in HTML');
69+
console.log('This might mean:');
70+
console.log(' - Early hints are not enabled');
71+
console.log(' - The deployment is not running the latest code');
72+
console.log(' - The page needs to be reloaded');
73+
}
74+
75+
// Also check for Link headers with preload
76+
const linkMatches = html.match(/<link[^>]*rel=["']preload["'][^>]*>/g);
77+
if (linkMatches) {
78+
console.log(`\n📦 Found ${linkMatches.length} preload links in HTML head:`);
79+
linkMatches.slice(0, 5).forEach(link => {
80+
console.log(` ${link}`);
81+
});
82+
}
83+
84+
ws.close();
85+
process.exit(0);
86+
}
87+
} catch (e) {
88+
// Ignore parse errors for other messages
89+
}
90+
});
91+
92+
ws.on('error', (err) => {
93+
console.error('❌ WebSocket error:', err.message);
94+
process.exit(1);
95+
});
96+
97+
// Timeout after 5 seconds
98+
setTimeout(() => {
99+
console.log('⏱️ Timeout - no HTML received');
100+
ws.close();
101+
process.exit(1);
102+
}, 5000);
103+
});
104+
});
105+
106+
req.on('error', (err) => {
107+
console.error('❌ Error connecting to Chrome:', err.message);
108+
console.log('\nMake sure Chrome is running with:');
109+
console.log(' --remote-debugging-port=9222');
110+
process.exit(1);
111+
});

check_early_hints.py

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
#!/usr/bin/env python3
2+
import json
3+
import urllib.request
4+
import websocket
5+
import ssl
6+
7+
# Get the WebSocket debugger URL
8+
response = urllib.request.urlopen('http://localhost:9222/json')
9+
tabs = json.loads(response.read())
10+
11+
if not tabs:
12+
print("No Chrome tabs found")
13+
exit(1)
14+
15+
# Use the first tab (the one we saw with the PR review app)
16+
tab = tabs[0]
17+
ws_url = tab['webSocketDebuggerUrl']
18+
19+
print(f"📱 Connecting to tab: {tab['title']}")
20+
print(f"🔗 URL: {tab['url']}\n")
21+
22+
# Connect via WebSocket
23+
ws = websocket.create_connection(ws_url, sslopt={"cert_reqs": ssl.CERT_NONE})
24+
25+
# Enable Network domain
26+
ws.send(json.dumps({"id": 1, "method": "Network.enable"}))
27+
response = json.loads(ws.recv())
28+
print(f"✅ Network enabled: {response}\n")
29+
30+
# Enable Page domain
31+
ws.send(json.dumps({"id": 2, "method": "Page.enable"}))
32+
response = json.loads(ws.recv())
33+
print(f"✅ Page enabled: {response}\n")
34+
35+
# Get the current HTML content
36+
ws.send(json.dumps({
37+
"id": 3,
38+
"method": "Runtime.evaluate",
39+
"params": {
40+
"expression": "document.documentElement.outerHTML"
41+
}
42+
}))
43+
44+
# Collect responses
45+
responses = []
46+
found_early_hints = False
47+
48+
for i in range(10): # Read a few messages
49+
try:
50+
msg = ws.recv()
51+
data = json.loads(msg)
52+
53+
if 'id' in data and data['id'] == 3:
54+
# This is our HTML response
55+
if 'result' in data and 'result' in data['result']:
56+
html = data['result']['result']['value']
57+
58+
# Search for Early Hints debug comments
59+
if 'Early Hints' in html:
60+
print("🎉 Found Early Hints debug comments in HTML!\n")
61+
62+
# Extract the comments
63+
import re
64+
matches = re.findall(r'<!--[\s\S]*?Early Hints[\s\S]*?-->', html)
65+
for match in matches:
66+
print(match)
67+
print()
68+
found_early_hints = True
69+
else:
70+
print("❌ No Early Hints debug comments found in HTML")
71+
72+
# Check for Link headers in the HTML head
73+
if 'rel=preload' in html or 'rel="preload"' in html:
74+
print("\n✅ Found preload links in HTML:")
75+
preload_matches = re.findall(r'<link[^>]*rel=["\']preload["\'][^>]*>', html)
76+
for link in preload_matches[:5]:
77+
print(f" {link}")
78+
break
79+
80+
except Exception as e:
81+
break
82+
83+
ws.close()
84+
85+
if found_early_hints:
86+
print("\n✅ SUCCESS: Early Hints are working!")
87+
else:
88+
print("\n⚠️ Could not verify Early Hints in the current page state")
89+
print("The page may need to be reloaded to capture HTTP 103 responses")

0 commit comments

Comments
 (0)