mirror of
https://github.com/vrtmrz/obsidian-livesync.git
synced 2026-07-23 04:52:58 +00:00
Validate custom HTTP request bodies
This commit is contained in:
@@ -26,12 +26,16 @@ function requestTimeout(timeoutInMs: number = 0): Promise<never> {
|
||||
}
|
||||
|
||||
function normaliseRequestBody(body: unknown): string | ArrayBuffer | undefined {
|
||||
if (body === undefined) return undefined;
|
||||
if (typeof body === "string" || body instanceof ArrayBuffer) return body;
|
||||
if (ArrayBuffer.isView(body)) {
|
||||
if (body.buffer instanceof ArrayBuffer) return body.buffer;
|
||||
return new Uint8Array(body.buffer).slice().buffer;
|
||||
if (body.buffer instanceof ArrayBuffer && body.byteOffset === 0 && body.byteLength === body.buffer.byteLength) {
|
||||
return body.buffer;
|
||||
}
|
||||
return new Uint8Array(body.buffer, body.byteOffset, body.byteLength).slice().buffer;
|
||||
}
|
||||
return undefined;
|
||||
const bodyType = Object.prototype.toString.call(body).slice(8, -1);
|
||||
throw new TypeError(`Obsidian requestUrl does not support the request body type ${bodyType}`);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
import { HttpRequest } from "@smithy/protocol-http";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
const requestUrlMock = vi.hoisted(() =>
|
||||
vi.fn<
|
||||
(param: { body?: string | ArrayBuffer }) => Promise<{
|
||||
headers: Record<string, string>;
|
||||
status: number;
|
||||
arrayBuffer: ArrayBuffer;
|
||||
}>
|
||||
>()
|
||||
);
|
||||
|
||||
vi.mock("@/deps.ts", () => ({
|
||||
requestUrl: requestUrlMock,
|
||||
}));
|
||||
|
||||
import { ObsHttpHandler } from "./ObsHttpHandler.ts";
|
||||
|
||||
function requestWithBody(body: unknown) {
|
||||
return new HttpRequest({
|
||||
protocol: "https:",
|
||||
hostname: "objects.example.com",
|
||||
method: "PUT",
|
||||
path: "/bucket/object",
|
||||
headers: {},
|
||||
body,
|
||||
});
|
||||
}
|
||||
|
||||
describe("ObsHttpHandler request bodies", () => {
|
||||
beforeEach(() => {
|
||||
requestUrlMock.mockReset();
|
||||
requestUrlMock.mockResolvedValue({
|
||||
headers: {},
|
||||
status: 200,
|
||||
arrayBuffer: new ArrayBuffer(0),
|
||||
});
|
||||
});
|
||||
|
||||
it("sends only the bytes addressed by an ArrayBuffer view", async () => {
|
||||
const body = new Uint8Array([0, 1, 2, 3]).subarray(1, 3);
|
||||
|
||||
await new ObsHttpHandler().handle(requestWithBody(body));
|
||||
|
||||
expect(requestUrlMock).toHaveBeenCalledOnce();
|
||||
const transmittedBody = requestUrlMock.mock.calls[0][0].body;
|
||||
expect(transmittedBody).toBeInstanceOf(ArrayBuffer);
|
||||
expect([...new Uint8Array(transmittedBody as ArrayBuffer)]).toEqual([1, 2]);
|
||||
});
|
||||
|
||||
it("rejects an unsupported body instead of dispatching an empty request", async () => {
|
||||
const body = new ReadableStream<Uint8Array>();
|
||||
|
||||
await expect(new ObsHttpHandler().handle(requestWithBody(body))).rejects.toThrow(
|
||||
"Obsidian requestUrl does not support the request body type ReadableStream"
|
||||
);
|
||||
expect(requestUrlMock).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user