Skip to content

Commit 25b7129

Browse files
authored
[FSSDK-12759] fix content-length header in NodeRequestHandler (#1156)
prevously, body.length was being used for content-length header, which is incorrect (The length data property of a String value contains the length of the string in UTF-16 code units, we need the byte length of utf-8 endcoded string). This PR fixes it.
1 parent 80e4c84 commit 25b7129

2 files changed

Lines changed: 76 additions & 5 deletions

File tree

lib/utils/http_request_handler/request_handler.node.spec.ts

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
import { describe, beforeEach, afterEach, beforeAll, afterAll, it, vi, expect } from 'vitest';
1818

19+
import http from 'http';
1920
import nock from 'nock';
2021
import zlib from 'zlib';
2122
import { NodeRequestHandler } from './request_handler.node';
@@ -202,6 +203,79 @@ describe('NodeRequestHandler', () => {
202203
scope.done();
203204
});
204205

206+
describe('multi-byte unicode data', () => {
207+
let server: http.Server;
208+
let port: number;
209+
let receivedBody: string;
210+
211+
beforeAll(async () => {
212+
nock.enableNetConnect('localhost');
213+
server = http.createServer((req, res) => {
214+
const chunks: Buffer[] = [];
215+
req.on('data', (chunk: Buffer) => chunks.push(chunk));
216+
req.on('end', () => {
217+
receivedBody = Buffer.concat(chunks).toString('utf8');
218+
res.writeHead(200, { 'content-type': 'application/json' });
219+
res.end(JSON.stringify({ ok: true }));
220+
});
221+
});
222+
223+
await new Promise<void>((resolve) => {
224+
server.listen(0, () => {
225+
port = (server.address() as { port: number }).port;
226+
resolve();
227+
});
228+
});
229+
});
230+
231+
afterAll(async () => {
232+
await new Promise<void>((resolve) => server.close(() => resolve()));
233+
nock.disableNetConnect();
234+
});
235+
236+
it('should correctly transmit ASCII data', async () => {
237+
const data = '{"key":"value"}';
238+
239+
const { responsePromise } = nodeRequestHandler.makeRequest(
240+
`http://localhost:${port}/test`,
241+
{ 'content-type': 'application/json' },
242+
'POST',
243+
data,
244+
);
245+
await responsePromise;
246+
247+
expect(receivedBody).toBe(data);
248+
});
249+
250+
it('should correctly transmit emoji data', async () => {
251+
const data = JSON.stringify({ message: '🚀 launch' });
252+
253+
const { responsePromise } = nodeRequestHandler.makeRequest(
254+
`http://localhost:${port}/test`,
255+
{ 'content-type': 'application/json' },
256+
'POST',
257+
data,
258+
);
259+
await responsePromise;
260+
261+
expect(receivedBody).toBe(data);
262+
});
263+
264+
it('should correctly transmit CJK character data', async () => {
265+
const data = JSON.stringify({ greeting: '你好世界' });
266+
267+
const { responsePromise } = nodeRequestHandler.makeRequest(
268+
`http://localhost:${port}/test`,
269+
{ 'content-type': 'application/json' },
270+
'POST',
271+
data,
272+
);
273+
await responsePromise;
274+
275+
expect(receivedBody).toBe(data);
276+
});
277+
});
278+
205279
describe('timeout', () => {
206280
beforeEach(() => {
207281
vi.useFakeTimers();

lib/utils/http_request_handler/request_handler.node.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,16 +62,13 @@ export class NodeRequestHandler implements RequestHandler {
6262
headers: {
6363
...headers,
6464
'accept-encoding': 'gzip,deflate',
65-
'content-length': String(data?.length || 0)
65+
'content-length': String(data ? Buffer.byteLength(data) : 0),
6666
},
6767
timeout: this.timeout,
6868
});
6969
const abortableRequest = this.getAbortableRequestFromRequest(request);
7070

71-
if (data) {
72-
request.write(data);
73-
}
74-
request.end();
71+
request.end(data);
7572

7673
return abortableRequest;
7774
}

0 commit comments

Comments
 (0)