Skip to content

Commit 6cf23f1

Browse files
CopilotL3P3
andauthored
Add HTTP cache headers for static files (#63)
* Initial plan * Add HTTP cache headers for static files with ETag and Last-Modified support Co-authored-by: L3P3 <4629449+L3P3@users.noreply.github.com> * Remove redundant ETag implementation, keep only Last-Modified Co-authored-by: L3P3 <4629449+L3P3@users.noreply.github.com> * Simplify cache implementation: inline variables, use return instead of throw Co-authored-by: L3P3 <4629449+L3P3@users.noreply.github.com> * Refactor cache and range request handling --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: L3P3 <4629449+L3P3@users.noreply.github.com> Co-authored-by: Len <dev@l3p3.de>
1 parent bc409ff commit 6cf23f1

2 files changed

Lines changed: 53 additions & 49 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "rtjscomp",
3-
"version": "0.9.12",
3+
"version": "0.9.13",
44
"description": "php-like server but with javascript",
55
"repository": {
66
"type": "git",

rtjscomp.js

Lines changed: 52 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1527,73 +1527,77 @@ const request_handle = async (request, response, https) => {
15271527
}
15281528

15291529
if (spam_enabled) spam('static_send', [path, file_compression]);
1530-
response.setHeader('Cache-Control', 'public, max-age=600');
1530+
15311531
if (compression_enabled_type) {
15321532
response.setHeader('Vary', 'Accept-Encoding');
15331533
}
1534+
response.setHeader('Cache-Control', 'public, max-age=31536000');
1535+
response.setHeader('Last-Modified', new Date(file_stat.mtimeMs).toUTCString());
1536+
1537+
if (
1538+
'if-modified-since' in request_headers &&
1539+
file_stat.mtimeMs <= new Date(request_headers['if-modified-since'])
1540+
) {
1541+
response.statusCode = 304;
1542+
response.end();
1543+
return;
1544+
}
15341545

1535-
// Handle Range requests only for uncompressed files
15361546
let range_start = 0;
15371547
let range_end = file_stat.size - 1;
15381548
let is_range_request = false;
15391549

1540-
if (
1541-
file_compression === COMPRESS_METHOD_NONE &&
1542-
'range' in request_headers &&
1543-
!request_method_head
1544-
) {
1550+
if (file_compression === COMPRESS_METHOD_NONE) {
15451551
response.setHeader('Accept-Ranges', 'bytes');
1546-
const range_header = request_headers['range'];
1547-
// Only single range requests supported (not multipart ranges)
1548-
const range_match = range_header.match(/^bytes=(\d*)-(\d*)$/);
1549-
1550-
if (range_match) {
1551-
const start = range_match[1];
1552-
const end = range_match[2];
1553-
1554-
if (start || end) {
1555-
is_range_request = true;
1556-
1557-
if (start && end) {
1558-
// Both start and end specified: bytes=10-20
1559-
range_start = parseInt(start, 10);
1560-
range_end = parseInt(end, 10);
1561-
} else if (start) {
1562-
// Only start specified: bytes=10-
1563-
range_start = parseInt(start, 10);
1564-
range_end = file_stat.size - 1;
1565-
} else {
1566-
// Only end specified (suffix-byte-range): bytes=-500
1567-
const suffix_length = parseInt(end, 10);
1568-
range_start = Math.max(0, file_stat.size - suffix_length);
1569-
range_end = file_stat.size - 1;
1570-
}
1571-
1572-
// Validate range
1573-
if (
1574-
range_end >= file_stat.size ||
1575-
range_start > range_end
1576-
) {
1552+
if (
1553+
!request_method_head &&
1554+
'range' in request_headers
1555+
) {
1556+
const range_match = request_headers['range'].match(/^bytes=(\d*)-(\d*)$/);
1557+
if (range_match) {
1558+
const start = range_match[1];
1559+
const end = range_match[2];
1560+
if (start || end) {
1561+
is_range_request = true;
1562+
1563+
if (start && end) {
1564+
range_start = parseInt(start);
1565+
range_end = parseInt(end);
1566+
}
1567+
else if (start) {
1568+
range_start = parseInt(start);
1569+
range_end = file_stat.size - 1;
1570+
}
1571+
else {
1572+
const suffix_length = parseInt(end);
1573+
range_start = Math.max(0, file_stat.size - suffix_length);
1574+
range_end = file_stat.size - 1;
1575+
}
1576+
1577+
if (
1578+
range_start > range_end ||
1579+
range_end >= file_stat.size
1580+
) {
1581+
response.setHeader(
1582+
'Content-Range',
1583+
`bytes */${file_stat.size}`
1584+
);
1585+
throw 416;
1586+
}
1587+
1588+
response.statusCode = 206;
1589+
response.setHeader('Content-Length', range_end - range_start + 1);
15771590
response.setHeader(
15781591
'Content-Range',
1579-
`bytes */${file_stat.size}`
1592+
`bytes ${range_start}-${range_end}/${file_stat.size}`
15801593
);
1581-
throw 416;
15821594
}
1583-
1584-
response.statusCode = 206;
1585-
response.setHeader(
1586-
'Content-Range',
1587-
`bytes ${range_start}-${range_end}/${file_stat.size}`
1588-
);
1589-
response.setHeader('Content-Length', range_end - range_start + 1);
15901595
}
15911596
}
15921597
}
15931598

15941599
if (!is_range_request) {
15951600
if (file_compression === COMPRESS_METHOD_NONE) {
1596-
response.setHeader('Accept-Ranges', 'bytes');
15971601
response.setHeader('Content-Length', file_stat.size);
15981602
}
15991603
else {

0 commit comments

Comments
 (0)