@gjsify/http2 0.3.21 → 0.4.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/src/index.spec.ts DELETED
@@ -1,275 +0,0 @@
1
- // Ported from refs/node-test/parallel/test-http2-*.js
2
- // Original: MIT license, Node.js contributors
3
-
4
- import { describe, it, expect } from '@gjsify/unit';
5
- import http2 from 'node:http2';
6
-
7
- // @types/node is missing some http2 constants that Node.js exports at runtime.
8
- declare module 'node:http2' {
9
- namespace constants {
10
- const NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL: number;
11
- const DEFAULT_SETTINGS_MAX_HEADER_LIST_SIZE: number;
12
- const HTTP2_HEADER_PROTOCOL: string;
13
- }
14
- }
15
-
16
- const {
17
- constants,
18
- getDefaultSettings,
19
- getPackedSettings,
20
- getUnpackedSettings,
21
- sensitiveHeaders,
22
- createServer,
23
- createSecureServer,
24
- connect,
25
- Http2ServerRequest,
26
- Http2ServerResponse,
27
- } = http2;
28
-
29
- export default async () => {
30
- // --- Constants ---
31
-
32
- await describe('http2.constants', async () => {
33
- await it('should export constants object', async () => {
34
- expect(constants).toBeDefined();
35
- expect(typeof constants).toBe('object');
36
- });
37
-
38
- await it('should have NGHTTP2 error codes', async () => {
39
- expect(constants.NGHTTP2_NO_ERROR).toBe(0x00);
40
- expect(constants.NGHTTP2_PROTOCOL_ERROR).toBe(0x01);
41
- expect(constants.NGHTTP2_INTERNAL_ERROR).toBe(0x02);
42
- expect(constants.NGHTTP2_FLOW_CONTROL_ERROR).toBe(0x03);
43
- expect(constants.NGHTTP2_SETTINGS_TIMEOUT).toBe(0x04);
44
- expect(constants.NGHTTP2_STREAM_CLOSED).toBe(0x05);
45
- expect(constants.NGHTTP2_FRAME_SIZE_ERROR).toBe(0x06);
46
- expect(constants.NGHTTP2_REFUSED_STREAM).toBe(0x07);
47
- expect(constants.NGHTTP2_CANCEL).toBe(0x08);
48
- expect(constants.NGHTTP2_COMPRESSION_ERROR).toBe(0x09);
49
- expect(constants.NGHTTP2_CONNECT_ERROR).toBe(0x0a);
50
- expect(constants.NGHTTP2_ENHANCE_YOUR_CALM).toBe(0x0b);
51
- expect(constants.NGHTTP2_INADEQUATE_SECURITY).toBe(0x0c);
52
- expect(constants.NGHTTP2_HTTP_1_1_REQUIRED).toBe(0x0d);
53
- });
54
-
55
- await it('should have session type constants', async () => {
56
- expect(constants.NGHTTP2_SESSION_SERVER).toBe(0);
57
- expect(constants.NGHTTP2_SESSION_CLIENT).toBe(1);
58
- });
59
-
60
- await it('should have stream state constants', async () => {
61
- expect(constants.NGHTTP2_STREAM_STATE_IDLE).toBe(1);
62
- expect(constants.NGHTTP2_STREAM_STATE_OPEN).toBe(2);
63
- expect(constants.NGHTTP2_STREAM_STATE_RESERVED_LOCAL).toBe(3);
64
- expect(constants.NGHTTP2_STREAM_STATE_RESERVED_REMOTE).toBe(4);
65
- expect(constants.NGHTTP2_STREAM_STATE_HALF_CLOSED_LOCAL).toBe(5);
66
- expect(constants.NGHTTP2_STREAM_STATE_HALF_CLOSED_REMOTE).toBe(6);
67
- expect(constants.NGHTTP2_STREAM_STATE_CLOSED).toBe(7);
68
- });
69
-
70
- await it('should have settings ID constants', async () => {
71
- expect(constants.NGHTTP2_SETTINGS_HEADER_TABLE_SIZE).toBe(0x01);
72
- expect(constants.NGHTTP2_SETTINGS_ENABLE_PUSH).toBe(0x02);
73
- expect(constants.NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS).toBe(0x03);
74
- expect(constants.NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE).toBe(0x04);
75
- expect(constants.NGHTTP2_SETTINGS_MAX_FRAME_SIZE).toBe(0x05);
76
- expect(constants.NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE).toBe(0x06);
77
- expect(constants.NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL).toBe(0x08);
78
- });
79
-
80
- await it('should have default settings value constants', async () => {
81
- expect(constants.DEFAULT_SETTINGS_HEADER_TABLE_SIZE).toBe(4096);
82
- expect(constants.DEFAULT_SETTINGS_ENABLE_PUSH).toBe(1);
83
- expect(constants.DEFAULT_SETTINGS_INITIAL_WINDOW_SIZE).toBe(65535);
84
- expect(constants.DEFAULT_SETTINGS_MAX_FRAME_SIZE).toBe(16384);
85
- expect(constants.DEFAULT_SETTINGS_MAX_HEADER_LIST_SIZE).toBe(65535);
86
- });
87
-
88
- await it('should have frame flag constants', async () => {
89
- expect(constants.NGHTTP2_FLAG_NONE).toBe(0);
90
- expect(constants.NGHTTP2_FLAG_END_STREAM).toBe(0x01);
91
- expect(constants.NGHTTP2_FLAG_END_HEADERS).toBe(0x04);
92
- expect(constants.NGHTTP2_FLAG_PADDED).toBe(0x08);
93
- expect(constants.NGHTTP2_FLAG_PRIORITY).toBe(0x20);
94
- });
95
-
96
- await it('should have HTTP/2 pseudo-header constants', async () => {
97
- expect(constants.HTTP2_HEADER_STATUS).toBe(':status');
98
- expect(constants.HTTP2_HEADER_METHOD).toBe(':method');
99
- expect(constants.HTTP2_HEADER_PATH).toBe(':path');
100
- expect(constants.HTTP2_HEADER_AUTHORITY).toBe(':authority');
101
- expect(constants.HTTP2_HEADER_SCHEME).toBe(':scheme');
102
- expect(constants.HTTP2_HEADER_PROTOCOL).toBe(':protocol');
103
- });
104
-
105
- await it('should have standard HTTP header constants', async () => {
106
- expect(constants.HTTP2_HEADER_CONTENT_TYPE).toBe('content-type');
107
- expect(constants.HTTP2_HEADER_CONTENT_LENGTH).toBe('content-length');
108
- expect(constants.HTTP2_HEADER_ACCEPT).toBe('accept');
109
- expect(constants.HTTP2_HEADER_AUTHORIZATION).toBe('authorization');
110
- expect(constants.HTTP2_HEADER_CACHE_CONTROL).toBe('cache-control');
111
- expect(constants.HTTP2_HEADER_COOKIE).toBe('cookie');
112
- expect(constants.HTTP2_HEADER_SET_COOKIE).toBe('set-cookie');
113
- expect(constants.HTTP2_HEADER_USER_AGENT).toBe('user-agent');
114
- expect(constants.HTTP2_HEADER_HOST).toBe('host');
115
- });
116
-
117
- await it('should have HTTP method constants', async () => {
118
- expect(constants.HTTP2_METHOD_GET).toBe('GET');
119
- expect(constants.HTTP2_METHOD_POST).toBe('POST');
120
- expect(constants.HTTP2_METHOD_PUT).toBe('PUT');
121
- expect(constants.HTTP2_METHOD_DELETE).toBe('DELETE');
122
- expect(constants.HTTP2_METHOD_PATCH).toBe('PATCH');
123
- expect(constants.HTTP2_METHOD_HEAD).toBe('HEAD');
124
- expect(constants.HTTP2_METHOD_OPTIONS).toBe('OPTIONS');
125
- expect(constants.HTTP2_METHOD_CONNECT).toBe('CONNECT');
126
- });
127
-
128
- await it('should have HTTP status code constants', async () => {
129
- expect(constants.HTTP_STATUS_CONTINUE).toBe(100);
130
- expect(constants.HTTP_STATUS_OK).toBe(200);
131
- expect(constants.HTTP_STATUS_CREATED).toBe(201);
132
- expect(constants.HTTP_STATUS_NO_CONTENT).toBe(204);
133
- expect(constants.HTTP_STATUS_MOVED_PERMANENTLY).toBe(301);
134
- expect(constants.HTTP_STATUS_NOT_FOUND).toBe(404);
135
- expect(constants.HTTP_STATUS_TEAPOT).toBe(418);
136
- expect(constants.HTTP_STATUS_INTERNAL_SERVER_ERROR).toBe(500);
137
- expect(constants.HTTP_STATUS_BAD_GATEWAY).toBe(502);
138
- expect(constants.HTTP_STATUS_SERVICE_UNAVAILABLE).toBe(503);
139
- });
140
-
141
- await it('should have frame size constraint constants', async () => {
142
- expect(constants.MAX_MAX_FRAME_SIZE).toBe(16777215);
143
- expect(constants.MIN_MAX_FRAME_SIZE).toBe(16384);
144
- expect(constants.MAX_INITIAL_WINDOW_SIZE).toBe(2147483647);
145
- expect(constants.NGHTTP2_DEFAULT_WEIGHT).toBe(16);
146
- });
147
- });
148
-
149
- // --- Settings ---
150
-
151
- await describe('http2.getDefaultSettings', async () => {
152
- await it('should return an object with default settings', async () => {
153
- const settings = getDefaultSettings();
154
- expect(settings).toBeDefined();
155
- expect(typeof settings).toBe('object');
156
- });
157
-
158
- await it('should have headerTableSize = 4096', async () => {
159
- expect(getDefaultSettings().headerTableSize).toBe(4096);
160
- });
161
-
162
- await it('should have enablePush = true', async () => {
163
- expect(getDefaultSettings().enablePush).toBe(true);
164
- });
165
-
166
- await it('should have initialWindowSize = 65535', async () => {
167
- expect(getDefaultSettings().initialWindowSize).toBe(65535);
168
- });
169
-
170
- await it('should have maxFrameSize = 16384', async () => {
171
- expect(getDefaultSettings().maxFrameSize).toBe(16384);
172
- });
173
-
174
- await it('should have enableConnectProtocol = false', async () => {
175
- expect(getDefaultSettings().enableConnectProtocol).toBe(false);
176
- });
177
- });
178
-
179
- await describe('http2.getPackedSettings / getUnpackedSettings', async () => {
180
- await it('getPackedSettings should return Uint8Array', async () => {
181
- const packed = getPackedSettings({ headerTableSize: 4096 });
182
- expect(packed instanceof Uint8Array).toBe(true);
183
- });
184
-
185
- await it('getPackedSettings with no args should return empty', async () => {
186
- // Calling getPackedSettings() without args is valid at runtime; @types/node requires one arg.
187
- const packed = (getPackedSettings as any)();
188
- expect(packed.byteLength).toBe(0);
189
- });
190
-
191
- await it('getPackedSettings should encode one setting as 6 bytes', async () => {
192
- const packed = getPackedSettings({ headerTableSize: 4096 });
193
- expect(packed.byteLength).toBe(6);
194
- });
195
-
196
- await it('getPackedSettings should encode multiple settings', async () => {
197
- const packed = getPackedSettings({
198
- headerTableSize: 4096,
199
- enablePush: true,
200
- maxFrameSize: 32768,
201
- });
202
- expect(packed.byteLength).toBe(18);
203
- });
204
-
205
- await it('round-trip should preserve settings', async () => {
206
- const original = {
207
- headerTableSize: 8192,
208
- enablePush: false,
209
- maxConcurrentStreams: 100,
210
- initialWindowSize: 32768,
211
- maxFrameSize: 32768,
212
- };
213
- const packed = getPackedSettings(original);
214
- const unpacked = getUnpackedSettings(packed);
215
- expect(unpacked.headerTableSize).toBe(8192);
216
- expect(unpacked.enablePush).toBe(false);
217
- expect(unpacked.maxConcurrentStreams).toBe(100);
218
- expect(unpacked.initialWindowSize).toBe(32768);
219
- expect(unpacked.maxFrameSize).toBe(32768);
220
- });
221
-
222
- await it('getUnpackedSettings should throw on invalid length', async () => {
223
- let threw = false;
224
- try {
225
- getUnpackedSettings(new Uint8Array(7));
226
- } catch {
227
- threw = true;
228
- }
229
- expect(threw).toBe(true);
230
- });
231
- });
232
-
233
- // --- sensitiveHeaders ---
234
-
235
- await describe('http2.sensitiveHeaders', async () => {
236
- await it('should be a symbol', async () => {
237
- expect(typeof sensitiveHeaders).toBe('symbol');
238
- });
239
- });
240
-
241
- // --- Factory functions ---
242
-
243
- await describe('http2 factory functions', async () => {
244
- await it('createServer should be a function', async () => {
245
- expect(typeof createServer).toBe('function');
246
- });
247
-
248
- await it('createSecureServer should be a function', async () => {
249
- expect(typeof createSecureServer).toBe('function');
250
- });
251
-
252
- await it('connect should be a function', async () => {
253
- expect(typeof connect).toBe('function');
254
- });
255
-
256
- // Note: createServer/createSecureServer/connect work on Node.js but throw on GJS.
257
- // Testing the throw behavior would be platform-specific.
258
- });
259
-
260
- // --- Class exports ---
261
-
262
- await describe('http2 class exports', async () => {
263
- await it('should export Http2ServerRequest', async () => {
264
- expect(typeof Http2ServerRequest).toBe('function');
265
- });
266
-
267
- await it('should export Http2ServerResponse', async () => {
268
- expect(typeof Http2ServerResponse).toBe('function');
269
- });
270
-
271
- // Note: Http2Session, Http2Stream, ServerHttp2Session are exported differently
272
- // on Node.js (named exports) vs our implementation (default export).
273
- // Testing export availability would be platform-specific.
274
- });
275
- };
package/src/index.ts DELETED
@@ -1,124 +0,0 @@
1
- // Reference: Node.js lib/http2.js, lib/internal/http2/core.js, lib/internal/http2/compat.js
2
- // Reimplemented for GJS using Soup 3.0 (HTTP/2 transparently via ALPN when TLS is active)
3
- //
4
- // Phase 1: Compat layer backed by Soup.Server + Soup.Session.
5
- // createServer() → HTTP/1.1 only (Soup does not support h2c/cleartext HTTP/2)
6
- // createSecureServer() → HTTP/2 via ALPN when TLS cert is provided, else HTTP/1.1
7
- // connect() → HTTP/2 over HTTPS automatically, HTTP/1.1 over plain HTTP
8
- //
9
- // Phase 2 (future, requires Vala/nghttp2): pushStream, stream IDs, flow control, GOAWAY
10
-
11
- // ─── Protocol constants & settings ───────────────────────────────────────────
12
-
13
- export {
14
- constants,
15
- getDefaultSettings,
16
- getPackedSettings,
17
- getUnpackedSettings,
18
- type Http2Settings,
19
- } from './protocol.js';
20
-
21
- import { constants, getDefaultSettings, getPackedSettings, getUnpackedSettings, type Http2Settings } from './protocol.js';
22
-
23
- // ─── Server-side classes ──────────────────────────────────────────────────────
24
-
25
- export {
26
- Http2ServerRequest,
27
- Http2ServerResponse,
28
- ServerHttp2Stream,
29
- ServerHttp2Session,
30
- Http2Server,
31
- Http2SecureServer,
32
- type ServerOptions,
33
- type SecureServerOptions,
34
- } from './server.js';
35
-
36
- import {
37
- Http2ServerRequest,
38
- Http2ServerResponse,
39
- ServerHttp2Stream,
40
- ServerHttp2Session,
41
- Http2Server,
42
- Http2SecureServer,
43
- type ServerOptions,
44
- type SecureServerOptions,
45
- } from './server.js';
46
-
47
- // ─── Client-side classes ──────────────────────────────────────────────────────
48
-
49
- export {
50
- Http2Session,
51
- ClientHttp2Session,
52
- ClientHttp2Stream,
53
- type ClientSessionOptions,
54
- type ClientStreamOptions,
55
- } from './client-session.js';
56
-
57
- import {
58
- Http2Session,
59
- ClientHttp2Session,
60
- ClientHttp2Stream,
61
- type ClientSessionOptions,
62
- } from './client-session.js';
63
-
64
- // ─── Factory functions ────────────────────────────────────────────────────────
65
-
66
- export function createServer(
67
- options?: ServerOptions | ((req: Http2ServerRequest, res: Http2ServerResponse) => void),
68
- handler?: (req: Http2ServerRequest, res: Http2ServerResponse) => void,
69
- ): Http2Server {
70
- return new Http2Server(options, handler);
71
- }
72
-
73
- export function createSecureServer(
74
- options: SecureServerOptions,
75
- handler?: (req: Http2ServerRequest, res: Http2ServerResponse) => void,
76
- ): Http2SecureServer {
77
- return new Http2SecureServer(options, handler);
78
- }
79
-
80
- export function connect(
81
- authority: string | URL,
82
- options?: ClientSessionOptions | ((session: ClientHttp2Session, socket: any) => void),
83
- listener?: (session: ClientHttp2Session, socket: any) => void,
84
- ): ClientHttp2Session {
85
- const authorityStr = typeof authority === 'string' ? authority : authority.toString();
86
- if (typeof options === 'function') {
87
- listener = options;
88
- options = {};
89
- }
90
- const session = new ClientHttp2Session(authorityStr, (options ?? {}) as ClientSessionOptions);
91
- if (listener) session.once('connect', listener);
92
- return session;
93
- }
94
-
95
- // ─── Misc ─────────────────────────────────────────────────────────────────────
96
-
97
- export const sensitiveHeaders = Symbol.for('nodejs.http2.sensitiveHeaders');
98
-
99
- export function performServerHandshake(_socket: unknown): unknown {
100
- throw new Error('http2.performServerHandshake() is not yet implemented in GJS');
101
- }
102
-
103
- // ─── Default export ───────────────────────────────────────────────────────────
104
-
105
- export default {
106
- constants,
107
- createServer,
108
- createSecureServer,
109
- connect,
110
- getDefaultSettings,
111
- getPackedSettings,
112
- getUnpackedSettings,
113
- sensitiveHeaders,
114
- performServerHandshake,
115
- Http2Session,
116
- Http2Server,
117
- Http2SecureServer,
118
- Http2ServerRequest,
119
- Http2ServerResponse,
120
- ServerHttp2Session,
121
- ServerHttp2Stream,
122
- ClientHttp2Session,
123
- ClientHttp2Stream,
124
- };