Skip to content

Commit fd3bc49

Browse files
Add detailed logging to fetch interception for debugging
1 parent 92570e9 commit fd3bc49

2 files changed

Lines changed: 131 additions & 107 deletions

File tree

src/background.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ function isLikelySolidServer (origin) {
338338
'solidweb.org',
339339
'/.well-known/solid'
340340
];
341-
341+
342342
return solidIndicators.some(indicator => origin.includes(indicator));
343343
}
344344

src/injected.js

Lines changed: 130 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,122 @@
33
* Bridges between injected window.nostr and background script
44
*/
55

6+
// CRITICAL: Set up fetch/XHR interception IMMEDIATELY, synchronously
7+
// This must run before ANY other code, including page scripts
8+
(function setupInterceptionImmediately () {
9+
'use strict';
10+
11+
// Store original functions
12+
const originalFetch = window.fetch;
13+
const originalXHROpen = XMLHttpRequest.prototype.open;
14+
const originalXHRSend = XMLHttpRequest.prototype.send;
15+
16+
// Helper to get auth header (will be async, but we'll handle that)
17+
let getAuthHeaderFn = null;
18+
19+
// Set up the async auth header function (will be defined below)
20+
function setAuthHeaderFn (fn) {
21+
getAuthHeaderFn = fn;
22+
}
23+
24+
// Intercept fetch - synchronous wrapper, async implementation
25+
window.fetch = function (url, options = {}) {
26+
const urlString = typeof url === 'string' ? url : url.toString();
27+
console.log('[Podkey] 🔍 fetch() called:', urlString, options.method || 'GET');
28+
29+
// If we have the auth function, use it
30+
if (getAuthHeaderFn) {
31+
console.log('[Podkey] Auth function available, adding header...');
32+
const promise = (async () => {
33+
try {
34+
const authHeader = await getAuthHeaderFn(url, options.method || 'GET', options.body);
35+
if (authHeader) {
36+
options = options || {};
37+
options.headers = options.headers || {};
38+
if (options.headers instanceof Headers) {
39+
options.headers.set('Authorization', authHeader);
40+
console.log('[Podkey] ✅ Added NIP-98 auth header (Headers)');
41+
} else {
42+
options.headers['Authorization'] = authHeader;
43+
console.log('[Podkey] ✅ Added NIP-98 auth header (object)');
44+
}
45+
} else {
46+
console.log('[Podkey] ⚠️ No auth header returned (will retry on 401)');
47+
}
48+
} catch (e) {
49+
console.error('[Podkey] Error in fetch interceptor:', e);
50+
}
51+
return originalFetch.call(this, url, options);
52+
})();
53+
54+
// Handle 401 retry
55+
return promise.then(response => {
56+
if (response.status === 401 && getAuthHeaderFn) {
57+
console.log('[Podkey] 🔄 401 detected, retrying with auth...');
58+
return (async () => {
59+
try {
60+
const authHeader = await getAuthHeaderFn(url, options.method || 'GET', options.body);
61+
if (authHeader) {
62+
const retryOptions = { ...options };
63+
retryOptions.headers = retryOptions.headers || {};
64+
if (retryOptions.headers instanceof Headers) {
65+
retryOptions.headers.set('Authorization', authHeader);
66+
} else {
67+
retryOptions.headers['Authorization'] = authHeader;
68+
}
69+
console.log('[Podkey] 🔄 Retrying with NIP-98 auth...');
70+
const retryResponse = await originalFetch.call(this, url, retryOptions);
71+
if (retryResponse.status === 200 || retryResponse.status === 201) {
72+
console.log('[Podkey] ✅✅ NIP-98 auth retry successful!');
73+
} else {
74+
console.log('[Podkey] ⚠️ Retry still failed:', retryResponse.status);
75+
}
76+
return retryResponse;
77+
}
78+
} catch (e) {
79+
console.error('[Podkey] Error in 401 retry:', e);
80+
}
81+
return response;
82+
})();
83+
}
84+
return response;
85+
});
86+
}
87+
88+
// Fallback if auth function not ready yet
89+
console.log('[Podkey] ⚠️ Auth function not ready yet, making request without auth');
90+
return originalFetch.call(this, url, options);
91+
};
92+
93+
// Intercept XMLHttpRequest
94+
XMLHttpRequest.prototype.open = function (method, url, ...args) {
95+
this._podkeyMethod = method;
96+
this._podkeyUrl = url;
97+
return originalXHROpen.apply(this, [method, url, ...args]);
98+
};
99+
100+
XMLHttpRequest.prototype.send = function (body) {
101+
if (getAuthHeaderFn && this._podkeyUrl) {
102+
(async () => {
103+
try {
104+
const authHeader = await getAuthHeaderFn(this._podkeyUrl, this._podkeyMethod, body);
105+
if (authHeader) {
106+
this.setRequestHeader('Authorization', authHeader);
107+
}
108+
} catch (e) {
109+
console.error('[Podkey] Error in XHR interceptor:', e);
110+
}
111+
})();
112+
}
113+
return originalXHRSend.apply(this, [body]);
114+
};
115+
116+
// Expose setter for the auth function
117+
window.__podkey_setAuthFn = setAuthHeaderFn;
118+
119+
console.log('[Podkey] ✅ Synchronous interception setup complete');
120+
})();
121+
6122
// Inject the nostr provider script into the page
7123
const script = document.createElement('script');
8124
script.src = chrome.runtime.getURL('src/nostr-provider.js');
@@ -67,110 +183,10 @@ window.addEventListener('podkey-request', async (event) => {
67183
}
68184
});
69185

70-
// NIP-98 auto-auth: Intercept fetch and XMLHttpRequest
71-
(function interceptHttpRequests () {
72-
// Intercept fetch
73-
const originalFetch = window.fetch;
74-
window.fetch = async function (url, options = {}) {
75-
try {
76-
const authHeader = await getNip98AuthHeader(url, options.method || 'GET', options.body);
77-
if (authHeader) {
78-
options.headers = options.headers || {};
79-
if (options.headers instanceof Headers) {
80-
options.headers.set('Authorization', authHeader);
81-
} else {
82-
options.headers['Authorization'] = authHeader;
83-
}
84-
}
85-
} catch (error) {
86-
console.error('[Podkey] Error adding NIP-98 auth to fetch:', error);
87-
}
88-
89-
const response = await originalFetch(url, options);
90-
91-
// Handle 401 responses - retry with NIP-98 auth
92-
if (response.status === 401) {
93-
console.log('[Podkey] 401 detected, attempting NIP-98 auth retry for:', url);
94-
try {
95-
// Clone response to read body if needed, but for retry we'll make a new request
96-
const authHeader = await getNip98AuthHeader(url, options.method || 'GET', options.body);
97-
if (authHeader) {
98-
// Retry with auth
99-
const retryOptions = { ...options };
100-
retryOptions.headers = retryOptions.headers || {};
101-
102-
// Handle Headers object
103-
if (retryOptions.headers instanceof Headers) {
104-
retryOptions.headers.set('Authorization', authHeader);
105-
} else if (retryOptions.headers instanceof Object) {
106-
retryOptions.headers['Authorization'] = authHeader;
107-
} else {
108-
retryOptions.headers = { 'Authorization': authHeader };
109-
}
110-
111-
console.log('[Podkey] Retrying request with NIP-98 auth');
112-
const retryResponse = await originalFetch(url, retryOptions);
113-
114-
if (retryResponse.status === 200 || retryResponse.status === 201) {
115-
console.log('[Podkey] ✅ NIP-98 auth successful!');
116-
} else {
117-
console.log('[Podkey] ⚠️ Retry still failed with status:', retryResponse.status);
118-
}
119-
120-
return retryResponse;
121-
} else {
122-
console.log('[Podkey] No NIP-98 auth header available for retry');
123-
}
124-
} catch (error) {
125-
console.error('[Podkey] Error retrying fetch with NIP-98 auth:', error);
126-
}
127-
}
128-
129-
return response;
130-
};
131-
132-
// Intercept XMLHttpRequest
133-
const originalOpen = XMLHttpRequest.prototype.open;
134-
const originalSend = XMLHttpRequest.prototype.send;
135-
136-
XMLHttpRequest.prototype.open = function (method, url, ...args) {
137-
this._podkeyMethod = method;
138-
this._podkeyUrl = url;
139-
return originalOpen.apply(this, [method, url, ...args]);
140-
};
141-
142-
XMLHttpRequest.prototype.send = async function (body) {
143-
try {
144-
const authHeader = await getNip98AuthHeader(this._podkeyUrl, this._podkeyMethod, body);
145-
if (authHeader) {
146-
this.setRequestHeader('Authorization', authHeader);
147-
}
148-
} catch (error) {
149-
console.error('[Podkey] Error adding NIP-98 auth to XHR:', error);
150-
}
151-
152-
// Handle 401 responses
153-
this.addEventListener('load', async function () {
154-
if (this.status === 401) {
155-
try {
156-
const authHeader = await getNip98AuthHeader(this._podkeyUrl, this._podkeyMethod, body);
157-
if (authHeader) {
158-
// Retry with auth
159-
const retryXhr = new XMLHttpRequest();
160-
retryXhr.open(this._podkeyMethod, this._podkeyUrl);
161-
retryXhr.setRequestHeader('Authorization', authHeader);
162-
// Copy other headers if needed
163-
retryXhr.send(body);
164-
// Note: This is a simplified retry - in practice, you'd want to handle the response properly
165-
}
166-
} catch (error) {
167-
console.error('[Podkey] Error retrying XHR with NIP-98 auth:', error);
168-
}
169-
}
170-
});
171-
172-
return originalSend.apply(this, [body]);
173-
};
186+
// NIP-98 auto-auth: Set up the async auth header function
187+
// This connects to the synchronous interceptor above
188+
(function setupAuthFunction () {
189+
console.log('[Podkey] Setting up NIP-98 auth function...');
174190

175191
async function getNip98AuthHeader (url, method, body) {
176192
try {
@@ -190,9 +206,9 @@ window.addEventListener('podkey-request', async (event) => {
190206
}
191207

192208
if (response) {
193-
console.log('[Podkey] Got NIP-98 auth header');
209+
console.log('[Podkey] Got NIP-98 auth header');
194210
} else {
195-
console.log('[Podkey] No NIP-98 auth header (origin not trusted, auto-sign disabled, or no keypair)');
211+
console.log('[Podkey] No NIP-98 auth header (origin not trusted, auto-sign disabled, or no keypair)');
196212
}
197213

198214
return response || null;
@@ -201,6 +217,14 @@ window.addEventListener('podkey-request', async (event) => {
201217
return null;
202218
}
203219
}
220+
221+
// Connect the auth function to the synchronous interceptor
222+
if (window.__podkey_setAuthFn) {
223+
window.__podkey_setAuthFn(getNip98AuthHeader);
224+
console.log('[Podkey] ✅ Auth function connected');
225+
} else {
226+
console.error('[Podkey] ❌ Could not connect auth function - interceptor not ready');
227+
}
204228
})();
205229

206230
console.log('[Podkey] Content script loaded with NIP-98 auto-auth interception');

0 commit comments

Comments
 (0)