@travetto/web-http 7.1.4 → 8.0.0-alpha.1
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/README.md +9 -8
- package/package.json +4 -4
- package/src/config.ts +8 -6
- package/src/http.ts +7 -12
- package/support/cli.web_http.ts +15 -3
- package/support/test/dispatcher.ts +5 -8
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@ yarn add @travetto/web-http
|
|
|
16
16
|
This module provides basic for running [http](https://nodejs.org/api/http.html). [https](https://nodejs.org/api/https.html) and [http2](https://nodejs.org/api/http2.html) servers, along with support for tls key generation during development.
|
|
17
17
|
|
|
18
18
|
## Running a Server
|
|
19
|
-
By default, the framework provides a default [@CliCommand](https://github.com/travetto/travetto/tree/main/module/cli/src/registry/decorator.ts#
|
|
19
|
+
By default, the framework provides a default [@CliCommand](https://github.com/travetto/travetto/tree/main/module/cli/src/registry/decorator.ts#L27) for [WebHttpServer](https://github.com/travetto/travetto/tree/main/module/web-http/src/types.ts#L19) that will follow default behaviors, and spin up the server.
|
|
20
20
|
|
|
21
21
|
**Terminal: Standard application**
|
|
22
22
|
```bash
|
|
@@ -123,23 +123,24 @@ export class WebHttpConfig {
|
|
|
123
123
|
@Ignore()
|
|
124
124
|
fetchUrl: string;
|
|
125
125
|
|
|
126
|
-
|
|
126
|
+
@PostConstruct()
|
|
127
|
+
async finalizeConfig(): Promise<void> {
|
|
127
128
|
this.tls ??= (this.httpVersion === '2' || !!this.tlsKeys);
|
|
128
129
|
this.port = (this.port < 0 ? await NetUtil.getFreePort() : this.port);
|
|
129
|
-
this.bindAddress ||=
|
|
130
|
+
this.bindAddress ||= NetUtil.getLocalAddress();
|
|
130
131
|
|
|
131
132
|
if (!this.tls) {
|
|
132
133
|
// Clear out keys if tls is not set
|
|
133
134
|
this.tlsKeys = undefined;
|
|
134
135
|
} else if (!this.tlsKeys) {
|
|
135
136
|
if (Runtime.production) {
|
|
136
|
-
throw new
|
|
137
|
+
throw new RuntimeError('Default tls keys are only valid for development use, please specify a config value at web.tls.keys');
|
|
137
138
|
}
|
|
138
139
|
this.tlsKeys = await WebTlsUtil.generateKeyPair();
|
|
139
140
|
} else {
|
|
140
141
|
if (this.tlsKeys.key.length < 100) { // We have files or resources
|
|
141
|
-
this.tlsKeys.key =
|
|
142
|
-
this.tlsKeys.cert =
|
|
142
|
+
this.tlsKeys.key = await RuntimeResources.readText(this.tlsKeys.key);
|
|
143
|
+
this.tlsKeys.cert = await RuntimeResources.readText(this.tlsKeys.cert);
|
|
143
144
|
}
|
|
144
145
|
}
|
|
145
146
|
|
|
@@ -149,7 +150,7 @@ export class WebHttpConfig {
|
|
|
149
150
|
```
|
|
150
151
|
|
|
151
152
|
### Creating a Custom CLI Entry Point
|
|
152
|
-
To customize a Web server, you may need to construct an entry point using the [@CliCommand](https://github.com/travetto/travetto/tree/main/module/cli/src/registry/decorator.ts#
|
|
153
|
+
To customize a Web server, you may need to construct an entry point using the [@CliCommand](https://github.com/travetto/travetto/tree/main/module/cli/src/registry/decorator.ts#L27) decorator. This could look like:
|
|
153
154
|
|
|
154
155
|
**Code: Application entry point for Web Applications**
|
|
155
156
|
```typescript
|
|
@@ -203,7 +204,7 @@ Initialized {
|
|
|
203
204
|
}
|
|
204
205
|
},
|
|
205
206
|
runtime: {
|
|
206
|
-
production:
|
|
207
|
+
production: false,
|
|
207
208
|
role: 'std',
|
|
208
209
|
debug: false,
|
|
209
210
|
resourcePaths: [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@travetto/web-http",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "8.0.0-alpha.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Web HTTP Server Support",
|
|
6
6
|
"keywords": [
|
|
@@ -27,11 +27,11 @@
|
|
|
27
27
|
"directory": "module/web-http"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@travetto/web": "^
|
|
30
|
+
"@travetto/web": "^8.0.0-alpha.1"
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
33
|
-
"@travetto/cli": "^
|
|
34
|
-
"@travetto/test": "^
|
|
33
|
+
"@travetto/cli": "^8.0.0-alpha.1",
|
|
34
|
+
"@travetto/test": "^8.0.0-alpha.1"
|
|
35
35
|
},
|
|
36
36
|
"peerDependenciesMeta": {
|
|
37
37
|
"@travetto/test": {
|
package/src/config.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Config, EnvVar } from '@travetto/config';
|
|
2
2
|
import { Ignore, Secret } from '@travetto/schema';
|
|
3
|
-
import {
|
|
3
|
+
import { RuntimeError, Runtime, RuntimeResources } from '@travetto/runtime';
|
|
4
4
|
import { NetUtil } from '@travetto/web';
|
|
5
|
+
import { PostConstruct } from '@travetto/di';
|
|
5
6
|
|
|
6
7
|
import type { WebSecureKeyPair } from './types.ts';
|
|
7
8
|
import { WebTlsUtil } from './tls.ts';
|
|
@@ -45,23 +46,24 @@ export class WebHttpConfig {
|
|
|
45
46
|
@Ignore()
|
|
46
47
|
fetchUrl: string;
|
|
47
48
|
|
|
48
|
-
|
|
49
|
+
@PostConstruct()
|
|
50
|
+
async finalizeConfig(): Promise<void> {
|
|
49
51
|
this.tls ??= (this.httpVersion === '2' || !!this.tlsKeys);
|
|
50
52
|
this.port = (this.port < 0 ? await NetUtil.getFreePort() : this.port);
|
|
51
|
-
this.bindAddress ||=
|
|
53
|
+
this.bindAddress ||= NetUtil.getLocalAddress();
|
|
52
54
|
|
|
53
55
|
if (!this.tls) {
|
|
54
56
|
// Clear out keys if tls is not set
|
|
55
57
|
this.tlsKeys = undefined;
|
|
56
58
|
} else if (!this.tlsKeys) {
|
|
57
59
|
if (Runtime.production) {
|
|
58
|
-
throw new
|
|
60
|
+
throw new RuntimeError('Default tls keys are only valid for development use, please specify a config value at web.tls.keys');
|
|
59
61
|
}
|
|
60
62
|
this.tlsKeys = await WebTlsUtil.generateKeyPair();
|
|
61
63
|
} else {
|
|
62
64
|
if (this.tlsKeys.key.length < 100) { // We have files or resources
|
|
63
|
-
this.tlsKeys.key =
|
|
64
|
-
this.tlsKeys.cert =
|
|
65
|
+
this.tlsKeys.key = await RuntimeResources.readText(this.tlsKeys.key);
|
|
66
|
+
this.tlsKeys.cert = await RuntimeResources.readText(this.tlsKeys.cert);
|
|
65
67
|
}
|
|
66
68
|
}
|
|
67
69
|
|
package/src/http.ts
CHANGED
|
@@ -2,11 +2,10 @@ import type net from 'node:net';
|
|
|
2
2
|
import http from 'node:http';
|
|
3
3
|
import http2 from 'node:http2';
|
|
4
4
|
import https from 'node:https';
|
|
5
|
-
import { pipeline } from 'node:stream/promises';
|
|
6
5
|
import { TLSSocket } from 'node:tls';
|
|
7
6
|
|
|
8
7
|
import { WebBodyUtil, WebCommonUtil, type WebDispatcher, WebRequest, WebResponse } from '@travetto/web';
|
|
9
|
-
import { BinaryUtil, castTo, ShutdownManager } from '@travetto/runtime';
|
|
8
|
+
import { type BinaryType, BinaryUtil, castTo, ShutdownManager } from '@travetto/runtime';
|
|
10
9
|
|
|
11
10
|
import type { WebSecureKeyPair, WebServerHandle } from './types.ts';
|
|
12
11
|
|
|
@@ -119,7 +118,7 @@ export class WebHttpUtil {
|
|
|
119
118
|
httpQuery: Object.fromEntries(new URLSearchParams(query)),
|
|
120
119
|
},
|
|
121
120
|
headers: request.headers,
|
|
122
|
-
body: WebBodyUtil.
|
|
121
|
+
body: WebBodyUtil.markRawBinary(request)
|
|
123
122
|
});
|
|
124
123
|
}
|
|
125
124
|
|
|
@@ -127,18 +126,14 @@ export class WebHttpUtil {
|
|
|
127
126
|
* Send WebResponse to outbound http response
|
|
128
127
|
*/
|
|
129
128
|
static async respondToServerResponse(webResponse: WebResponse, response: HttpResponse): Promise<void> {
|
|
130
|
-
const binaryResponse = new WebResponse({ context: webResponse.context, ...WebBodyUtil.toBinaryMessage(webResponse) });
|
|
129
|
+
const binaryResponse = new WebResponse<BinaryType>({ context: webResponse.context, ...WebBodyUtil.toBinaryMessage(webResponse) });
|
|
131
130
|
binaryResponse.headers.forEach((value, key) => response.setHeader(key, value));
|
|
132
131
|
response.statusCode = WebCommonUtil.getStatusCode(binaryResponse);
|
|
133
|
-
const body = binaryResponse.body;
|
|
134
132
|
|
|
135
|
-
if (
|
|
136
|
-
await pipeline(body, response);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
// Weird type union that http2 uses
|
|
140
|
-
'stream' in response ? response.write(body) : response.write(body);
|
|
141
|
-
}
|
|
133
|
+
if (binaryResponse.body) {
|
|
134
|
+
await BinaryUtil.pipeline(binaryResponse.body, response);
|
|
135
|
+
}
|
|
136
|
+
if (!response.closed) {
|
|
142
137
|
response.end();
|
|
143
138
|
}
|
|
144
139
|
}
|
package/support/cli.web_http.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Runtime, toConcrete } from '@travetto/runtime';
|
|
2
2
|
import { DependencyRegistryIndex } from '@travetto/di';
|
|
3
|
-
import { CliCommand, type CliCommandShape } from '@travetto/cli';
|
|
3
|
+
import { CliCommand, CliDebugIpcFlag, CliModuleFlag, CliProfilesFlag, CliRestartOnChangeFlag, type CliCommandShape } from '@travetto/cli';
|
|
4
4
|
import { NetUtil } from '@travetto/web';
|
|
5
5
|
import { Registry } from '@travetto/registry';
|
|
6
6
|
|
|
@@ -9,7 +9,7 @@ import type { WebHttpServer } from '../src/types.ts';
|
|
|
9
9
|
/**
|
|
10
10
|
* Run a web server
|
|
11
11
|
*/
|
|
12
|
-
@CliCommand(
|
|
12
|
+
@CliCommand()
|
|
13
13
|
export class WebHttpCommand implements CliCommandShape {
|
|
14
14
|
|
|
15
15
|
/** Port to run on */
|
|
@@ -18,7 +18,19 @@ export class WebHttpCommand implements CliCommandShape {
|
|
|
18
18
|
/** Kill conflicting port owner */
|
|
19
19
|
killConflict?: boolean = Runtime.localDevelopment;
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
@CliModuleFlag({ short: 'm' })
|
|
22
|
+
module: string;
|
|
23
|
+
|
|
24
|
+
@CliProfilesFlag()
|
|
25
|
+
profile: string[];
|
|
26
|
+
|
|
27
|
+
@CliRestartOnChangeFlag()
|
|
28
|
+
restartOnChange: boolean = true;
|
|
29
|
+
|
|
30
|
+
@CliDebugIpcFlag()
|
|
31
|
+
debugIpc?: boolean;
|
|
32
|
+
|
|
33
|
+
finalize(): void {
|
|
22
34
|
if (this.port) {
|
|
23
35
|
process.env.WEB_HTTP_PORT = `${this.port}`;
|
|
24
36
|
}
|
|
@@ -1,16 +1,11 @@
|
|
|
1
|
-
import type { Readable } from 'node:stream';
|
|
2
|
-
import { buffer } from 'node:stream/consumers';
|
|
3
|
-
|
|
4
1
|
import { Inject, Injectable } from '@travetto/di';
|
|
5
2
|
import { type WebFilterContext, WebResponse, type WebDispatcher, WebBodyUtil } from '@travetto/web';
|
|
6
|
-
import { castTo } from '@travetto/runtime';
|
|
3
|
+
import { BinaryUtil, castTo } from '@travetto/runtime';
|
|
7
4
|
|
|
8
5
|
import { WebTestDispatchUtil } from '@travetto/web/support/test/dispatch-util.ts';
|
|
9
6
|
|
|
10
7
|
import type { WebHttpConfig } from '../../src/config.ts';
|
|
11
8
|
|
|
12
|
-
const toBuffer = (src: Buffer | Readable) => Buffer.isBuffer(src) ? src : buffer(src);
|
|
13
|
-
|
|
14
9
|
/**
|
|
15
10
|
* Support for invoking http requests against the server
|
|
16
11
|
*/
|
|
@@ -23,7 +18,9 @@ export class FetchWebDispatcher implements WebDispatcher {
|
|
|
23
18
|
async dispatch({ request }: WebFilterContext): Promise<WebResponse> {
|
|
24
19
|
const baseRequest = await WebTestDispatchUtil.applyRequestBody(request);
|
|
25
20
|
const finalPath = WebTestDispatchUtil.buildPath(baseRequest);
|
|
26
|
-
const body: RequestInit['body'] = WebBodyUtil.
|
|
21
|
+
const body: RequestInit['body'] = WebBodyUtil.isRawBinary(request.body) ?
|
|
22
|
+
await BinaryUtil.toBinaryArray(request.body) :
|
|
23
|
+
castTo(request.body);
|
|
27
24
|
const { context: { httpMethod: method }, headers } = request;
|
|
28
25
|
|
|
29
26
|
const response = await fetch(
|
|
@@ -33,7 +30,7 @@ export class FetchWebDispatcher implements WebDispatcher {
|
|
|
33
30
|
|
|
34
31
|
return await WebTestDispatchUtil.finalizeResponseBody(
|
|
35
32
|
new WebResponse({
|
|
36
|
-
body:
|
|
33
|
+
body: await response.arrayBuffer(),
|
|
37
34
|
context: { httpStatusCode: response.status },
|
|
38
35
|
headers: response.headers
|
|
39
36
|
})
|