Skip to content

Commit 7e0814f

Browse files
committed
feat: support for body
1 parent fdbc842 commit 7e0814f

File tree

9 files changed

+147
-17
lines changed

9 files changed

+147
-17
lines changed

deno.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@typescriptplayground/socket",
3-
"version": "0.1.2",
3+
"version": "0.2.0",
44
"license": "./LICENSE",
55
"exports": {
66
".": "./src/index.ts"

deno.lock

Lines changed: 10 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/http/error/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
export { InvalidBodyTypeError } from './invalid_body_type_error.ts'
12
export { InvalidChunkSizeError } from './invalid_chunk_size_error.ts'
23
export { InvalidResponseError } from './invalid_response_error.ts'
34
export { InvalidStartLineError } from './invalid_start_line_error.ts'
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export class InvalidBodyTypeError extends Error {
2+
constructor() {
3+
super(`Invalid body type`);
4+
}
5+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import { assertEquals } from '@std/assert'
2+
import { bodyToString } from './body_to_string.ts';
3+
4+
Deno.test('Tests "bodyToString"', async (test) => {
5+
await test.step({
6+
name: 'Convert string to string.',
7+
fn() : void {
8+
const testString = 'string';
9+
10+
const result = bodyToString(testString);
11+
12+
assertEquals(
13+
result,
14+
testString
15+
)
16+
}
17+
})
18+
19+
await test.step({
20+
name: 'Convert ArrayBuffer to string.',
21+
async fn() : Promise<void> {
22+
const testString = 'ArrayBuffer';
23+
24+
const buffer = new TextEncoder().encode(testString).buffer;
25+
26+
const result = await bodyToString(buffer);
27+
28+
assertEquals(result, testString);
29+
},
30+
});
31+
32+
await test.step({
33+
name: "Convert Blob to string.",
34+
async fn() : Promise<void> {
35+
const testString = 'Blob';
36+
37+
const blob = new Blob([testString]);
38+
39+
const result = await bodyToString(blob);
40+
41+
assertEquals(result, testString);
42+
},
43+
});
44+
45+
await test.step({
46+
name: 'Convert DataView to string.',
47+
async fn() : Promise<void> {
48+
const testString = 'DataView';
49+
50+
const buffer = new TextEncoder().encode(testString).buffer;
51+
const dataView = new DataView(buffer);
52+
53+
const result = await bodyToString(dataView);
54+
55+
assertEquals(result, testString);
56+
},
57+
});
58+
59+
await test.step({
60+
name: 'Convert ReadableStream to string.',
61+
async fn() : Promise<void> {
62+
const testString = 'ReadableStream';
63+
64+
const textEncoder = new TextEncoder();
65+
const stream = new ReadableStream({
66+
start(controller) : void {
67+
controller.enqueue(textEncoder.encode(testString));
68+
controller.close();
69+
},
70+
});
71+
72+
const result = await bodyToString(stream);
73+
74+
assertEquals(result, testString);
75+
},
76+
});
77+
})

src/http/request/body_to_string.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { InvalidBodyTypeError } from '../error/index.ts';
2+
3+
/**
4+
* This function converts the different input type into a string.
5+
*
6+
* @param body Input body
7+
*
8+
* @throws `InvalidBodyTypeError` if the input is an invalid
9+
* @returns The body as a string.
10+
*/
11+
export function bodyToString(body : string | ArrayBuffer | Blob | DataView | ReadableStream) : string | Promise<string> {
12+
const textDecoder = new TextDecoder()
13+
14+
if (typeof body === "string") {
15+
return body;
16+
}
17+
18+
if (body instanceof Blob) {
19+
return body.text();
20+
}
21+
22+
if (body instanceof ArrayBuffer) {
23+
return textDecoder.decode(body);
24+
}
25+
26+
if (body instanceof DataView) {
27+
return textDecoder.decode(body.buffer);
28+
}
29+
30+
if (body instanceof ReadableStream) {
31+
return new Response(body).text();
32+
}
33+
34+
throw new InvalidBodyTypeError();
35+
}

src/http/request/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { bodyToString } from './body_to_string.ts';

src/socket.ts

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { method } from './method.ts';
22
import { SocketRequestInit } from './socket_request_init.ts';
33
import { SocketOptions } from './socket_options.ts';
44
import { parse } from './http/response/parse.ts';
5+
import { bodyToString } from './http/request/index.ts';
56

67
const textEncoder = new TextEncoder();
78
const textDecoder = new TextDecoder();
@@ -34,27 +35,29 @@ export class Socket {
3435

3536
public async request(
3637
path : string,
37-
init : SocketRequestInit = {
38-
method: method.GET,
39-
headers: {}
40-
}
38+
init? : SocketRequestInit
4139
) : Promise<Response> {
4240
const connection = await this.connect();
4341

4442
const headers = Object.assign({
4543
Connection: 'close',
46-
Host: 'localhost'
47-
}, {...init.headers})
44+
Host: 'localhost',
45+
}, {...init?.headers})
46+
47+
let bodyString = '';
48+
if (init?.body) {
49+
bodyString = await bodyToString(init.body);
50+
headers['Content-Length'] ??= new TextEncoder().encode(bodyString).length.toString();
51+
}
4852

49-
const headerLines = [
50-
`${init.method} ${path} HTTP/1.1`,
53+
const payload = [
54+
`${init?.method ?? method.GET} ${path} HTTP/1.1`,
5155
...Object.entries(headers).map(([key, value]) => `${key}: ${value}`),
5256
'',
53-
''
54-
];
57+
bodyString
58+
].join("\r\n");
5559

56-
const requestPayload = headerLines.join("\r\n");
57-
await connection.write(textEncoder.encode(requestPayload));
60+
await connection.write(textEncoder.encode(payload));
5861

5962
let buffer = new Uint8Array()
6063
for await (const chunk of connection.readable) {

src/socket_request_init.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@ import { Method } from './method.ts';
22

33
export interface SocketRequestInit {
44
method? : Method,
5-
headers : Record<string, string>
5+
headers? : Record<string, string>,
6+
body? : string | ArrayBuffer | Blob | DataView | ReadableStream
67
}

0 commit comments

Comments
 (0)