@nx.js/http 0.0.1 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/body.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ /// <reference types="nxjs-runtime" />
2
+ import { UnshiftableStream } from './unshiftable-readable-stream';
3
+ export declare function bodyStream(unshiftable: UnshiftableStream, headers: Headers): ReadableStream<Uint8Array>;
package/dist/body.js ADDED
@@ -0,0 +1,94 @@
1
+ import { flushBytes, readUntilEol } from './util';
2
+ function bodyWithContentLength(unshiftable, contentLengthVal) {
3
+ let bytesRead = 0;
4
+ const reader = unshiftable.readable.getReader();
5
+ const contentLength = parseInt(contentLengthVal, 10);
6
+ //console.log(`content-length: ${contentLength}`);
7
+ return new ReadableStream({
8
+ async pull(controller) {
9
+ if (bytesRead < contentLength) {
10
+ unshiftable.resume();
11
+ const { done, value } = await reader.read();
12
+ unshiftable.pause();
13
+ if (done) {
14
+ reader.releaseLock();
15
+ controller.close();
16
+ return;
17
+ }
18
+ const remainingLength = contentLength - bytesRead;
19
+ const chunkLength = value.length;
20
+ if (chunkLength <= remainingLength) {
21
+ controller.enqueue(value);
22
+ bytesRead += chunkLength;
23
+ }
24
+ else {
25
+ // If the chunk is larger than needed, slice it to fit and unshift the rest back
26
+ const neededPart = value.slice(0, remainingLength);
27
+ const excessPart = value.slice(remainingLength);
28
+ controller.enqueue(neededPart);
29
+ unshiftable.unshift(excessPart);
30
+ bytesRead += neededPart.length;
31
+ reader.releaseLock();
32
+ controller.close(); // Close the stream as we have read the required content length
33
+ }
34
+ }
35
+ else {
36
+ reader.releaseLock();
37
+ controller.close(); // Close the stream if bytesRead is already equal to contentLength
38
+ }
39
+ },
40
+ cancel() {
41
+ reader.cancel();
42
+ },
43
+ });
44
+ }
45
+ function bodyWithChunkedEncoding(unshiftable) {
46
+ const reader = unshiftable.readable.getReader();
47
+ return new ReadableStream({
48
+ async pull(controller) {
49
+ const numBytesHex = await readUntilEol(reader, unshiftable);
50
+ const numBytes = parseInt(numBytesHex, 16);
51
+ if (Number.isNaN(numBytes)) {
52
+ return controller.error(new Error(`Invalid chunk size: ${numBytesHex}`));
53
+ }
54
+ if (numBytes > 0) {
55
+ await flushBytes(controller, numBytes, reader, unshiftable);
56
+ }
57
+ const empty = await readUntilEol(reader, unshiftable);
58
+ if (empty) {
59
+ return controller.error(new Error(`Expected \\r\\n after data chunk, received: ${empty}`));
60
+ }
61
+ if (numBytes === 0) {
62
+ // This is the final chunk
63
+ reader.releaseLock();
64
+ controller.close();
65
+ }
66
+ },
67
+ cancel(reason) {
68
+ if (reason) {
69
+ reader.cancel(reason);
70
+ }
71
+ else {
72
+ reader.cancel();
73
+ }
74
+ },
75
+ });
76
+ }
77
+ export function bodyStream(unshiftable, headers) {
78
+ const contentLength = headers.get('content-length');
79
+ if (typeof contentLength === 'string') {
80
+ return bodyWithContentLength(unshiftable, contentLength);
81
+ }
82
+ const transferEncoding = headers.get('transfer-encoding')?.split(/\s*,\s*/);
83
+ if (transferEncoding?.includes('chunked')) {
84
+ return bodyWithChunkedEncoding(unshiftable);
85
+ }
86
+ // Identity transfer encoding - read until the end of the stream for the body
87
+ const body = new TransformStream();
88
+ unshiftable.readable.pipeTo(body.writable).finally(() => {
89
+ unshiftable.pause();
90
+ });
91
+ unshiftable.resume();
92
+ return body.readable;
93
+ }
94
+ //# sourceMappingURL=body.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"body.js","sourceRoot":"","sources":["../src/body.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export declare class Deferred<T> {
2
+ promise: Promise<T>;
3
+ resolve: (v: T) => void;
4
+ reject: (v: any) => void;
5
+ constructor();
6
+ }
@@ -0,0 +1,12 @@
1
+ export class Deferred {
2
+ promise;
3
+ resolve;
4
+ reject;
5
+ constructor() {
6
+ this.promise = new Promise((r, j) => {
7
+ this.resolve = r;
8
+ this.reject = j;
9
+ });
10
+ }
11
+ }
12
+ //# sourceMappingURL=deferred.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deferred.js","sourceRoot":"","sources":["../src/deferred.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,QAAQ;IACpB,OAAO,CAAa;IACpB,OAAO,CAAkB;IACzB,MAAM,CAAoB;IAE1B;QACC,IAAI,CAAC,OAAO,GAAG,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YACnC,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC;YACjB,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;QACjB,CAAC,CAAC,CAAC;IACJ,CAAC;CACD"}
@@ -0,0 +1,4 @@
1
+ /// <reference types="nxjs-runtime" />
2
+ import { UnshiftableStream } from './unshiftable-readable-stream';
3
+ export declare function readHeaders(unshiftable: UnshiftableStream): Promise<string[]>;
4
+ export declare function toHeaders(input: string[]): Headers;
@@ -0,0 +1,46 @@
1
+ import { concat, indexOfEol, decoder } from './util';
2
+ export async function readHeaders(unshiftable) {
3
+ let leftover = null;
4
+ const reader = unshiftable.readable.getReader();
5
+ const lines = [];
6
+ while (true) {
7
+ unshiftable.resume();
8
+ const next = await reader.read();
9
+ unshiftable.pause();
10
+ if (next.done)
11
+ return lines;
12
+ const chunk = leftover
13
+ ? concat(leftover, next.value)
14
+ : next.value;
15
+ let pos = 0;
16
+ while (true) {
17
+ const eol = indexOfEol(chunk, pos);
18
+ if (eol === -1) {
19
+ leftover = chunk.slice(pos);
20
+ break;
21
+ }
22
+ const line = decoder.decode(chunk.slice(pos, eol));
23
+ pos = eol + 2;
24
+ if (line) {
25
+ lines.push(line);
26
+ }
27
+ else {
28
+ // end of headers
29
+ unshiftable.unshift(chunk.slice(pos));
30
+ reader.releaseLock();
31
+ return lines;
32
+ }
33
+ }
34
+ }
35
+ }
36
+ export function toHeaders(input) {
37
+ const headers = new Headers();
38
+ for (const line of input) {
39
+ const col = line.indexOf(':');
40
+ const name = line.slice(0, col);
41
+ const value = line.slice(col + 1).trim();
42
+ headers.set(name, value);
43
+ }
44
+ return headers;
45
+ }
46
+ //# sourceMappingURL=headers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"headers.js","sourceRoot":"","sources":["../src/headers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAGrD,MAAM,CAAC,KAAK,UAAU,WAAW,CAChC,WAA8B;IAE9B,IAAI,QAAQ,GAAsB,IAAI,CAAC;IACvC,MAAM,MAAM,GAAG,WAAW,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC;IAChD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,OAAO,IAAI,EAAE,CAAC;QACb,WAAW,CAAC,MAAM,EAAE,CAAC;QACrB,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;QACjC,WAAW,CAAC,KAAK,EAAE,CAAC;QACpB,IAAI,IAAI,CAAC,IAAI;YAAE,OAAO,KAAK,CAAC;QAC5B,MAAM,KAAK,GAAe,QAAQ;YACjC,CAAC,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC;YAC9B,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC;QACd,IAAI,GAAG,GAAG,CAAC,CAAC;QACZ,OAAO,IAAI,EAAE,CAAC;YACb,MAAM,GAAG,GAAG,UAAU,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;YACnC,IAAI,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC;gBAChB,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBAC5B,MAAM;YACP,CAAC;YACD,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;YACnD,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;YACd,IAAI,IAAI,EAAE,CAAC;gBACV,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAClB,CAAC;iBAAM,CAAC;gBACP,iBAAiB;gBACjB,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;gBACtC,MAAM,CAAC,WAAW,EAAE,CAAC;gBACrB,OAAO,KAAK,CAAC;YACd,CAAC;QACF,CAAC;IACF,CAAC;AACF,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,KAAe;IACxC,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IAC9B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QAC1B,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC9B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QAChC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACzC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC1B,CAAC;IACD,OAAO,OAAO,CAAC;AAChB,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  /// <reference types="nxjs-runtime" />
2
+ export { createStaticFileHandler, type StaticFileHandlerOpts } from './static';
2
3
  /**
3
4
  * Handler function for processing an HTTP request.
4
5
  */
@@ -18,29 +19,6 @@ export interface ListenOptions extends Omit<Switch.ListenOptions, 'accept'> {
18
19
  * @param handler The HTTP handler function to invoke when an HTTP request is received
19
20
  */
20
21
  export declare function createServerHandler(handler: ServerHandler): ({ socket }: Switch.SocketEvent) => Promise<void>;
21
- /**
22
- * Creates an HTTP handler function which serves file contents from the filesystem.
23
- *
24
- * @example
25
- *
26
- * ```typescript
27
- * const fileHandler = http.createStaticFileHandler('sdmc:/switch/');
28
- *
29
- * http.listen({
30
- * port: 8080,
31
- * async fetch(req) {
32
- * let res = await fileHandler(req);
33
- * if (!res) {
34
- * res = new Response('File not found', { status: 404 });
35
- * }
36
- * return res;
37
- * }
38
- * });
39
- * ```
40
- *
41
- * @param root Root directory where static files are served from
42
- */
43
- export declare function createStaticFileHandler(root: Switch.PathLike): (req: Request) => Promise<Response | null>;
44
22
  /**
45
23
  * Creates an HTTP server and listens on the `port` number specified in the options object.
46
24
  * The `fetch` function will be invoked upon receiving an HTTP request.
package/dist/index.js CHANGED
@@ -1,116 +1,6 @@
1
- import mime from 'mime';
2
- const decoder = new TextDecoder();
3
- const encoder = new TextEncoder();
4
- function indexOfEol(arr, offset) {
5
- for (let i = offset; i < arr.length - 1; i++) {
6
- if (arr[i] === 13 && arr[i + 1] === 10) {
7
- return i;
8
- }
9
- }
10
- return -1;
11
- }
12
- function concat(a, b) {
13
- const c = new Uint8Array(a.length + b.length);
14
- c.set(a, 0);
15
- c.set(b, a.length);
16
- return c;
17
- }
18
- async function* headersIterator(reader) {
19
- let leftover = null;
20
- while (true) {
21
- const next = await reader.read();
22
- if (next.done)
23
- throw new Error('Stream closed before end of headers');
24
- const chunk = leftover
25
- ? concat(leftover, next.value)
26
- : next.value;
27
- let pos = 0;
28
- while (true) {
29
- const eol = indexOfEol(chunk, pos);
30
- if (eol === -1) {
31
- leftover = chunk.slice(pos);
32
- break;
33
- }
34
- const line = decoder.decode(chunk.slice(pos, eol));
35
- pos = eol + 2;
36
- if (line) {
37
- yield { line };
38
- }
39
- else {
40
- // end of headers
41
- leftover = chunk.slice(pos);
42
- yield { line: null, leftover };
43
- reader.releaseLock();
44
- return;
45
- }
46
- }
47
- }
48
- }
49
- const STATUS_CODES = {
50
- '100': 'Continue',
51
- '101': 'Switching Protocols',
52
- '102': 'Processing',
53
- '103': 'Early Hints',
54
- '200': 'OK',
55
- '201': 'Created',
56
- '202': 'Accepted',
57
- '203': 'Non-Authoritative Information',
58
- '204': 'No Content',
59
- '205': 'Reset Content',
60
- '206': 'Partial Content',
61
- '207': 'Multi-Status',
62
- '208': 'Already Reported',
63
- '226': 'IM Used',
64
- '300': 'Multiple Choices',
65
- '301': 'Moved Permanently',
66
- '302': 'Found',
67
- '303': 'See Other',
68
- '304': 'Not Modified',
69
- '305': 'Use Proxy',
70
- '307': 'Temporary Redirect',
71
- '308': 'Permanent Redirect',
72
- '400': 'Bad Request',
73
- '401': 'Unauthorized',
74
- '402': 'Payment Required',
75
- '403': 'Forbidden',
76
- '404': 'Not Found',
77
- '405': 'Method Not Allowed',
78
- '406': 'Not Acceptable',
79
- '407': 'Proxy Authentication Required',
80
- '408': 'Request Timeout',
81
- '409': 'Conflict',
82
- '410': 'Gone',
83
- '411': 'Length Required',
84
- '412': 'Precondition Failed',
85
- '413': 'Payload Too Large',
86
- '414': 'URI Too Long',
87
- '415': 'Unsupported Media Type',
88
- '416': 'Range Not Satisfiable',
89
- '417': 'Expectation Failed',
90
- '418': "I'm a Teapot",
91
- '421': 'Misdirected Request',
92
- '422': 'Unprocessable Entity',
93
- '423': 'Locked',
94
- '424': 'Failed Dependency',
95
- '425': 'Too Early',
96
- '426': 'Upgrade Required',
97
- '428': 'Precondition Required',
98
- '429': 'Too Many Requests',
99
- '431': 'Request Header Fields Too Large',
100
- '451': 'Unavailable For Legal Reasons',
101
- '500': 'Internal Server Error',
102
- '501': 'Not Implemented',
103
- '502': 'Bad Gateway',
104
- '503': 'Service Unavailable',
105
- '504': 'Gateway Timeout',
106
- '505': 'HTTP Version Not Supported',
107
- '506': 'Variant Also Negotiates',
108
- '507': 'Insufficient Storage',
109
- '508': 'Loop Detected',
110
- '509': 'Bandwidth Limit Exceeded',
111
- '510': 'Not Extended',
112
- '511': 'Network Authentication Required',
113
- };
1
+ import { UnshiftableStream } from './unshiftable-readable-stream';
2
+ import { readRequest, writeResponse } from './server';
3
+ export { createStaticFileHandler } from './static';
114
4
  /**
115
5
  * Creates a socket handler function which accepts a socket
116
6
  * event and parses the incoming data as an HTTP request.
@@ -120,97 +10,18 @@ const STATUS_CODES = {
120
10
  * @param handler The HTTP handler function to invoke when an HTTP request is received
121
11
  */
122
12
  export function createServerHandler(handler) {
123
- return async function ({ socket }) {
124
- const reqHeaders = new Headers();
125
- const r = socket.readable.getReader();
126
- const hi = headersIterator(r);
127
- // Parse request headers
128
- const firstLine = await hi.next();
129
- if (firstLine.done || !firstLine.value.line) {
130
- throw new Error('Failed to read response header');
131
- }
132
- const [method, path, httpVersion] = firstLine.value.line.split(' ');
133
- let leftover;
134
- for await (const v of hi) {
135
- if (typeof v.line === 'string') {
136
- const col = v.line.indexOf(':');
137
- const name = v.line.slice(0, col);
138
- const value = v.line.slice(col + 1).trim();
139
- reqHeaders.set(name, value);
140
- }
141
- else {
142
- leftover = v.leftover;
143
- }
144
- }
145
- const host = reqHeaders.get('host');
146
- const req = new Request(`http://${host}${path}`, {
147
- method,
148
- headers: reqHeaders,
149
- });
150
- const res = await handler(req);
151
- res.headers.set('connection', 'close');
152
- let headersStr = '';
153
- for (const [k, v] of res.headers) {
154
- headersStr += `${k}: ${v}\r\n`;
155
- }
156
- const statusText = res.statusText || STATUS_CODES[res.status];
157
- const resHeader = `${httpVersion} ${res.status} ${statusText}\r\n${headersStr}\r\n`;
158
- const w = socket.writable.getWriter();
159
- w.write(encoder.encode(resHeader));
160
- if (res.body) {
161
- w.releaseLock();
162
- await res.body.pipeTo(socket.writable);
163
- }
164
- else {
165
- await w.close();
13
+ return async ({ socket }) => {
14
+ const unshiftable = new UnshiftableStream(socket.readable);
15
+ while (true) {
16
+ const req = await readRequest(unshiftable);
17
+ if (!req)
18
+ break;
19
+ const res = await handler(req);
20
+ writeResponse(socket.writable, res, 'HTTP/1.1');
166
21
  }
167
22
  socket.close();
168
23
  };
169
24
  }
170
- /**
171
- * Creates an HTTP handler function which serves file contents from the filesystem.
172
- *
173
- * @example
174
- *
175
- * ```typescript
176
- * const fileHandler = http.createStaticFileHandler('sdmc:/switch/');
177
- *
178
- * http.listen({
179
- * port: 8080,
180
- * async fetch(req) {
181
- * let res = await fileHandler(req);
182
- * if (!res) {
183
- * res = new Response('File not found', { status: 404 });
184
- * }
185
- * return res;
186
- * }
187
- * });
188
- * ```
189
- *
190
- * @param root Root directory where static files are served from
191
- */
192
- export function createStaticFileHandler(root) {
193
- if (!String(root).endsWith('/')) {
194
- throw new Error('`root` directory must end with a "/"');
195
- }
196
- return async function (req) {
197
- const { pathname } = new URL(req.url);
198
- const url = new URL(pathname.slice(1), root);
199
- const stat = await Switch.stat(url);
200
- if (!stat)
201
- return null;
202
- // TODO: replace with readable stream API
203
- const data = await Switch.readFile(url);
204
- if (!data)
205
- return null;
206
- return new Response(data, {
207
- headers: {
208
- 'content-length': String(data.byteLength),
209
- 'content-type': mime.getType(pathname) || 'application/octet-stream',
210
- },
211
- });
212
- };
213
- }
214
25
  /**
215
26
  * Creates an HTTP server and listens on the `port` number specified in the options object.
216
27
  * The `fetch` function will be invoked upon receiving an HTTP request.
@@ -228,10 +39,7 @@ export function createStaticFileHandler(root) {
228
39
  * ```
229
40
  */
230
41
  export function listen(opts) {
231
- const handler = createServerHandler(opts.fetch);
232
- return Switch.listen({
233
- ...opts,
234
- accept: handler,
235
- });
42
+ const accept = createServerHandler(opts.fetch);
43
+ return Switch.listen({ ...opts, accept });
236
44
  }
237
45
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEtD,OAAO,EAAE,uBAAuB,EAA8B,MAAM,UAAU,CAAC;AAc/E;;;;;;;GAOG;AACH,MAAM,UAAU,mBAAmB,CAAC,OAAsB;IACzD,OAAO,KAAK,EAAE,EAAE,MAAM,EAAsB,EAAE,EAAE;QAC/C,MAAM,WAAW,GAAG,IAAI,iBAAiB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC3D,OAAO,IAAI,EAAE,CAAC;YACb,MAAM,GAAG,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,CAAC;YAC3C,IAAI,CAAC,GAAG;gBAAE,MAAM;YAChB,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC;YAC/B,aAAa,CAAC,MAAM,CAAC,QAAQ,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC;QACjD,CAAC;QACD,MAAM,CAAC,KAAK,EAAE,CAAC;IAChB,CAAC,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,MAAM,CAAC,IAAmB;IACzC,MAAM,MAAM,GAAG,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC/C,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;AAC3C,CAAC"}
@@ -0,0 +1,5 @@
1
+ /// <reference types="nxjs-runtime" />
2
+ import type { UnshiftableStream } from './unshiftable-readable-stream';
3
+ export declare function readRequest(unshiftable: UnshiftableStream): Promise<Request | null>;
4
+ export declare function createChunkedWriter(readable: ReadableStream<Uint8Array>): ReadableStream<Uint8Array>;
5
+ export declare function writeResponse(writable: WritableStream<Uint8Array>, res: Response, httpVersion: string): Promise<void>;
package/dist/server.js ADDED
@@ -0,0 +1,135 @@
1
+ import { encoder } from './util';
2
+ import { bodyStream } from './body';
3
+ import { readHeaders, toHeaders } from './headers';
4
+ const STATUS_CODES = {
5
+ '100': 'Continue',
6
+ '101': 'Switching Protocols',
7
+ '102': 'Processing',
8
+ '103': 'Early Hints',
9
+ '200': 'OK',
10
+ '201': 'Created',
11
+ '202': 'Accepted',
12
+ '203': 'Non-Authoritative Information',
13
+ '204': 'No Content',
14
+ '205': 'Reset Content',
15
+ '206': 'Partial Content',
16
+ '207': 'Multi-Status',
17
+ '208': 'Already Reported',
18
+ '226': 'IM Used',
19
+ '300': 'Multiple Choices',
20
+ '301': 'Moved Permanently',
21
+ '302': 'Found',
22
+ '303': 'See Other',
23
+ '304': 'Not Modified',
24
+ '305': 'Use Proxy',
25
+ '307': 'Temporary Redirect',
26
+ '308': 'Permanent Redirect',
27
+ '400': 'Bad Request',
28
+ '401': 'Unauthorized',
29
+ '402': 'Payment Required',
30
+ '403': 'Forbidden',
31
+ '404': 'Not Found',
32
+ '405': 'Method Not Allowed',
33
+ '406': 'Not Acceptable',
34
+ '407': 'Proxy Authentication Required',
35
+ '408': 'Request Timeout',
36
+ '409': 'Conflict',
37
+ '410': 'Gone',
38
+ '411': 'Length Required',
39
+ '412': 'Precondition Failed',
40
+ '413': 'Payload Too Large',
41
+ '414': 'URI Too Long',
42
+ '415': 'Unsupported Media Type',
43
+ '416': 'Range Not Satisfiable',
44
+ '417': 'Expectation Failed',
45
+ '418': "I'm a Teapot",
46
+ '421': 'Misdirected Request',
47
+ '422': 'Unprocessable Entity',
48
+ '423': 'Locked',
49
+ '424': 'Failed Dependency',
50
+ '425': 'Too Early',
51
+ '426': 'Upgrade Required',
52
+ '428': 'Precondition Required',
53
+ '429': 'Too Many Requests',
54
+ '431': 'Request Header Fields Too Large',
55
+ '451': 'Unavailable For Legal Reasons',
56
+ '500': 'Internal Server Error',
57
+ '501': 'Not Implemented',
58
+ '502': 'Bad Gateway',
59
+ '503': 'Service Unavailable',
60
+ '504': 'Gateway Timeout',
61
+ '505': 'HTTP Version Not Supported',
62
+ '506': 'Variant Also Negotiates',
63
+ '507': 'Insufficient Storage',
64
+ '508': 'Loop Detected',
65
+ '509': 'Bandwidth Limit Exceeded',
66
+ '510': 'Not Extended',
67
+ '511': 'Network Authentication Required',
68
+ };
69
+ export async function readRequest(unshiftable) {
70
+ const rawHeaders = await readHeaders(unshiftable);
71
+ if (!rawHeaders.length) {
72
+ // Malformed HTTP request - no header sent
73
+ return null;
74
+ }
75
+ const [method, path, _httpVersion] = rawHeaders[0].split(' ');
76
+ const headers = toHeaders(rawHeaders.slice(1));
77
+ const host = headers.get('host');
78
+ const body = method === 'GET' || method === 'HEAD'
79
+ ? null
80
+ : bodyStream(unshiftable, headers);
81
+ return new Request(`http://${host}${path}`, {
82
+ method,
83
+ body,
84
+ headers,
85
+ // @ts-expect-error wtf Node.js - https://github.com/nodejs/node/issues/46221
86
+ duplex: 'half',
87
+ });
88
+ }
89
+ export function createChunkedWriter(readable) {
90
+ const reader = readable.getReader();
91
+ return new ReadableStream({
92
+ async pull(controller) {
93
+ const { done, value } = await reader.read();
94
+ const bytes = done ? 0 : value.length;
95
+ controller.enqueue(encoder.encode(`${bytes.toString(16)}\r\n`));
96
+ if (value)
97
+ controller.enqueue(value);
98
+ controller.enqueue(encoder.encode(`\r\n`));
99
+ if (done)
100
+ controller.close();
101
+ },
102
+ });
103
+ }
104
+ export async function writeResponse(writable, res, httpVersion) {
105
+ const close = res.headers.get('connection') === 'close';
106
+ const chunked = !(close || res.headers.has('content-length'));
107
+ if (!res.headers.has('date')) {
108
+ res.headers.set('date', new Date().toUTCString());
109
+ }
110
+ if (!res.headers.has('content-type')) {
111
+ res.headers.set('content-type', 'text/plain');
112
+ }
113
+ if (chunked) {
114
+ res.headers.set('transfer-encoding', 'chunked');
115
+ }
116
+ let headersStr = '';
117
+ for (const [k, v] of res.headers) {
118
+ headersStr += `${k}: ${v}\r\n`;
119
+ }
120
+ const statusText = res.statusText || STATUS_CODES[res.status];
121
+ const header = `${httpVersion} ${res.status} ${statusText}\r\n${headersStr}\r\n`;
122
+ const w = writable.getWriter();
123
+ w.write(encoder.encode(header));
124
+ w.releaseLock();
125
+ let body = res.body;
126
+ if (body) {
127
+ if (chunked)
128
+ body = createChunkedWriter(body);
129
+ await body.pipeTo(writable, { preventClose: true });
130
+ }
131
+ if (close) {
132
+ await writable.close();
133
+ }
134
+ }
135
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ /// <reference types="nxjs-runtime" />
2
+ export interface StaticFileHandlerOpts {
3
+ headers?: HeadersInit | ((req: Request, path: URL) => HeadersInit);
4
+ }
5
+ export declare function resolvePath(url: string, root: string): URL;
6
+ /**
7
+ * Creates an HTTP handler function which serves file contents from the filesystem.
8
+ *
9
+ * @example
10
+ *
11
+ * ```typescript
12
+ * const fileHandler = http.createStaticFileHandler('sdmc:/switch/');
13
+ *
14
+ * http.listen({
15
+ * port: 8080,
16
+ * async fetch(req) {
17
+ * let res = await fileHandler(req);
18
+ * if (!res) {
19
+ * res = new Response('File not found', { status: 404 });
20
+ * }
21
+ * return res;
22
+ * }
23
+ * });
24
+ * ```
25
+ *
26
+ * @param root Root directory where static files are served from
27
+ */
28
+ export declare function createStaticFileHandler(root: Switch.PathLike, opts?: StaticFileHandlerOpts): (req: Request) => Promise<Response | null>;
package/dist/static.js ADDED
@@ -0,0 +1,50 @@
1
+ import mime from 'mime';
2
+ export function resolvePath(url, root) {
3
+ const { pathname } = new URL(url);
4
+ const resolved = new URL(pathname.replace(/^\/*/, ''), root);
5
+ return resolved;
6
+ }
7
+ /**
8
+ * Creates an HTTP handler function which serves file contents from the filesystem.
9
+ *
10
+ * @example
11
+ *
12
+ * ```typescript
13
+ * const fileHandler = http.createStaticFileHandler('sdmc:/switch/');
14
+ *
15
+ * http.listen({
16
+ * port: 8080,
17
+ * async fetch(req) {
18
+ * let res = await fileHandler(req);
19
+ * if (!res) {
20
+ * res = new Response('File not found', { status: 404 });
21
+ * }
22
+ * return res;
23
+ * }
24
+ * });
25
+ * ```
26
+ *
27
+ * @param root Root directory where static files are served from
28
+ */
29
+ export function createStaticFileHandler(root, opts = {}) {
30
+ let rootStr = String(root);
31
+ if (!rootStr.endsWith('/'))
32
+ rootStr += '/';
33
+ return async (req) => {
34
+ const url = resolvePath(req.url, rootStr);
35
+ const stat = await Switch.stat(url);
36
+ if (!stat)
37
+ return null;
38
+ // TODO: replace with readable stream API
39
+ const data = await Switch.readFile(url);
40
+ if (!data)
41
+ return null;
42
+ const headers = new Headers(typeof opts.headers === 'function'
43
+ ? opts.headers(req, url)
44
+ : opts.headers);
45
+ headers.set('content-length', String(data.byteLength));
46
+ headers.set('content-type', mime.getType(url.pathname) || 'application/octet-stream');
47
+ return new Response(data, { headers });
48
+ };
49
+ }
50
+ //# sourceMappingURL=static.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"static.js","sourceRoot":"","sources":["../src/static.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AAMxB,MAAM,UAAU,WAAW,CAAC,GAAW,EAAE,IAAY;IACpD,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IAClC,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC;IAC7D,OAAO,QAAQ,CAAC;AACjB,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,uBAAuB,CACtC,IAAqB,EACrB,OAA8B,EAAE;IAEhC,IAAI,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAC3B,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,GAAG,CAAC;IAC3C,OAAO,KAAK,EAAE,GAAY,EAA4B,EAAE;QACvD,MAAM,GAAG,GAAG,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAC1C,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACpC,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,CAAC;QACvB,yCAAyC;QACzC,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QACxC,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,CAAC;QACvB,MAAM,OAAO,GAAG,IAAI,OAAO,CAC1B,OAAO,IAAI,CAAC,OAAO,KAAK,UAAU;YACjC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC;YACxB,CAAC,CAAC,IAAI,CAAC,OAAO,CACf,CAAC;QACF,OAAO,CAAC,GAAG,CAAC,gBAAgB,EAAE,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;QACvD,OAAO,CAAC,GAAG,CACV,cAAc,EACd,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,0BAA0B,CACxD,CAAC;QACF,OAAO,IAAI,QAAQ,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;IACxC,CAAC,CAAC;AACH,CAAC"}
@@ -0,0 +1,16 @@
1
+ /// <reference types="nxjs-runtime" />
2
+ import { Deferred } from './deferred';
3
+ export declare class UnshiftableStream {
4
+ buffer: Uint8Array;
5
+ reader: ReadableStreamDefaultReader<Uint8Array>;
6
+ readable: ReadableStream<Uint8Array>;
7
+ paused?: Deferred<void>;
8
+ constructor(sourceStream: ReadableStream<Uint8Array>);
9
+ unshift: (data: Uint8Array) => void;
10
+ pause(): void;
11
+ resume(): void;
12
+ read(): Promise<ReadableStreamReadDoneResult<Uint8Array> | {
13
+ done: boolean;
14
+ value: Uint8Array;
15
+ }>;
16
+ }
@@ -0,0 +1,69 @@
1
+ import { Deferred } from './deferred';
2
+ export class UnshiftableStream {
3
+ buffer;
4
+ reader;
5
+ readable;
6
+ paused;
7
+ constructor(sourceStream) {
8
+ this.buffer = new Uint8Array();
9
+ this.reader = sourceStream.getReader();
10
+ this.pause();
11
+ // Wrap the read method in a ReadableStream
12
+ this.readable = new ReadableStream({
13
+ pull: async (controller) => {
14
+ const { done, value } = await this.read();
15
+ if (done) {
16
+ controller.close();
17
+ }
18
+ else {
19
+ controller.enqueue(value);
20
+ }
21
+ },
22
+ cancel: () => {
23
+ this.reader.cancel();
24
+ },
25
+ });
26
+ }
27
+ // Method to unshift data back to the stream
28
+ unshift = (data) => {
29
+ const newData = new Uint8Array(this.buffer.length + data.length);
30
+ newData.set(data, 0);
31
+ newData.set(this.buffer, data.length);
32
+ this.buffer = newData;
33
+ };
34
+ pause() {
35
+ if (this.paused)
36
+ return;
37
+ //console.log('pause');
38
+ this.paused = new Deferred();
39
+ }
40
+ resume() {
41
+ const p = this.paused;
42
+ if (!p)
43
+ return;
44
+ //console.log('resume');
45
+ this.paused = undefined;
46
+ p.resolve();
47
+ }
48
+ // Read method that checks the buffer first
49
+ async read() {
50
+ //console.log('read')
51
+ if (this.paused) {
52
+ //console.log('read paused')
53
+ await this.paused.promise;
54
+ }
55
+ //console.log('read resume')
56
+ if (this.buffer.length > 0) {
57
+ const value = this.buffer;
58
+ //console.log('buffer', { value })
59
+ this.buffer = new Uint8Array(); // Clear the buffer after reading
60
+ return { done: false, value };
61
+ }
62
+ else {
63
+ const result = await this.reader.read();
64
+ //console.log({ result })
65
+ return result; // Return data from the source stream
66
+ }
67
+ }
68
+ }
69
+ //# sourceMappingURL=unshiftable-readable-stream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unshiftable-readable-stream.js","sourceRoot":"","sources":["../src/unshiftable-readable-stream.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,MAAM,OAAO,iBAAiB;IAC7B,MAAM,CAAa;IACnB,MAAM,CAA0C;IAChD,QAAQ,CAA6B;IACrC,MAAM,CAAkB;IAExB,YAAY,YAAwC;QACnD,IAAI,CAAC,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;QAC/B,IAAI,CAAC,MAAM,GAAG,YAAY,CAAC,SAAS,EAAE,CAAC;QACvC,IAAI,CAAC,KAAK,EAAE,CAAC;QAEb,2CAA2C;QAC3C,IAAI,CAAC,QAAQ,GAAG,IAAI,cAAc,CAAa;YAC9C,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE;gBAC1B,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;gBAC1C,IAAI,IAAI,EAAE,CAAC;oBACV,UAAU,CAAC,KAAK,EAAE,CAAC;gBACpB,CAAC;qBAAM,CAAC;oBACP,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;gBAC3B,CAAC;YACF,CAAC;YACD,MAAM,EAAE,GAAG,EAAE;gBACZ,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YACtB,CAAC;SACD,CAAC,CAAC;IACJ,CAAC;IAED,4CAA4C;IAC5C,OAAO,GAAG,CAAC,IAAgB,EAAE,EAAE;QAC9B,MAAM,OAAO,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;QACjE,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QACrB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QACtC,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC;IACvB,CAAC,CAAC;IAEF,KAAK;QACJ,IAAI,IAAI,CAAC,MAAM;YAAE,OAAO;QACxB,uBAAuB;QACvB,IAAI,CAAC,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;IAC9B,CAAC;IAED,MAAM;QACL,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC;QACtB,IAAI,CAAC,CAAC;YAAE,OAAO;QACf,wBAAwB;QACxB,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC;QACxB,CAAC,CAAC,OAAO,EAAE,CAAC;IACb,CAAC;IAED,2CAA2C;IAC3C,KAAK,CAAC,IAAI;QACT,qBAAqB;QACrB,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,4BAA4B;YAC5B,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC;QAC3B,CAAC;QACD,4BAA4B;QAC5B,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC5B,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC;YAC1B,kCAAkC;YAClC,IAAI,CAAC,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC,CAAC,iCAAiC;YACjE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;QAC/B,CAAC;aAAM,CAAC;YACP,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;YACxC,yBAAyB;YACzB,OAAO,MAAM,CAAC,CAAC,qCAAqC;QACrD,CAAC;IACF,CAAC;CACD"}
package/dist/util.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ /// <reference types="nxjs-runtime" />
2
+ import type { UnshiftableStream } from './unshiftable-readable-stream';
3
+ export declare const encoder: TextEncoder;
4
+ export declare const decoder: TextDecoder;
5
+ export declare function indexOfEol(arr: ArrayLike<number>, offset?: number): number;
6
+ export declare function concat(a: Uint8Array, b: Uint8Array): Uint8Array;
7
+ export declare function readUntilEol(reader: ReadableStreamDefaultReader<Uint8Array>, unshiftable: UnshiftableStream): Promise<string>;
8
+ export declare function flushBytes(controller: ReadableStreamDefaultController<Uint8Array>, numBytes: number, reader: ReadableStreamDefaultReader<Uint8Array>, unshiftable: UnshiftableStream): Promise<void>;
package/dist/util.js ADDED
@@ -0,0 +1,62 @@
1
+ export const encoder = new TextEncoder();
2
+ export const decoder = new TextDecoder();
3
+ export function indexOfEol(arr, offset = 0) {
4
+ for (let i = offset; i < arr.length - 1; i++) {
5
+ if (arr[i] === 13 && arr[i + 1] === 10) {
6
+ return i;
7
+ }
8
+ }
9
+ return -1;
10
+ }
11
+ export function concat(a, b) {
12
+ const c = new Uint8Array(a.length + b.length);
13
+ c.set(a, 0);
14
+ c.set(b, a.length);
15
+ return c;
16
+ }
17
+ export async function readUntilEol(reader, unshiftable) {
18
+ let buffered = new Uint8Array(0);
19
+ while (true) {
20
+ unshiftable.resume();
21
+ const { done, value } = await reader.read();
22
+ unshiftable.pause();
23
+ if (done)
24
+ break;
25
+ buffered = concat(buffered, value);
26
+ const i = indexOfEol(buffered);
27
+ if (i !== -1) {
28
+ if (buffered.length > i + 2) {
29
+ unshiftable.unshift(buffered.slice(i + 2));
30
+ buffered = buffered.slice(0, i);
31
+ }
32
+ break;
33
+ }
34
+ }
35
+ return decoder.decode(buffered);
36
+ }
37
+ export async function flushBytes(controller, numBytes, reader, unshiftable) {
38
+ let numFlushed = 0;
39
+ while (true) {
40
+ unshiftable.resume();
41
+ const { done, value } = await reader.read();
42
+ unshiftable.pause();
43
+ if (done)
44
+ break;
45
+ const numRemaining = numBytes - numFlushed;
46
+ if (value.length > numRemaining) {
47
+ unshiftable.unshift(value.slice(numRemaining));
48
+ const chunk = value.slice(0, numRemaining);
49
+ numFlushed += chunk.length;
50
+ controller.enqueue(chunk);
51
+ break;
52
+ }
53
+ else {
54
+ numFlushed += value.length;
55
+ controller.enqueue(value);
56
+ }
57
+ }
58
+ if (numFlushed !== numBytes) {
59
+ // TODO: throw error?
60
+ }
61
+ }
62
+ //# sourceMappingURL=util.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nx.js/http",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "description": "HTTP server for nx.js",
5
5
  "main": "dist/index.js",
6
6
  "files": [
@@ -10,9 +10,10 @@
10
10
  "access": "public"
11
11
  },
12
12
  "devDependencies": {
13
- "@types/mime-types": "^2.1.4",
14
13
  "typescript": "^5.3.2",
15
- "nxjs-runtime": "0.0.37"
14
+ "vite": "^5.1.6",
15
+ "vitest": "^1.3.1",
16
+ "nxjs-runtime": "0.0.43"
16
17
  },
17
18
  "keywords": [
18
19
  "nx.js",
@@ -26,6 +27,7 @@
26
27
  "mime": "^4.0.1"
27
28
  },
28
29
  "scripts": {
29
- "build": "tsc"
30
+ "build": "tsc",
31
+ "test": "vitest"
30
32
  }
31
33
  }