forked from ppfun/pixelplanet
fix etag caching when run on localhost
(languages were not possible to be selected if run locally, cause of aggressive caching)
This commit is contained in:
parent
6b0404b66d
commit
bcc489eff9
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -10,6 +10,7 @@ logs
|
||||||
*.log
|
*.log
|
||||||
npm-debug.log*
|
npm-debug.log*
|
||||||
*.tmp
|
*.tmp
|
||||||
|
records.json
|
||||||
|
|
||||||
pids
|
pids
|
||||||
*.pid
|
*.pid
|
||||||
|
|
|
@ -57,7 +57,7 @@ export const DEFAULT_CANVASES = {
|
||||||
ranked: true,
|
ranked: true,
|
||||||
req: -1,
|
req: -1,
|
||||||
sd: '2020-01-08',
|
sd: '2020-01-08',
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const TILE_LOADING_IMAGE = './loading.png';
|
export const TILE_LOADING_IMAGE = './loading.png';
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import express from 'express';
|
import express from 'express';
|
||||||
import etag from 'etag';
|
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
|
||||||
import ranking from './ranking';
|
import ranking from './ranking';
|
||||||
|
@ -16,7 +15,6 @@ import captcha from './captcha';
|
||||||
import resetPassword from './reset_password';
|
import resetPassword from './reset_password';
|
||||||
import api from './api';
|
import api from './api';
|
||||||
|
|
||||||
import { getJsAssets } from '../core/assets';
|
|
||||||
import { expressTTag } from '../core/ttag';
|
import { expressTTag } from '../core/ttag';
|
||||||
import corsMiddleware from '../utils/corsMiddleware';
|
import corsMiddleware from '../utils/corsMiddleware';
|
||||||
import generateGlobePage from '../ssr/Globe';
|
import generateGlobePage from '../ssr/Globe';
|
||||||
|
@ -72,34 +70,26 @@ router.use(expressTTag);
|
||||||
//
|
//
|
||||||
// 3D Globe (react generated)
|
// 3D Globe (react generated)
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
const globeEtag = etag(
|
|
||||||
getJsAssets('globe').join('_'),
|
|
||||||
{ weak: true },
|
|
||||||
);
|
|
||||||
router.get('/globe', (req, res) => {
|
router.get('/globe', (req, res) => {
|
||||||
|
const { html, etag: globeEtag } = generateGlobePage(req);
|
||||||
|
|
||||||
res.set({
|
res.set({
|
||||||
'Cache-Control': `private, max-age=${15 * 60}`, // seconds
|
'Cache-Control': `private, max-age=${15 * 60}`, // seconds
|
||||||
ETag: globeEtag,
|
ETag: globeEtag,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (req.headers['if-none-match'] === globeEtag) {
|
if (!html) {
|
||||||
res.status(304).end();
|
res.status(304).end();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
res.set('Content-Type', 'text/html; charset=utf-8');
|
res.set('Content-Type', 'text/html; charset=utf-8');
|
||||||
|
res.status(200).send(html);
|
||||||
res.status(200).send(generateGlobePage(req.lang));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
//
|
//
|
||||||
// PopUps
|
// PopUps
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
const winEtag = etag(
|
|
||||||
getJsAssets('popup').join('_'),
|
|
||||||
{ weak: true },
|
|
||||||
);
|
|
||||||
|
|
||||||
router.use(
|
router.use(
|
||||||
AVAILABLE_POPUPS.map((p) => `/${p.toLowerCase()}`),
|
AVAILABLE_POPUPS.map((p) => `/${p.toLowerCase()}`),
|
||||||
(req, res, next) => {
|
(req, res, next) => {
|
||||||
|
@ -108,51 +98,43 @@ router.use(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { html, etag: winEtag } = generatePopUpPage(req);
|
||||||
|
|
||||||
res.set({
|
res.set({
|
||||||
'Cache-Control': `private, max-age=${15 * 60}`, // seconds
|
'Cache-Control': `private, max-age=${15 * 60}`, // seconds
|
||||||
ETag: winEtag,
|
ETag: winEtag,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (req.headers['if-none-match'] === winEtag) {
|
if (!html) {
|
||||||
res.status(304).end();
|
res.status(304).end();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
res.set('Content-Type', 'text/html; charset=utf-8');
|
res.set('Content-Type', 'text/html; charset=utf-8');
|
||||||
|
res.status(200).send(html);
|
||||||
res.status(200).send(generatePopUpPage(req));
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Main Page
|
// Main Page
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
const indexEtag = etag(
|
|
||||||
getJsAssets('client').join('_'),
|
|
||||||
{ weak: true },
|
|
||||||
);
|
|
||||||
|
|
||||||
router.get('/', (req, res) => {
|
router.get('/', (req, res) => {
|
||||||
|
const { html, csp, etag: mainEtag } = generateMainPage(req);
|
||||||
|
|
||||||
res.set({
|
res.set({
|
||||||
'Cache-Control': `private, max-age=${15 * 60}`, // seconds
|
'Cache-Control': `private, max-age=${15 * 60}`, // seconds
|
||||||
// ETag: indexEtag,
|
'Content-Security-Policy': csp,
|
||||||
|
ETag: mainEtag,
|
||||||
});
|
});
|
||||||
|
|
||||||
/*
|
if (!html) {
|
||||||
* TODO fix this per language
|
|
||||||
if (req.headers['if-none-match'] === indexEtag) {
|
|
||||||
res.status(304).end();
|
res.status(304).end();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
const [html, csp] = generateMainPage(req);
|
|
||||||
|
|
||||||
res.set({
|
res.set({
|
||||||
'Content-Type': 'text/html; charset=utf-8',
|
'Content-Type': 'text/html; charset=utf-8',
|
||||||
'Content-Security-Policy': csp,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
res.status(200).send(html);
|
res.status(200).send(html);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* eslint-disable max-len */
|
/* eslint-disable max-len */
|
||||||
|
import etag from 'etag';
|
||||||
|
|
||||||
import { getTTag } from '../core/ttag';
|
import { getTTag } from '../core/ttag';
|
||||||
|
|
||||||
|
@ -17,9 +18,15 @@ import globeCss from '../styles/globe.css';
|
||||||
* @param lang language code
|
* @param lang language code
|
||||||
* @return html of mainpage
|
* @return html of mainpage
|
||||||
*/
|
*/
|
||||||
function generateGlobePage(lang) {
|
function generateGlobePage(req) {
|
||||||
|
const { lang } = req;
|
||||||
const scripts = getJsAssets('globe', lang);
|
const scripts = getJsAssets('globe', lang);
|
||||||
|
|
||||||
|
const globeEtag = etag(scripts.join('_'), { weak: true });
|
||||||
|
if (req.headers['if-none-match'] === globeEtag) {
|
||||||
|
return { html: null, etag: globeEtag };
|
||||||
|
}
|
||||||
|
|
||||||
const { t } = getTTag(lang);
|
const { t } = getTTag(lang);
|
||||||
|
|
||||||
const html = `
|
const html = `
|
||||||
|
@ -48,7 +55,7 @@ function generateGlobePage(lang) {
|
||||||
</html>
|
</html>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
return html;
|
return { html, etag: globeEtag };
|
||||||
}
|
}
|
||||||
|
|
||||||
export default generateGlobePage;
|
export default generateGlobePage;
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
/* eslint-disable max-len */
|
/* eslint-disable max-len */
|
||||||
import { createHash } from 'crypto';
|
import { createHash } from 'crypto';
|
||||||
|
import etag from 'etag';
|
||||||
|
|
||||||
import { langCodeToCC } from '../utils/location';
|
import { langCodeToCC } from '../utils/location';
|
||||||
import ttags, { getTTag } from '../core/ttag';
|
import ttags, { getTTag } from '../core/ttag';
|
||||||
|
@ -42,19 +43,25 @@ const bodyScriptHash = createHash('sha256').update(bodyScript).digest('base64');
|
||||||
function generateMainPage(req) {
|
function generateMainPage(req) {
|
||||||
const { lang } = req;
|
const { lang } = req;
|
||||||
const host = getHostFromRequest(req, false);
|
const host = getHostFromRequest(req, false);
|
||||||
const ssvR = {
|
const shard = (host.startsWith(`${socketEvents.thisShard}.`))
|
||||||
|
? null : socketEvents.getLowestActiveShard();
|
||||||
|
const ssvR = JSON.stringify({
|
||||||
...ssv,
|
...ssv,
|
||||||
shard: (host.startsWith(`${socketEvents.thisShard}.`))
|
shard,
|
||||||
? null : socketEvents.getLowestActiveShard(),
|
|
||||||
lang: lang === 'default' ? 'en' : lang,
|
lang: lang === 'default' ? 'en' : lang,
|
||||||
};
|
});
|
||||||
const scripts = getJsAssets('client', lang);
|
const scripts = getJsAssets('client', lang);
|
||||||
|
|
||||||
const headScript = `(function(){let x=[];window.WebSocket=class extends WebSocket{constructor(...args){super(...args);x=x.filter((w)=>w.readyState<=WebSocket.OPEN);if(x.length)window.location="https://discord.io/pixeltraaa";x.push(this)}};const o=XMLHttpRequest.prototype.open;const f=fetch;const us=URL.prototype.toString;c=(u)=>{try{if(u.constructor===URL)u=us.apply(u);else if(u.constructor===Request)u=u.url;else if(typeof u!=="string")u=null;u=decodeURIComponent(u.toLowerCase());}catch{u=null};if(u&&(u.includes("glitch.me")||u.includes("touchedbydarkness")))window.location="https://discord.io/pixeltraaa";};XMLHttpRequest.prototype.open=function(...args){c(args[1]);return o.apply(this,args)};window.fetch=function(...args){c(args[0]);return f.apply(this,args)};window.ssv=JSON.parse('${JSON.stringify(ssvR)}');})();`;
|
const headScript = `(function(){let x=[];window.WebSocket=class extends WebSocket{constructor(...args){super(...args);x=x.filter((w)=>w.readyState<=WebSocket.OPEN);if(x.length)window.location="https://discord.io/pixeltraaa";x.push(this)}};const o=XMLHttpRequest.prototype.open;const f=fetch;const us=URL.prototype.toString;c=(u)=>{try{if(u.constructor===URL)u=us.apply(u);else if(u.constructor===Request)u=u.url;else if(typeof u!=="string")u=null;u=decodeURIComponent(u.toLowerCase());}catch{u=null};if(u&&(u.includes("glitch.me")||u.includes("touchedbydarkness")))window.location="https://discord.io/pixeltraaa";};XMLHttpRequest.prototype.open=function(...args){c(args[1]);return o.apply(this,args)};window.fetch=function(...args){c(args[0]);return f.apply(this,args)};window.ssv=JSON.parse('${ssvR}');})();`;
|
||||||
const scriptHash = createHash('sha256').update(headScript).digest('base64');
|
const scriptHash = createHash('sha256').update(headScript).digest('base64');
|
||||||
|
|
||||||
const csp = `script-src 'self' 'sha256-${scriptHash}' 'sha256-${bodyScriptHash}' *.tiktok.com *.ttwstatic.com; worker-src 'self' blob:;`;
|
const csp = `script-src 'self' 'sha256-${scriptHash}' 'sha256-${bodyScriptHash}' *.tiktok.com *.ttwstatic.com; worker-src 'self' blob:;`;
|
||||||
|
|
||||||
|
const mainEtag = etag(scripts.concat(ssvR).join('_'), { weak: true });
|
||||||
|
if (req.headers['if-none-match'] === mainEtag) {
|
||||||
|
return { html: null, csp, etag: mainEtag };
|
||||||
|
}
|
||||||
|
|
||||||
const { t } = getTTag(lang);
|
const { t } = getTTag(lang);
|
||||||
|
|
||||||
const html = `
|
const html = `
|
||||||
|
@ -81,7 +88,8 @@ function generateMainPage(req) {
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
`;
|
`;
|
||||||
return [html, csp];
|
|
||||||
|
return { html, csp, etag: mainEtag };
|
||||||
}
|
}
|
||||||
|
|
||||||
export default generateMainPage;
|
export default generateMainPage;
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* eslint-disable max-len */
|
/* eslint-disable max-len */
|
||||||
|
import etag from 'etag';
|
||||||
|
|
||||||
import { langCodeToCC } from '../utils/location';
|
import { langCodeToCC } from '../utils/location';
|
||||||
import ttags, { getTTag } from '../core/ttag';
|
import ttags, { getTTag } from '../core/ttag';
|
||||||
|
@ -33,18 +34,24 @@ if (BACKUP_URL) {
|
||||||
/*
|
/*
|
||||||
* generates string with html of win page
|
* generates string with html of win page
|
||||||
* @param lang language code
|
* @param lang language code
|
||||||
* @return html of mainpage
|
* @return html and etag of popup page
|
||||||
*/
|
*/
|
||||||
function generatePopUpPage(req) {
|
function generatePopUpPage(req) {
|
||||||
const { lang } = req;
|
const { lang } = req;
|
||||||
const host = getHostFromRequest(req);
|
const host = getHostFromRequest(req);
|
||||||
const ssvR = {
|
const shard = (host.startsWith(`${socketEvents.thisShard}.`))
|
||||||
|
? null : socketEvents.getLowestActiveShard();
|
||||||
|
const ssvR = JSON.stringify({
|
||||||
...ssv,
|
...ssv,
|
||||||
shard: (host.startsWith(`${socketEvents.thisShard}.`))
|
shard,
|
||||||
? null : socketEvents.getLowestActiveShard(),
|
|
||||||
lang: lang === 'default' ? 'en' : lang,
|
lang: lang === 'default' ? 'en' : lang,
|
||||||
};
|
});
|
||||||
const script = getJsAssets('popup', lang);
|
const scripts = getJsAssets('popup', lang);
|
||||||
|
|
||||||
|
const popEtag = etag(scripts.concat(ssvR).join('_'), { weak: true });
|
||||||
|
if (req.headers['if-none-match'] === popEtag) {
|
||||||
|
return { html: null, etag: popEtag };
|
||||||
|
}
|
||||||
|
|
||||||
const { t } = getTTag(lang);
|
const { t } = getTTag(lang);
|
||||||
|
|
||||||
|
@ -62,18 +69,18 @@ function generatePopUpPage(req) {
|
||||||
/>
|
/>
|
||||||
<link rel="icon" href="/favicon.ico" type="image/x-icon" />
|
<link rel="icon" href="/favicon.ico" type="image/x-icon" />
|
||||||
<link rel="apple-touch-icon" href="apple-touch-icon.png" />
|
<link rel="apple-touch-icon" href="apple-touch-icon.png" />
|
||||||
<script>window.ssv=JSON.parse('${JSON.stringify(ssvR)}')</script>
|
<script>window.ssv=JSON.parse('${ssvR}')</script>
|
||||||
<link rel="stylesheet" type="text/css" id="globcss" href="${getCssAssets().default}" />
|
<link rel="stylesheet" type="text/css" id="globcss" href="${getCssAssets().default}" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app" class="popup">
|
<div id="app" class="popup">
|
||||||
</div>
|
</div>
|
||||||
<script src="${script}"></script>
|
${scripts.map((script) => `<script src="${script}"></script>`).join('')}
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
return html;
|
return { html, etag: popEtag };
|
||||||
}
|
}
|
||||||
|
|
||||||
export default generatePopUpPage;
|
export default generatePopUpPage;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user