Skip to content

Commit 7bf03fc

Browse files
authored
fix(node-http-handler): fix type error sending Uint8Array as payload (#1561)
1 parent 40f52db commit 7bf03fc

File tree

2 files changed

+157
-3
lines changed

2 files changed

+157
-3
lines changed

packages/node-http-handler/src/node-http-handler.spec.ts

Lines changed: 155 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,13 @@ import https from "https";
77
import { AddressInfo } from "net";
88

99
import { NodeHttpHandler } from "./node-http-handler";
10-
import { createMockHttpServer, createMockHttpsServer, createResponseFunction } from "./server.mock";
10+
import { ReadFromBuffers } from "./readable.mock";
11+
import {
12+
createContinueResponseFunction,
13+
createMockHttpServer,
14+
createMockHttpsServer,
15+
createResponseFunction,
16+
} from "./server.mock";
1117

1218
describe("NodeHttpHandler", () => {
1319
describe("constructor", () => {
@@ -35,10 +41,12 @@ describe("NodeHttpHandler", () => {
3541
afterAll(() => {
3642
mockHttpServer.close();
3743
});
44+
3845
it("has metadata", () => {
3946
const nodeHttpHandler = new NodeHttpHandler();
4047
expect(nodeHttpHandler.metadata.handlerProtocol).toContain("http/1.1");
4148
});
49+
4250
it("can send http requests", async () => {
4351
const mockResponse = {
4452
statusCode: 200,
@@ -65,6 +73,152 @@ describe("NodeHttpHandler", () => {
6573
expect(response.headers).toMatchObject(mockResponse.headers);
6674
expect(response.body).toBeDefined();
6775
});
76+
77+
it("can send requests with bodies", async () => {
78+
const body = Buffer.from("test");
79+
const mockResponse = {
80+
statusCode: 200,
81+
headers: {},
82+
};
83+
mockHttpServer.addListener("request", createResponseFunction(mockResponse));
84+
const spy = jest.spyOn(http, "request").mockImplementationOnce(() => {
85+
const calls = spy.mock.calls;
86+
const currentIndex = calls.length - 1;
87+
return http.request(calls[currentIndex][0], calls[currentIndex][1]);
88+
});
89+
90+
const nodeHttpHandler = new NodeHttpHandler();
91+
const { response } = await nodeHttpHandler.handle(
92+
new HttpRequest({
93+
hostname: "localhost",
94+
method: "PUT",
95+
port: (mockHttpServer.address() as AddressInfo).port,
96+
protocol: "http:",
97+
path: "/",
98+
headers: {},
99+
body,
100+
}),
101+
{}
102+
);
103+
104+
expect(response.statusCode).toEqual(mockResponse.statusCode);
105+
expect(response.headers).toBeDefined();
106+
expect(response.headers).toMatchObject(mockResponse.headers);
107+
});
108+
109+
it("can handle expect 100-continue", async () => {
110+
const body = Buffer.from("test");
111+
const mockResponse = {
112+
statusCode: 200,
113+
headers: {},
114+
};
115+
116+
mockHttpServer.addListener("checkContinue", createContinueResponseFunction(mockResponse));
117+
let endSpy: jest.SpyInstance<any>;
118+
let continueWasTriggered = false;
119+
const spy = jest.spyOn(http, "request").mockImplementationOnce(() => {
120+
const calls = spy.mock.calls;
121+
const currentIndex = calls.length - 1;
122+
const request = http.request(calls[currentIndex][0], calls[currentIndex][1]);
123+
request.on("continue", () => {
124+
continueWasTriggered = true;
125+
});
126+
endSpy = jest.spyOn(request, "end");
127+
128+
return request;
129+
});
130+
131+
const nodeHttpHandler = new NodeHttpHandler();
132+
const { response } = await nodeHttpHandler.handle(
133+
new HttpRequest({
134+
hostname: "localhost",
135+
method: "PUT",
136+
port: (mockHttpServer.address() as AddressInfo).port,
137+
protocol: "http:",
138+
path: "/",
139+
headers: {
140+
Expect: "100-continue",
141+
},
142+
body,
143+
}),
144+
{}
145+
);
146+
147+
expect(response.statusCode).toEqual(mockResponse.statusCode);
148+
expect(response.headers).toBeDefined();
149+
expect(response.headers).toMatchObject(mockResponse.headers);
150+
expect(endSpy!.mock.calls.length).toBe(1);
151+
expect(endSpy!.mock.calls[0][0]).toStrictEqual(body);
152+
expect(continueWasTriggered).toBe(true);
153+
});
154+
155+
it("can send requests with streaming bodies", async () => {
156+
const body = new ReadFromBuffers({
157+
buffers: [Buffer.from("t"), Buffer.from("e"), Buffer.from("s"), Buffer.from("t")],
158+
});
159+
const inputBodySpy = jest.spyOn(body, "pipe");
160+
const mockResponse = {
161+
statusCode: 200,
162+
headers: {},
163+
};
164+
mockHttpServer.addListener("request", createResponseFunction(mockResponse));
165+
const nodeHttpHandler = new NodeHttpHandler();
166+
167+
const { response } = await nodeHttpHandler.handle(
168+
new HttpRequest({
169+
hostname: "localhost",
170+
method: "PUT",
171+
port: (mockHttpServer.address() as AddressInfo).port,
172+
protocol: "http:",
173+
path: "/",
174+
headers: {},
175+
body,
176+
}),
177+
{}
178+
);
179+
180+
expect(response.statusCode).toEqual(mockResponse.statusCode);
181+
expect(response.headers).toBeDefined();
182+
expect(response.headers).toMatchObject(mockResponse.headers);
183+
expect(inputBodySpy.mock.calls.length).toBeTruthy();
184+
});
185+
186+
it("can send requests with Uint8Array bodies", async () => {
187+
const body = Buffer.from([0, 1, 2, 3]);
188+
const mockResponse = {
189+
statusCode: 200,
190+
headers: {},
191+
};
192+
mockHttpServer.addListener("request", createResponseFunction(mockResponse));
193+
let endSpy: jest.SpyInstance<any>;
194+
const spy = jest.spyOn(http, "request").mockImplementationOnce(() => {
195+
const calls = spy.mock.calls;
196+
const currentIndex = calls.length - 1;
197+
const request = http.request(calls[currentIndex][0], calls[currentIndex][1]);
198+
endSpy = jest.spyOn(request, "end");
199+
return request;
200+
});
201+
202+
const nodeHttpHandler = new NodeHttpHandler();
203+
const { response } = await nodeHttpHandler.handle(
204+
new HttpRequest({
205+
hostname: "localhost",
206+
method: "PUT",
207+
port: (mockHttpServer.address() as AddressInfo).port,
208+
protocol: "http:",
209+
path: "/",
210+
headers: {},
211+
body,
212+
}),
213+
{}
214+
);
215+
216+
expect(response.statusCode).toEqual(mockResponse.statusCode);
217+
expect(response.headers).toBeDefined();
218+
expect(response.headers).toMatchObject(mockResponse.headers);
219+
expect(endSpy!.mock.calls.length).toBe(1);
220+
expect(endSpy!.mock.calls[0][0]).toStrictEqual(body);
221+
});
68222
});
69223

70224
describe("https", () => {

packages/node-http-handler/src/write-request-body.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,13 @@ export function writeRequestBody(httpRequest: ClientRequest | ClientHttp2Stream,
1616

1717
function writeBody(
1818
httpRequest: ClientRequest | ClientHttp2Stream,
19-
body?: string | ArrayBuffer | ArrayBufferView | Readable
19+
body?: string | ArrayBuffer | ArrayBufferView | Readable | Uint8Array
2020
) {
2121
if (body instanceof Readable) {
2222
// pipe automatically handles end
2323
body.pipe(httpRequest);
2424
} else if (body) {
25-
httpRequest.end(body);
25+
httpRequest.end(Buffer.from(body));
2626
} else {
2727
httpRequest.end();
2828
}

0 commit comments

Comments
 (0)