From 441d1cb617dbef70c6801a80ed492c4894b69e5e Mon Sep 17 00:00:00 2001 From: Jorrin Date: Tue, 9 Jan 2024 23:35:56 +0100 Subject: [PATCH] add fetcher logic to makeRequest --- src/background/messages/makeRequest.ts | 18 +++++++++++------- src/utils/fetcher.ts | 24 ++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 7 deletions(-) create mode 100644 src/utils/fetcher.ts diff --git a/src/background/messages/makeRequest.ts b/src/background/messages/makeRequest.ts index fd53e79..cbfeed9 100644 --- a/src/background/messages/makeRequest.ts +++ b/src/background/messages/makeRequest.ts @@ -2,12 +2,16 @@ import type { PlasmoMessaging } from '@plasmohq/messaging'; import type { BaseRequest } from '~types/request'; import type { BaseResponse } from '~types/response'; +import { makeFullUrl } from '~utils/fetcher'; import { validateDomainWhiteList } from '~utils/storage'; -interface Request extends BaseRequest { - url: string; - method: string; +export interface Request extends BaseRequest { + baseUrl?: string; headers?: Record; + method?: string; + query?: Record; + readHeaders?: Record; + url: string; body?: string | FormData | URLSearchParams; } @@ -15,27 +19,27 @@ type Response = BaseResponse<{ status: number; requestHeaders: Record; responseHeaders: Record; - data: string | Record; + body: string | Record; }>; const handler: PlasmoMessaging.MessageHandler = async (req, res) => { try { await validateDomainWhiteList(req.body.requestDomain); - const response = await fetch(req.body.url, { + const response = await fetch(makeFullUrl(req.body.url, req.body), { method: req.body.method, headers: req.body.headers, body: req.body.body, }); const contentType = response.headers.get('content-type'); - const data = contentType?.includes('application/json') ? await response.json() : await response.text(); + const body = contentType?.includes('application/json') ? await response.json() : await response.text(); res.send({ success: true, status: response.status, requestHeaders: req.body.headers, responseHeaders: Object.fromEntries(response.headers.entries()), - data, + body, }); } catch (err) { res.send({ diff --git a/src/utils/fetcher.ts b/src/utils/fetcher.ts new file mode 100644 index 0000000..e4be9d6 --- /dev/null +++ b/src/utils/fetcher.ts @@ -0,0 +1,24 @@ +import { type Request as MakeRequest } from '~background/messages/makeRequest'; + +export function makeFullUrl(url: string, ops?: MakeRequest): string { + // glue baseUrl and rest of url together + let leftSide = ops?.baseUrl ?? ''; + let rightSide = url; + + // left side should always end with slash, if its set + if (leftSide.length > 0 && !leftSide.endsWith('/')) leftSide += '/'; + + // right side should never start with slash + if (rightSide.startsWith('/')) rightSide = rightSide.slice(1); + + const fullUrl = leftSide + rightSide; + if (!fullUrl.startsWith('http://') && !fullUrl.startsWith('https://')) + throw new Error(`Invald URL -- URL doesn't start with a http scheme: '${fullUrl}'`); + + const parsedUrl = new URL(fullUrl); + Object.entries(ops?.query ?? {}).forEach(([k, v]) => { + parsedUrl.searchParams.set(k, v); + }); + + return parsedUrl.toString(); +}