Skip to content

Commit

Permalink
live proxy improvements:
Browse files Browse the repository at this point in the history
- add custom error page for live proxy errors for >400 (except 404) status responses
- add option to send messages when proxy POST request fail, or when rate limited, if messageOnProxyErrors is set
  • Loading branch information
ikreymer committed Oct 11, 2024
1 parent f19ee5a commit 95861e6
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 8 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@webrecorder/wabac",
"version": "2.20.0-beta.2",
"version": "2.20.0-beta.3",
"main": "index.js",
"type": "module",
"exports": {
Expand Down
75 changes: 68 additions & 7 deletions src/liveproxy.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { getProxyNotFoundResponse } from "./notfound";
import { type ArchiveRequest } from "./request";
import { ArchiveResponse } from "./response";
import { type DBStore } from "./types";

declare let self: ServiceWorkerGlobalScope;

// ===========================================================================
export class LiveProxy implements DBStore {
prefix: string;
Expand All @@ -15,6 +18,8 @@ export class LiveProxy implements DBStore {
hostProxy: Record<string, any>;
hostProxyOnly: boolean;

messageOnProxyErrors: boolean;

constructor(
// [TODO]
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Expand All @@ -36,6 +41,9 @@ export class LiveProxy implements DBStore {
this.cloneResponse = cloneResponse;
this.allowBody = allowBody || this.isLive;

// @ts-expect-error [TODO] - TS4111 - Property 'messageOnProxyErrors' comes from an index signature, so it must be accessed with ['messageOnProxyErrors'].
this.messageOnProxyErrors = extraConfig.messageOnProxyErrors || false;

// @ts-expect-error [TODO] - TS4111 - Property 'hostProxy' comes from an index signature, so it must be accessed with ['hostProxy'].
this.hostProxy = extraConfig.hostProxy;

Expand Down Expand Up @@ -109,14 +117,20 @@ export class LiveProxy implements DBStore {

let body: Uint8Array | null = null;

if (
this.allowBody &&
(request.method === "POST" || request.method === "PUT")
) {
body = await request.getBody();
const isPOST =
request.method === "POST" ||
request.method === "PUT" ||
request.method === "DELETE";

if (isPOST) {
if (this.allowBody) {
body = await request.getBody();
} else {
void this.sendProxyError("post-request-attempt", url, request.method);
}
}

const response = await fetch(fetchUrl, {
let response = await fetch(fetchUrl, {
method: request.method,
body,
headers,
Expand All @@ -125,6 +139,33 @@ export class LiveProxy implements DBStore {
redirect: "follow",
});

let noRW = false;

if (isPOST && response.status >= 400) {
void this.sendProxyError(
"post-request-failed",
url,
request.method,
response.status,
);
} else if (response.status === 429) {
void this.sendProxyError(
"rate-limited",
url,
request.method,
response.status,
);
}

if (
response.status > 400 &&
response.status !== 404 &&
["", "document", "iframe"].includes(request.destination)
) {
response = getProxyNotFoundResponse(url, response.status);
noRW = true;
}

let clonedResponse: Response | null = null;

if (this.cloneResponse) {
Expand All @@ -135,7 +176,7 @@ export class LiveProxy implements DBStore {
url,
response,
date: new Date(),
noRW: false,
noRW,
isLive: this.isLive,
archivePrefix: this.archivePrefix,
});
Expand All @@ -146,4 +187,24 @@ export class LiveProxy implements DBStore {

return archiveResponse;
}

async sendProxyError(
type: string,
url: string,
method: string,
status?: number,
) {
if (!this.messageOnProxyErrors) {
return;
}

const clients = await self.clients.matchAll({ type: "window" });
for (const client of clients) {
const clientUrl = new URL(client.url);
if (clientUrl.searchParams.get("source") === this.prefix) {
client.postMessage({ type, url, method, status });
break;
}
}
}
}
47 changes: 47 additions & 0 deletions src/notfound.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ export function notFoundByTypeResponse(
contentType = "text/html; charset=utf-8";
}

return textToResponse(content, contentType, status);
}

function textToResponse(content: string, contentType: string, status = 200) {
const buff = new TextEncoder().encode(content);

const initOpt = {
Expand Down Expand Up @@ -134,3 +138,46 @@ function getScriptCSSNotFound(
function getJSONNotFound(URL: string, TS: string, error = "not_found") {
return JSON.stringify({ error, URL, TS });
}

export function getProxyNotFoundResponse(url: string, status: number) {
return textToResponse(getHTMLNotProxyError(url, status), "text/html", status);
}

function getHTMLNotProxyError(requestURL: string, status: number) {
return `
<!doctype html>
<html>
<head>
<script>
window.requestURL = "${requestURL}";
</script>
</head>
<body style="font-family: sans-serif">
<h2>Live page could not be loaded</h2>
<p>Sorry, this page was could not be loaded through the archiving proxy. Check the URL and try again.</p>
<p><code id="url" style="word-break: break-all; font-size: larger">Status Code: ${status}</code></p>
<p id="goback" style="display: none"><a href="#" onclick="window.history.back()">Go Back</a> to the previous page.</a></p>
<script>
let isTop = true;
try {
if (window.parent._WB_wombat_location) {
isTop = false;
}
} catch (e) {
}
if (isTop) {
document.querySelector("#goback").style.display = "";
window.parent.postMessage({
wb_type: "live-proxy-url-error",
url: window.requestURL,
status: ${status},
}, "*");
}
</script>
</body>
</html>
`;
}

0 comments on commit 95861e6

Please sign in to comment.