mirror of
https://github.com/vrtmrz/obsidian-livesync.git
synced 2026-07-23 13:02: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 {
|
function normaliseRequestBody(body: unknown): string | ArrayBuffer | undefined {
|
||||||
|
if (body === undefined) return undefined;
|
||||||
if (typeof body === "string" || body instanceof ArrayBuffer) return body;
|
if (typeof body === "string" || body instanceof ArrayBuffer) return body;
|
||||||
if (ArrayBuffer.isView(body)) {
|
if (ArrayBuffer.isView(body)) {
|
||||||
if (body.buffer instanceof ArrayBuffer) return body.buffer;
|
if (body.buffer instanceof ArrayBuffer && body.byteOffset === 0 && body.byteLength === body.buffer.byteLength) {
|
||||||
return new Uint8Array(body.buffer).slice().buffer;
|
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