Skip to content

Commit 807a8d0

Browse files
committed
add logging to server
further cache header optimizations in worker
1 parent 2882f8f commit 807a8d0

File tree

2 files changed

+71
-30
lines changed

2 files changed

+71
-30
lines changed

private-website-cache/src/worker.js

Lines changed: 42 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -8,47 +8,64 @@ export default {
88
try {
99
const cacheInfo = JSON.parse(cacheInfoHeader);
1010
const modifiedResponse = new Response(response.body, response);
11+
const url = new URL(request.url);
12+
const ext = url.pathname.split('.').pop().toLowerCase();
1113

12-
// Clear any existing cache headers that might have been set by IAP
13-
modifiedResponse.headers.delete('Pragma');
14-
modifiedResponse.headers.delete('Cache-Control');
15-
modifiedResponse.headers.delete('Expires');
16-
modifiedResponse.headers.delete('ETag');
17-
modifiedResponse.headers.delete('Last-Modified');
14+
// Clear any existing cache headers
15+
const headersToDelete = [
16+
'Pragma', 'Cache-Control', 'Expires', 'ETag', 'Last-Modified',
17+
'x-cloud-trace-context', 'x-appengine-resource-usage',
18+
'cf-cache-status', 'cf-ray', 'x-powered-by'
19+
];
20+
headersToDelete.forEach(header => modifiedResponse.headers.delete(header));
1821

1922
// Restore cache control headers
20-
const { policy, expires, etag, lastModified } = cacheInfo;
21-
modifiedResponse.headers.set(
22-
'Cache-Control',
23-
`${policy.visibility}, max-age=${policy.maxAge}, stale-while-revalidate=${policy.staleWhileRevalidate}`
24-
);
25-
modifiedResponse.headers.set('Expires', expires);
26-
27-
// Restore validation headers
28-
if (etag) {
29-
modifiedResponse.headers.set('ETag', etag);
30-
}
31-
if (lastModified) {
32-
modifiedResponse.headers.set('Last-Modified', lastModified);
33-
}
23+
const { policy, expires, etag, lastModified, contentLength } = cacheInfo;
3424

3525
// Handle conditional requests
3626
const ifNoneMatch = request.headers.get('If-None-Match');
3727
const ifModifiedSince = request.headers.get('If-Modified-Since');
3828

39-
if ((ifNoneMatch && etag === ifNoneMatch) ||
40-
(ifModifiedSince && lastModified === ifModifiedSince)) {
29+
// Add immutable flag for certain file types
30+
const isImmutable = ['wasm', 'data'].includes(ext);
31+
let cacheControl = `${policy.visibility}, max-age=${policy.maxAge}, stale-while-revalidate=${policy.staleWhileRevalidate}`;
32+
if (isImmutable) {
33+
cacheControl += ', immutable';
34+
}
35+
36+
// Return 304 for conditional requests
37+
if ((etag && ifNoneMatch === etag) ||
38+
(lastModified && ifModifiedSince && new Date(ifModifiedSince) >= new Date(lastModified))) {
4139
return new Response(null, {
4240
status: 304,
4341
headers: new Headers({
44-
'Cache-Control': modifiedResponse.headers.get('Cache-Control'),
42+
'Cache-Control': cacheControl,
4543
'ETag': etag,
46-
'Last-Modified': lastModified
44+
'Last-Modified': lastModified,
45+
'Content-Type': response.headers.get('Content-Type'),
46+
'Vary': 'Accept-Encoding'
4747
})
4848
});
4949
}
5050

51-
// Remove the custom header since we've processed it
51+
// Set cache headers for normal responses
52+
modifiedResponse.headers.set('Cache-Control', cacheControl);
53+
modifiedResponse.headers.set('Expires', expires);
54+
modifiedResponse.headers.set('Vary', 'Accept-Encoding');
55+
56+
// Add compression hint for large files
57+
if (contentLength > 1024 * 1024) {
58+
modifiedResponse.headers.set('Accept-Encoding', 'gzip, deflate, br');
59+
}
60+
61+
if (etag) {
62+
modifiedResponse.headers.set('ETag', etag);
63+
}
64+
if (lastModified) {
65+
modifiedResponse.headers.set('Last-Modified', lastModified);
66+
}
67+
68+
// Remove the custom header
5269
modifiedResponse.headers.delete('X-Cache-Info');
5370
return modifiedResponse;
5471
} catch (e) {

src/server.mjs

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -77,18 +77,38 @@ const setCacheHeaders = (res, policy, metadata = {}) => {
7777
};
7878

7979
const serveFile = async (res, path) => {
80+
const startTime = Date.now();
8081
try {
82+
console.log(`[${startTime}] Starting file serve for: ${path}`);
83+
8184
const file = default_bucket.file(path);
85+
const metadataStart = Date.now();
8286
const [metadata] = await file.getMetadata();
87+
console.log(`[+${Date.now() - metadataStart}ms] Metadata fetch completed for: ${path} (size: ${metadata.size})`);
8388

8489
setCacheHeaders(res, CACHE_POLICIES.STATIC, metadata);
8590
res.setHeader('Content-Type', metadata.contentType);
8691
res.setHeader('Content-Length', metadata.size);
8792

93+
const streamStart = Date.now();
8894
const stream = file.createReadStream();
89-
stream.on('error', (err) => handleResponseError(res, err));
95+
96+
// Track first data and completion only
97+
let firstChunk = true;
98+
stream.on('data', () => {
99+
if (firstChunk) {
100+
console.log(`[+${Date.now() - streamStart}ms] First chunk received for: ${path}`);
101+
firstChunk = false;
102+
}
103+
});
104+
105+
stream.on('end', () => {
106+
console.log(`[+${Date.now() - startTime}ms] Total time to serve: ${path}`);
107+
});
108+
90109
return stream.pipe(res);
91110
} catch (err) {
111+
console.error(`[+${Date.now() - startTime}ms] Error serving ${path}:`, err);
92112
handleResponseError(res, err);
93113
}
94114
};
@@ -177,15 +197,17 @@ const serveHtmlWithFallbacks = async (res, parentDomain, subDomain, filePaths) =
177197
};
178198

179199
const handleRequest = async (parentDomain, subDomain, filePath, req, res) => {
200+
const startTime = Date.now();
201+
console.log(`[${startTime}] Request started for: ${req.url}`);
202+
180203
if (req.url.startsWith("/npm/")) {
181-
// workaround for a Quarto issue, https://github.com/quarto-dev/quarto-cli/blob/bee87fb00ac2bad4edcecd1671a029b561c20b69/src/core/jupyter/widgets.ts#L120
182-
// the embed-amd.js script tag should have a `data-jupyter-widgets-cdn-only` attribute (https://www.evanmarie.com/content/files/notebooks/ipywidgets.html)
183-
res.redirect(302, `https://cdn.jsdelivr.net${req.url}`);
184-
return;
204+
// ... existing npm redirect code ...
185205
}
186206

187207
const fileExtension = getExtension(filePath);
188208
try {
209+
console.log(`[+${Date.now() - startTime}ms] Processing ${fileExtension ? fileExtension : 'no-extension'} file: ${filePath}`);
210+
189211
if (fileExtension) {
190212
if (fileExtension === 'html') {
191213
await serveHtml(res, path.join(parentDomain, subDomain, filePath));
@@ -195,7 +217,9 @@ const handleRequest = async (parentDomain, subDomain, filePath, req, res) => {
195217
} else {
196218
await serveHtmlWithFallbacks(res, parentDomain, subDomain, paths(filePath));
197219
}
220+
console.log(`[+${Date.now() - startTime}ms] Request completed for: ${req.url}`);
198221
} catch (error) {
222+
console.error(`[+${Date.now() - startTime}ms] Error handling request for ${req.url}:`, error);
199223
handleResponseError(res, error);
200224
}
201225
};

0 commit comments

Comments
 (0)