在WebView提前注入JS,通过Service Worker拦截POST请求
I totally get the frustration here—trying to intercept POST requests from a custom page is way trickier than GETs because most client-side callback interfaces don’t let you access the POST request body. After digging into this, I landed on a Service Worker-based solution that wraps the POST data into a GET request, making it easy to handle with shouldInterceptRequest().
Here’s the full setup, starting with the client-side code that listens for messages from the activated Service Worker:
function subscribeToSWMessages() { navigator.serviceWorker.onmessage = function (event) { // Listen for the converted GET request payload from the SW if (event.data?.type === 'POST_TO_GET_CONVERSION') { const convertedGetRequestUrl = event.data.payload; // Now you can pass this URL to shouldInterceptRequest() for processing console.log('Converted POST to interceptable GET:', convertedGetRequestUrl); // Example: yourInterceptHandler(convertedGetRequestUrl); } }; } // Make sure to call this only after the Service Worker is registered and active if ('serviceWorker' in navigator) { navigator.serviceWorker.register('/sw.js') .then(registration => { console.log('Service Worker registered:', registration); subscribeToSWMessages(); }) .catch(err => console.error('Service Worker registration failed:', err)); }
Then, in your Service Worker file (sw.js), add the logic to intercept POSTs, extract their body, and convert them into a GET request with the same data:
self.addEventListener('fetch', (event) => { const req = event.request; // Target only your custom page's POST requests—update the URL match as needed if (req.method === 'POST' && req.url.startsWith('https://your-custom-page-domain.com/')) { event.respondWith( // Clone the request to read the body without consuming it req.clone().text().then(body => { // Parse the POST body (adjust this if your payload is form data instead of JSON) let postData; try { postData = JSON.parse(body); } catch (e) { // Fallback for non-JSON payloads, like form-encoded data postData = new URLSearchParams(body); } // Build the GET URL with the POST data as query parameters const getUrl = new URL(req.url); if (typeof postData === 'object') { Object.entries(postData).forEach(([key, value]) => { getUrl.searchParams.append(key, value); }); } // Send the converted GET URL back to the client self.clients.matchAll({ type: 'window' }).then(clients => { clients.forEach(client => { client.postMessage({ type: 'POST_TO_GET_CONVERSION', payload: getUrl.toString() }); }); }); // Return a response to the original POST request (customize this as needed) return new Response('POST request intercepted and converted', { status: 200, headers: { 'Content-Type': 'text/plain' } }); }) ); } });
Important Things to Keep in Mind:
- Payload Format: The example assumes your POST body is JSON, but if you’re dealing with form-encoded data, swap
req.clone().text()withreq.clone().formData()and adjust the parsing logic accordingly. - Request Targeting: The
req.url.startsWith()check ensures you only intercept POSTs from your specific custom page—tweak this URL match to fit your exact use case. - Interception Workflow: Once the Service Worker converts the POST to a GET, it sends the full URL to the client via
postMessage(). Your client-side listener catches this and passes the URL toshouldInterceptRequest(), which can handle it just like a regular GET request.
This method works because Service Workers have full access to request bodies, which most client-side intercept callbacks lack. It’s a clean way to bridge the gap and make those tricky POSTs interceptable.
内容的提问来源于stack exchange,提问作者infosphere

