mirror of
https://github.com/titaniumnetwork-dev/Ultraviolet.git
synced 2025-05-15 20:40:01 -04:00
206 lines
No EOL
6.8 KiB
JavaScript
206 lines
No EOL
6.8 KiB
JavaScript
importScripts('/op.bundle.js');
|
|
|
|
const csp = [
|
|
'cross-origin-embedder-policy',
|
|
'cross-origin-opener-policy',
|
|
'cross-origin-resource-policy',
|
|
'content-security-policy',
|
|
'content-security-policy-report-only',
|
|
'expect-ct',
|
|
'feature-policy',
|
|
'origin-isolation',
|
|
'strict-transport-security',
|
|
'upgrade-insecure-requests',
|
|
'x-content-type-options',
|
|
'x-download-options',
|
|
'x-frame-options',
|
|
'x-permitted-cross-domain-policies',
|
|
'x-powered-by',
|
|
'x-xss-protection',
|
|
];
|
|
|
|
const emptyBody = ['204'];
|
|
|
|
async function handle(request) {
|
|
try {
|
|
const parsed = new URL(request.url);
|
|
|
|
if (parsed.pathname === '/op.bundle.js' || parsed.pathname === '/favicon.ico' || parsed.pathname === '/op.handler.js') return fetch(request);
|
|
|
|
const rewrite = new Rewriter({
|
|
meta: {
|
|
origin: location.origin,
|
|
},
|
|
prefix: '/service/',
|
|
});
|
|
|
|
const db = await rewrite.cookie.db();
|
|
|
|
rewrite.html.on('element', (element, type) => {
|
|
if (type !== 'rewrite') return false;
|
|
if (element.tagName !== 'head') return false;
|
|
|
|
element.childNodes.unshift(
|
|
{
|
|
tagName: 'script',
|
|
nodeName: 'script',
|
|
childNodes: [],
|
|
attrs: [
|
|
{ name: 'src', value: '/op.handler.js', skip: true }
|
|
],
|
|
}
|
|
);
|
|
|
|
element.childNodes.unshift(
|
|
{
|
|
tagName: 'script',
|
|
nodeName: 'script',
|
|
childNodes: [],
|
|
attrs: [
|
|
{ name: 'src', value: '/op.bundle.js', skip: true }
|
|
],
|
|
}
|
|
);
|
|
});
|
|
|
|
rewrite.addRewrites();
|
|
|
|
if (!request.url.startsWith(location.origin) || request.url.startsWith(location.origin + rewrite.prefix)) {
|
|
let blob = false;
|
|
let requestUrl = '/fetch/asdsaadsad';
|
|
|
|
rewrite.meta.base = rewrite.meta.url = !request.url.startsWith(location.origin) ? new URL(request.url) : new URL(rewrite.sourceUrl(request.url));
|
|
|
|
if (rewrite.meta.url.protocol === 'blob:') {
|
|
blob = true;
|
|
rewrite.meta.base = rewrite.meta.url = new URL(rewrite.meta.url.pathname);
|
|
requestUrl = 'blob:' + location.origin + rewrite.meta.url.pathname;
|
|
};
|
|
|
|
const requestHeaders = request.headers instanceof Headers ? Object.fromEntries([...request.headers.entries()]) : request.headers;
|
|
let cookieStr = '';
|
|
|
|
if (request.referrer && request.referrer.startsWith(location.origin)) {
|
|
const referer = new URL(rewrite.sourceUrl(request.referrer));
|
|
|
|
if (rewrite.meta.url.origin !== referer.origin && request.mode === 'cors') {
|
|
request.headers.origin = referer.origin;
|
|
};
|
|
|
|
request.headers.referer = referer.href;
|
|
};
|
|
|
|
cookieStr = await rewrite.cookie.getCookies(await db.getAll('cookies'), rewrite.meta);
|
|
|
|
requestHeaders.cookie = cookieStr;
|
|
|
|
const headers = {
|
|
'x-tomp-protocol': rewrite.meta.url.protocol,
|
|
'x-tomp-host': rewrite.meta.url.hostname,
|
|
'x-tomp-path': rewrite.meta.url.pathname + rewrite.meta.url.search,
|
|
'x-tomp-port': rewrite.meta.url.port,
|
|
'x-tomp-headers': JSON.stringify(requestHeaders),
|
|
'x-tomp-forward-headers': JSON.stringify(['user-agent', 'accept', 'accept-encoding', 'accept', 'connection']),
|
|
};
|
|
|
|
const options = {
|
|
method: request.method,
|
|
headers: !blob ? headers : request.headers,
|
|
redirect: request.redirect,
|
|
mode: request.mode === 'cors' ? request.mode : 'same-origin',
|
|
};
|
|
|
|
if (!['GET', 'HEAD'].includes(request.method.toUpperCase())) options.body = await request.blob();
|
|
|
|
const newRequest = new Request(requestUrl, options);
|
|
|
|
const processed = fetch(newRequest).then(async response => {
|
|
let body = response.body;
|
|
|
|
const resHeaders = new Headers(response.headers);
|
|
|
|
const rawHeaders = response.headers.has('x-tomp-headers') ? JSON.parse(response.headers.get('x-tomp-headers')) : Object.fromEntries([...response.headers.entries()]);
|
|
const status = response.headers.get('x-tomp-status') || response.status;
|
|
const statusText = response.headers.get('x-tomp-status-text') || response.statusText;
|
|
|
|
for (let header in rawHeaders) {
|
|
if (csp.indexOf(header) > -1) delete rawHeaders[header];
|
|
};
|
|
|
|
if (rawHeaders.location) {
|
|
rawHeaders.location = rewrite.rewriteUrl(rawHeaders.location);
|
|
};
|
|
|
|
if (rawHeaders['set-cookie']) {
|
|
Promise.resolve(rewrite.cookie.setCookies(rawHeaders['set-cookie'], db, rewrite.meta)).then(() => {
|
|
self.clients.matchAll().then(function (clients){
|
|
clients.forEach(function(client){
|
|
client.postMessage({
|
|
msg: 'updateCookies',
|
|
url: rewrite.meta.url.href,
|
|
});
|
|
});
|
|
});
|
|
});
|
|
delete rawHeaders['set-cookie'];
|
|
};
|
|
|
|
if (isHtml(rewrite.meta.url, (resHeaders.get('content-type') || ''))) {
|
|
body = rewrite.rewriteHtml(
|
|
await response.text(),
|
|
{
|
|
document: true
|
|
}
|
|
);
|
|
};
|
|
|
|
if (request.destination === 'script') {
|
|
body = rewrite.js.rewrite(
|
|
await response.text()
|
|
);
|
|
};
|
|
|
|
if (request.destination === 'worker') {
|
|
body = `if (!self.__op) importScripts('/op.bundle.js', '/op.handler.js');\n`;
|
|
body += rewrite.js.rewrite(
|
|
await response.text()
|
|
);
|
|
};
|
|
|
|
if (request.destination === 'style') {
|
|
body = rewrite.rewriteCSS(
|
|
await response.text()
|
|
);
|
|
};
|
|
|
|
if (emptyBody.includes(status)) {
|
|
return new Response(null, {
|
|
headers: rawHeaders,
|
|
status,
|
|
statusText,
|
|
});
|
|
};
|
|
|
|
return new Response(body, {
|
|
headers: rawHeaders,
|
|
status,
|
|
statusText,
|
|
});
|
|
});
|
|
|
|
return processed;
|
|
|
|
};
|
|
} catch(e) {
|
|
return new Response(e.toString());
|
|
};
|
|
}
|
|
|
|
self.addEventListener('fetch', event => {
|
|
if (event.request.url) event.respondWith(handle(event.request));
|
|
});
|
|
|
|
|
|
function isHtml(url, contentType = '') {
|
|
return (Rewriter.mime.contentType((contentType || url.pathname)) || 'text/html').split(';')[0] === 'text/html';
|
|
}; |