Skip to content

Commit

Permalink
Fix timeout
Browse files Browse the repository at this point in the history
  • Loading branch information
j3lte committed Nov 21, 2023
1 parent 4489d8b commit a008e75
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 41 deletions.
6 changes: 6 additions & 0 deletions deno.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 5 additions & 2 deletions dev_deps.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
export { assertEquals, assertRejects } from "https://deno.land/[email protected]/assert/mod.ts";
export {
assertEquals,
assertRejects,
assertThrows,
} from "https://deno.land/[email protected]/assert/mod.ts";
export { emptyDir } from "https://deno.land/[email protected]/fs/mod.ts";
export { MockFetch } from "https://deno.land/x/[email protected]/mod.ts";
export { resolvesNext, stub } from "https://deno.land/[email protected]/testing/mock.ts";
export { build } from "https://deno.land/x/[email protected]/mod.ts";
2 changes: 1 addition & 1 deletion scripts/build-npm.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { build, emptyDir } from "../dev_deps.ts";
import { build, emptyDir } from "https://deno.land/x/[email protected]/mod.ts";

const cleanupTypes = async (dir: string) => {
for await (const dirEntry of Deno.readDir(dir)) {
Expand Down
71 changes: 34 additions & 37 deletions src/lib/Pastebin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -359,26 +359,13 @@ export abstract class AbstractPastebin {
method: "GET" | "POST",
params: Record<string, string> | IPasteAPIOptions = {},
): RequestInit {
const abortController = this.requestTimeout > 0 && AbortController
? new AbortController()
: undefined;

if (abortController) {
const _timeoutId = setTimeout(() => {
if (abortController) {
abortController.abort();
}
}, this.requestTimeout);
}

const init: RequestInit = {
headers: new Headers({
"User-Agent": "Pastebin-ts",
"Cache-Control": "no-cache",
}),
method,
cache: "no-cache",
signal: abortController ? abortController.signal : undefined,
};

if (method === "POST") {
Expand All @@ -395,54 +382,64 @@ export abstract class AbstractPastebin {

async #handleResponse(
res: Response,
resolve: (value: string | PromiseLike<string>) => void,
reject: (reason?: unknown) => void,
): Promise<void> {
): Promise<string> {
if (res.status === 404) {
reject(new Error("Not found!"));
return;
return Promise.reject(new Error("Not found!"));
}
if (res.status === 403) {
reject(new Error("Forbidden! Is this paste private?"));
return;
return Promise.reject(new Error("Forbidden! Is this paste private?"));
}
if (!res.ok) {
reject(new Error(`Response not ok: ${res.status} : ${res.statusText}`));
return;
return Promise.reject(new Error(`Response not ok: ${res.status} : ${res.statusText}`));
}
let buffer: ArrayBuffer;
try {
buffer = await res.arrayBuffer();
} catch (error) {
return reject(error);
return Promise.reject(error);
}
// parse Buffer as text
const text = new TextDecoder().decode(buffer);
if (text.includes("Bad API request")) {
reject(new Error("Bad API request"));
return;
return Promise.reject(new Error("Bad API request"));
}
if (text.includes("Post limit")) {
reject(new Error("Post limit reached"));
return;
return Promise.reject(new Error("Post limit reached"));
}
resolve(text);
return text;
}

#abstractRequest(
async #abstractRequest(
method: "GET" | "POST",
path: string,
params?: Record<string, string> | IPasteAPIOptions,
): Promise<string> {
return new Promise<string>((resolve, reject) => {
const options = this.#getRequestOptions(method, params);
const init = this.#getRequestOptions(method, params);
let timeout: number | null = null;

this.fetch(path, options).then((res) => {
this.#handleResponse(res, resolve, reject);
}).catch((err) => {
reject(err);
});
});
if (this.requestTimeout > 0 && AbortController) {
const abortController = new AbortController();
init.signal = abortController.signal;

timeout = setTimeout(() => {
this.#debugger(">>>>> aborting request");
if (abortController) {
abortController.abort();
}
timeout = null;
}, this.requestTimeout);
}

try {
const res = await this.fetch(path, init);
if (timeout !== null) {
clearTimeout(timeout);
}
return this.#handleResponse(res);
} catch (error) {
console.log("error", error);
return Promise.reject(error);
}
}

#getRequest(path: string): Promise<string> {
Expand Down
31 changes: 30 additions & 1 deletion test/Pastebin.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import { assertEquals, assertRejects, MockFetch, resolvesNext, stub } from "../dev_deps.ts";
import {
assertEquals,
assertRejects,
assertThrows,
MockFetch,
resolvesNext,
stub,
} from "../dev_deps.ts";
import { ExpirationTime, IPastebinOptions, Pastebin, PrivacyLevel } from "../mod.ts";

// We're mocking Pastebin with a timeout of 0, so we don't introduce unwanted timeouts
Expand All @@ -20,6 +27,28 @@ Deno.test("Pastebin", async (t) => {
method: "POST",
}).response("12345678901234567890123456789012");

// // Not working yet
// await t.step("getPaste - timeout", async () => {
// class DelayPastebin extends Pastebin {
// requestTimeout = 500;
// }

// mf.intercept("https://pastebin.com/raw.php?i=test2").response("Hello World!").delay(1000);

// assertRejects(
// () => {
// const pastebin = new DelayPastebin(defaultOptions);
// return pastebin.getPaste("https://pastebin.com/test2").then((res) => {
// console.log(res);
// }).catch((err) => {
// console.log(err);
// });
// },
// Error,
// "Request timed out",
// );
// });

await t.step("getPaste - anonymous (with debug)", async () => {
const pastebin = new TestPastebin({
debug: true,
Expand Down

0 comments on commit a008e75

Please sign in to comment.