PageSourceSearch

https://smartnadlan.ai/_service-worker.js

js smartnadlan.ai collected 2026-10-05 15:06:00 UTC 5,639 bytes, 159 lines download raw bytes

1/**
2 * @license
3 * Copyright 2025 Google LLC
4 * SPDX-License-Identifier: Apache-2.0
5 */
6// service-worker.js
7
8// Define the target URL that we want to intercept and proxy.
9const TARGET_URL_PREFIX = 'https://generativelanguage.googleapis.com';
10
11const BYPASS_PATHS =
12    ['generateContentPerUserQuota', 'streamGenerateContentPerUserQuota'];
13
14// Installation event:
15self.addEventListener('install', (event) => {
16  try {
17    console.log('Service Worker: Installing...');
18    event.waitUntil(self.skipWaiting());
19  } catch (error) {
20    console.error('Service Worker: Error during install event:', error);
21    // If skipWaiting fails, the new SW might get stuck in a waiting state.
22  }
23});
24
25// Activation event:
26self.addEventListener('activate', (event) => {
27  try {
28    console.log('Service Worker: Activating...');
29    event.waitUntil(self.clients.claim());
30  } catch (error) {
31    console.error('Service Worker: Error during activate event:', error);
32    // If clients.claim() fails, the SW might not control existing pages until
33    // next nav.
34  }
35});
36
37// Fetch event:
38self.addEventListener('fetch', (event) => {
39  try {
40    const requestUrl = event.request.url;
41
42    if (requestUrl.startsWith(TARGET_URL_PREFIX) &&
43        !BYPASS_PATHS.some(path => requestUrl.includes(path))) {
44      console.log(`Service Worker: Intercepting request to ${requestUrl}`);
45
46      const remainingPathAndQuery =
47          requestUrl.substring(TARGET_URL_PREFIX.length);
48
49      const separator = remainingPathAndQuery.includes('?') ? '&' : '?';
50      const proxyUrl =
51          `${self.location.origin}/gemini-api-proxy${remainingPathAndQuery}${separator}__applet_proxy=true`;
52
53      console.log(`Service Worker: Proxying to ${proxyUrl}`);
54
55      // Construct headers for the request to the proxy
56      const newHeaders = new Headers();
57      // Copy essential headers from the original request
58      // For OPTIONS (preflight) requests, Access-Control-Request-*  are
59      // critical. For actual requests (POST, GET), Content-Type, Accept etc.
60      const headersToCopy = [
61        'Content-Type',
62        'Accept',
63        'Access-Control-Request-Method',
64        'Access-Control-Request-Headers',
65      ];
66
67      for (const headerName of headersToCopy) {
68        if (event.request.headers.has(headerName)) {
69          newHeaders.set(headerName, event.request.headers.get(headerName));
70        }
71      }
72
73      if (event.request.method === 'POST') {
74        // Ensure Content-Type is set for POST requests to the proxy, defaulting
75        // to application/json
76        if (!newHeaders.has('Content-Type')) {
77          console.warn(
78              'Service Worker: POST request to proxy was missing Content-Type in newHeaders. Defaulting to application/json.');
79          newHeaders.set('Content-Type', 'application/json');
80        } else {
81          console.log(
82              `Service Worker: POST request to proxy has Content-Type: ${
83                  newHeaders.get('Content-Type')}`);
84        }
85      }
86
87      const createProxyRequest = async () => {
88        const body =
89            event.request.method !== 'GET' && event.request.method !== 'HEAD' ?
90            await event.request.arrayBuffer() :
91            undefined;
92
93        const requestOptions = {
94          method: event.request.method,
95          headers: newHeaders,
96          body: body,
97          mode: event.request.mode,
98          credentials: event.request.credentials,
99          cache: event.request.cache,
100          redirect: event.request.redirect,
101          referrer: event.request.referrer,
102          integrity: event.request.integrity,
103        };
104
105        // Only set duplex if there's a body and it's a relevant method
106        if (body) {
107          requestOptions.duplex = 'half';
108        }
109
110        return new Request(proxyUrl, requestOptions);
111      };
112
113      const promise =
114          createProxyRequest()
115              .then(proxyRequest => fetch(proxyRequest))
116              .then((response) => {
117                console.log(`Service Worker: Successfully proxied request to ${
118                    proxyUrl}, Status: ${response.status}`);
119                return response;
120              })
121              .catch((error) => {
122                // Log more error details
123                console.error(`Service Worker: Error proxying request to ${
124                    proxyUrl}. Message: ${error.message}, Name: ${
125                    error.name}, Stack: ${error.stack}`);
126                return new Response(
127                    JSON.stringify({
128                      error: 'Proxying failed',
129                      details: error.message,
130                      name: error.name,
131                      proxiedUrl: proxyUrl
132                    }),
133                    {
134                      status:
135                          502,  // Bad Gateway is appropriate for proxy errors
136                      headers: {'Content-Type': 'application/json'}
137                    });
138              });
139
140      event.respondWith(promise);
141
142    } else {
143      // If the request URL doesn't match our target, let it proceed as normal.
144      event.respondWith(fetch(event.request));
145    }
146  } catch (error) {
147    // Log more error details for unhandled errors too
148    console.error(
149        'Service Worker: Unhandled error in fetch event handler. Message:',
150        error.message, 'Name:', error.name, 'Stack:', error.stack);
151    event.respondWith(new Response(
152        JSON.stringify({
153          error: 'Service worker fetch handler failed',
154          details: error.message,
155          name: error.name
156        }),
157        {status: 500, headers: {'Content-Type': 'application/json'}}));
158  }
159});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.