cdk-local 0.147.16 → 0.147.18
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/cli.js +2 -2
- package/dist/index.js +1 -1
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +1 -1
- package/dist/local-studio-BBA_8Xvk.d.ts.map +1 -1
- package/dist/{local-studio-BJxBmC75.js → local-studio-BIHN-Erp.js} +194 -32
- package/dist/local-studio-BIHN-Erp.js.map +1 -0
- package/package.json +1 -1
- package/dist/local-studio-BJxBmC75.js.map +0 -1
|
@@ -8102,6 +8102,136 @@ function extractHashFromImageUri(imageUri) {
|
|
|
8102
8102
|
return /:([a-f0-9]{8,})$/.exec(imageUri)?.[1];
|
|
8103
8103
|
}
|
|
8104
8104
|
|
|
8105
|
+
//#endregion
|
|
8106
|
+
//#region src/utils/url-authority.ts
|
|
8107
|
+
/**
|
|
8108
|
+
* Compose the authority component of a URL from a host and a port.
|
|
8109
|
+
*
|
|
8110
|
+
* Every local serve prints an endpoint banner, and several of those banners
|
|
8111
|
+
* are MACHINE-PARSED — `cdkl studio` reads them to learn where to point its
|
|
8112
|
+
* capture proxy (`local/studio-serve-manager`'s `readyRe` /
|
|
8113
|
+
* `parsePublishedHostEndpoint`), then resolves the result with `new URL(...)`
|
|
8114
|
+
* before it will forward anything there. So an authority that the WHATWG
|
|
8115
|
+
* parser rejects is not a cosmetic log defect: the serve is refused.
|
|
8116
|
+
*
|
|
8117
|
+
* The one shape that used to be composed wrong is an IPv6 literal. RFC 3986
|
|
8118
|
+
* 3.2.2 requires it to be bracketed inside an authority, so a bare
|
|
8119
|
+
* `${host}:${port}` turns `--container-host ::` into `http://:::8080`, which
|
|
8120
|
+
* is not a URL — while the IPv4 wildcard `0.0.0.0`, the same intention spelled
|
|
8121
|
+
* differently, works. Issue go-to-k/cdk-local#599.
|
|
8122
|
+
*
|
|
8123
|
+
* The detection is mechanical rather than a list of known values: a colon is
|
|
8124
|
+
* forbidden in both a registered name and an IPv4 address, so a host carrying
|
|
8125
|
+
* one is an IPv6 literal — PROVIDED the rest of it could be one, which is a
|
|
8126
|
+
* character-class test (hex digits, `:`, and `.` for the IPv4-mapped form)
|
|
8127
|
+
* rather than an enumeration. The qualifier is load-bearing rather than
|
|
8128
|
+
* pedantry: `buildRedirectLocation` fills its host from an ALB `#{host}`
|
|
8129
|
+
* template or a configured literal, so a CRLF-injection attempt reaches this
|
|
8130
|
+
* function AS-IS — `example.test\r\nx-injected: yes`, with the CR/LF still in
|
|
8131
|
+
* it, because `front-door-server` sanitises the Location only AFTER building
|
|
8132
|
+
* it. Either way it is a colon in something that is not an address and must
|
|
8133
|
+
* pass through untouched rather than gain brackets it never had. (CR and LF
|
|
8134
|
+
* are outside the character class by construction, so the raw and flattened
|
|
8135
|
+
* spellings classify identically — but the raw one is what actually arrives.)
|
|
8136
|
+
* Caught by `front-door-server.test.ts`'s raw-socket injection case.
|
|
8137
|
+
*/
|
|
8138
|
+
/**
|
|
8139
|
+
* A host that could be an IPv6 literal: hex digits, `:` separators, and `.`
|
|
8140
|
+
* for the IPv4-mapped form (`::ffff:127.0.0.1`). Deliberately NOT a full
|
|
8141
|
+
* grammar — the job is to separate "an address" from "not an address", and
|
|
8142
|
+
* validating an address that has already been bound to is not this function's
|
|
8143
|
+
* business.
|
|
8144
|
+
*/
|
|
8145
|
+
const IPV6_LITERAL_CHARS = /^[0-9A-Fa-f:.]+$/;
|
|
8146
|
+
/**
|
|
8147
|
+
* Render `host` as it must appear inside a URL authority.
|
|
8148
|
+
*
|
|
8149
|
+
* - An IPv6 literal is bracketed, in either case (`FE80::1` -> `[FE80::1]`).
|
|
8150
|
+
* - An already-bracketed literal comes back bracketed exactly once, so the
|
|
8151
|
+
* function is idempotent: `[::1]` never becomes `[[::1]]`. That matters
|
|
8152
|
+
* because a caller often feeds back a `URL.hostname`, which is ALREADY
|
|
8153
|
+
* bracketed.
|
|
8154
|
+
* - A zone id (`fe80::1%en0`) is DROPPED, keeping `[fe80::1]`. No URL parser
|
|
8155
|
+
* accepts one — Node's `new URL` throws on both the raw `%en0` and the
|
|
8156
|
+
* percent-encoded `%25en0` — and a zone id is a host-local interface
|
|
8157
|
+
* selector that carries no meaning for whoever reads the banner. Emitting
|
|
8158
|
+
* an authority nothing can parse is the exact failure this helper exists to
|
|
8159
|
+
* prevent, so the scope is dropped rather than propagated. The brackets are
|
|
8160
|
+
* removed BEFORE that decision, so `[fe80::1%en0]` is stripped too — an
|
|
8161
|
+
* early return on "already bracketed" would have waved the one input that
|
|
8162
|
+
* is both bracketed and unparseable straight through.
|
|
8163
|
+
* - Everything else (IPv4 literal, registered name, the empty string, and a
|
|
8164
|
+
* colon-bearing string that is not an address) is returned untouched.
|
|
8165
|
+
*/
|
|
8166
|
+
function formatHostForAuthority(host) {
|
|
8167
|
+
const inner = host.length > 1 && host.startsWith("[") && host.endsWith("]") ? host.slice(1, -1) : host;
|
|
8168
|
+
if (!inner.includes(":")) return host;
|
|
8169
|
+
const zoneAt = inner.indexOf("%");
|
|
8170
|
+
const literal = zoneAt === -1 ? inner : inner.slice(0, zoneAt);
|
|
8171
|
+
if (!IPV6_LITERAL_CHARS.test(literal)) return host;
|
|
8172
|
+
return `[${literal}]`;
|
|
8173
|
+
}
|
|
8174
|
+
/**
|
|
8175
|
+
* Compose `<host>:<port>` for use inside a URL, bracketing an IPv6 literal.
|
|
8176
|
+
*
|
|
8177
|
+
* An empty `host` is passed through as-is rather than substituted: the helper
|
|
8178
|
+
* composes an authority, it does not invent a host, and a caller that has no
|
|
8179
|
+
* host has a bug of its own. The result (`:8080`) does not parse, which is the
|
|
8180
|
+
* honest rendering of that state.
|
|
8181
|
+
*/
|
|
8182
|
+
function formatAuthority(host, port) {
|
|
8183
|
+
return `${formatHostForAuthority(host)}:${port}`;
|
|
8184
|
+
}
|
|
8185
|
+
/**
|
|
8186
|
+
* Read the HOST out of an authority (`<host>` or `<host>:<port>`), returning
|
|
8187
|
+
* it BARE — an IPv6 literal comes back without its brackets, ready to be
|
|
8188
|
+
* handed straight back to {@link formatAuthority}.
|
|
8189
|
+
*
|
|
8190
|
+
* The inverse of {@link formatAuthority}, and it exists for the same reason:
|
|
8191
|
+
* `authority.split(':')[0]` is the obvious thing to write and it is wrong for
|
|
8192
|
+
* exactly one input. A conforming client sends `Host: [::1]:8080` (measured —
|
|
8193
|
+
* see `tests/unit/local/ipv6-host-header.test.ts`), and splitting that on the
|
|
8194
|
+
* first colon yields `'['`, so an ALB `#{host}` substitution built from it
|
|
8195
|
+
* produced `http://[:8080/...`. Issue go-to-k/cdk-local#599.
|
|
8196
|
+
*
|
|
8197
|
+
* # It refuses rather than guesses — on BOTH arms
|
|
8198
|
+
*
|
|
8199
|
+
* This is an attacker-reachable parser: the request `Host` header feeds an
|
|
8200
|
+
* ALB `#{host}` substitution, and whatever comes back is composed into a
|
|
8201
|
+
* redirect `Location`. So a malformed authority yields the empty string
|
|
8202
|
+
* rather than the fragment that happens to be readable, on either branch.
|
|
8203
|
+
*
|
|
8204
|
+
* BRACKETED — read to the closing `]`, and only when the value is
|
|
8205
|
+
* well-formed: there must BE a closing bracket, and what follows it must be
|
|
8206
|
+
* empty or `:<digits>`. Guessing here is the worse of the two directions,
|
|
8207
|
+
* because the guess PARSES: `[evil.example` (no closing bracket) would come
|
|
8208
|
+
* back as `evil.example`, turning a half-named host into a valid `Location`
|
|
8209
|
+
* the client would follow, where the malformed input should have produced
|
|
8210
|
+
* nothing. `[a:b]junk` would silently drop its trailing junk, and `[x:y`
|
|
8211
|
+
* would return a multi-colon value as a host — the very thing the other arm
|
|
8212
|
+
* refuses.
|
|
8213
|
+
*
|
|
8214
|
+
* UNBRACKETED — the text before its single `:`. Two or more colons yields
|
|
8215
|
+
* the empty string: it is not a shape any conforming client sends (Node
|
|
8216
|
+
* brackets — measured in `tests/unit/local/ipv6-host-header.test.ts`), it has
|
|
8217
|
+
* no unambiguous split, and returning the leading fragment would hand a
|
|
8218
|
+
* caller a host that is not the one named. `split(':')[0]` did exactly that —
|
|
8219
|
+
* `fe80::1:8080` came back as `'fe80'`.
|
|
8220
|
+
*/
|
|
8221
|
+
function hostFromAuthority(authority) {
|
|
8222
|
+
if (authority.startsWith("[")) {
|
|
8223
|
+
const close = authority.indexOf("]");
|
|
8224
|
+
if (close === -1) return "";
|
|
8225
|
+
const afterBracket = authority.slice(close + 1);
|
|
8226
|
+
if (afterBracket !== "" && !/^:\d+$/.test(afterBracket)) return "";
|
|
8227
|
+
return authority.slice(1, close);
|
|
8228
|
+
}
|
|
8229
|
+
const firstColon = authority.indexOf(":");
|
|
8230
|
+
if (firstColon === -1) return authority;
|
|
8231
|
+
if (authority.includes(":", firstColon + 1)) return "";
|
|
8232
|
+
return authority.slice(0, firstColon);
|
|
8233
|
+
}
|
|
8234
|
+
|
|
8105
8235
|
//#endregion
|
|
8106
8236
|
//#region src/local/rie-client.ts
|
|
8107
8237
|
/**
|
|
@@ -8168,7 +8298,7 @@ async function waitForRieReady(host, port, timeoutMs = 5e3) {
|
|
|
8168
8298
|
await setTimeout$1(100);
|
|
8169
8299
|
}
|
|
8170
8300
|
const tail = lastError instanceof Error ? `: ${lastError.message}` : "";
|
|
8171
|
-
throw new Error(`RIE did not become ready on ${host
|
|
8301
|
+
throw new Error(`RIE did not become ready on ${formatAuthority(host, port)} within ${timeoutMs}ms${tail}. The container may have exited early — check 'docker logs' output.`);
|
|
8172
8302
|
}
|
|
8173
8303
|
/**
|
|
8174
8304
|
* Issue a tiny HTTP request to confirm RIE's HTTP listener is up (not
|
|
@@ -8180,7 +8310,7 @@ async function httpProbe(host, port, timeoutMs) {
|
|
|
8180
8310
|
const controller = new AbortController();
|
|
8181
8311
|
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
8182
8312
|
try {
|
|
8183
|
-
await (await fetch(`http://${host
|
|
8313
|
+
await (await fetch(`http://${formatAuthority(host, port)}/`, {
|
|
8184
8314
|
method: "POST",
|
|
8185
8315
|
headers: { "Content-Type": "application/json" },
|
|
8186
8316
|
body: "{}",
|
|
@@ -8222,7 +8352,7 @@ function isTransientNetworkError$3(err) {
|
|
|
8222
8352
|
* the timeout in v1, but it's the right ballpark.
|
|
8223
8353
|
*/
|
|
8224
8354
|
async function invokeRie(host, port, event, timeoutMs) {
|
|
8225
|
-
const url = `http://${host
|
|
8355
|
+
const url = `http://${formatAuthority(host, port)}${INVOKE_PATH}`;
|
|
8226
8356
|
const body = JSON.stringify(event ?? {});
|
|
8227
8357
|
const controller = new AbortController();
|
|
8228
8358
|
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
@@ -8359,7 +8489,7 @@ const STREAM_BODY_MAX_BYTES = 100 * 1024 * 1024;
|
|
|
8359
8489
|
* Readable is destroyed with a clear error when the cap trips.
|
|
8360
8490
|
*/
|
|
8361
8491
|
async function invokeRieStreaming(host, port, event, timeoutMs) {
|
|
8362
|
-
const url = `http://${host
|
|
8492
|
+
const url = `http://${formatAuthority(host, port)}${INVOKE_PATH}`;
|
|
8363
8493
|
const body = JSON.stringify(event ?? {});
|
|
8364
8494
|
const controller = new AbortController();
|
|
8365
8495
|
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
@@ -8747,7 +8877,7 @@ function parseConnectionsPath(url) {
|
|
|
8747
8877
|
* Issue #537 item 7.
|
|
8748
8878
|
*/
|
|
8749
8879
|
function buildMgmtEndpointEnvUrl(host, port, stage) {
|
|
8750
|
-
return `http://${host
|
|
8880
|
+
return `http://${formatAuthority(host, port)}/${stage}`;
|
|
8751
8881
|
}
|
|
8752
8882
|
/**
|
|
8753
8883
|
* `decodeURIComponent` throws `URIError` on malformed input
|
|
@@ -16352,6 +16482,24 @@ async function writeProfileCredentialsFile(profileName, creds) {
|
|
|
16352
16482
|
|
|
16353
16483
|
//#endregion
|
|
16354
16484
|
//#region src/cli/commands/local-start-api.ts
|
|
16485
|
+
/**
|
|
16486
|
+
* The `Server listening on <url> (<label>)` ready banner, terminated with a
|
|
16487
|
+
* newline.
|
|
16488
|
+
*
|
|
16489
|
+
* D8.4 — load-bearing, and the most machine-parsed line in the repo: several
|
|
16490
|
+
* integ fixtures grep the prefix and extract the port from it, and
|
|
16491
|
+
* `cdkl studio` matches it with `SERVE_SPECS.api.readyRe` and then resolves
|
|
16492
|
+
* the captured URL with `new URL(...)` before it will front the serve with a
|
|
16493
|
+
* capture proxy. An authority the WHATWG parser rejects therefore does not
|
|
16494
|
+
* merely read badly — the studio serve is refused (issue #599).
|
|
16495
|
+
*
|
|
16496
|
+
* Exported so that contract has a unit test at the EMITTER. Both banner sites
|
|
16497
|
+
* live inside the long-running boot function, which has no cheap test seam,
|
|
16498
|
+
* so without this the only emitter-side coverage was the source fence.
|
|
16499
|
+
*/
|
|
16500
|
+
function formatServerListeningBanner(scheme, host, port, pathSuffix, label) {
|
|
16501
|
+
return `Server listening on ${scheme}://${formatAuthority(host, port)}${pathSuffix} (${label})\n`;
|
|
16502
|
+
}
|
|
16355
16503
|
async function localStartApiCommand(targets, options, extraStateProviders) {
|
|
16356
16504
|
const logger = getLogger();
|
|
16357
16505
|
if (options.verbose) logger.setLevel("debug");
|
|
@@ -16660,10 +16808,10 @@ async function localStartApiCommand(targets, options, extraStateProviders) {
|
|
|
16660
16808
|
warnUnsupportedRoutes(allRoutes, logger);
|
|
16661
16809
|
warnSsrfRiskyIntegrations(allRoutes, logger);
|
|
16662
16810
|
logger.info(`Per-Lambda concurrency: ${perLambdaConcurrency} (override with --per-lambda-concurrency)`);
|
|
16663
|
-
for (const { group, server } of servers) process.stdout.write(
|
|
16811
|
+
for (const { group, server } of servers) process.stdout.write(formatServerListeningBanner(server.scheme, server.host, server.port, "", group.displayName));
|
|
16664
16812
|
for (const ws of wsServers) {
|
|
16665
16813
|
const scheme = ws.server.scheme === "https" ? "wss" : "ws";
|
|
16666
|
-
process.stdout.write(
|
|
16814
|
+
process.stdout.write(formatServerListeningBanner(scheme, ws.server.host, ws.server.port, ws.apiPath, `${ws.api.apiLogicalId} (WebSocket API)`));
|
|
16667
16815
|
}
|
|
16668
16816
|
process.stdout.write("^C to stop and clean up containers.\n");
|
|
16669
16817
|
let watcher;
|
|
@@ -17781,7 +17929,7 @@ function filterSpecsForGroup(group, allSpecs) {
|
|
|
17781
17929
|
*/
|
|
17782
17930
|
function printPerServerRouteTables(servers) {
|
|
17783
17931
|
for (const { group, server } of servers) {
|
|
17784
|
-
process.stdout.write(`\n${group.displayName} (http://${server.host
|
|
17932
|
+
process.stdout.write(`\n${group.displayName} (http://${formatAuthority(server.host, server.port)})\n`);
|
|
17785
17933
|
printRouteTable(group.routes);
|
|
17786
17934
|
}
|
|
17787
17935
|
}
|
|
@@ -19254,7 +19402,7 @@ async function waitForAgentCorePing(host, port, timeoutMs = 3e4) {
|
|
|
19254
19402
|
await setTimeout$1(150);
|
|
19255
19403
|
}
|
|
19256
19404
|
const tail = lastDetail ? `: ${lastDetail}` : "";
|
|
19257
|
-
throw new Error(`AgentCore agent did not become ready on ${host
|
|
19405
|
+
throw new Error(`AgentCore agent did not become ready on ${formatAuthority(host, port)} within ${timeoutMs}ms${tail}. The container may have exited early or may not serve GET ${PING_PATH} — check 'docker logs' output.`);
|
|
19258
19406
|
}
|
|
19259
19407
|
/**
|
|
19260
19408
|
* Issue `GET /ping`. Returns the HTTP status on any response, undefined on
|
|
@@ -19265,7 +19413,7 @@ async function pingProbe(host, port, timeoutMs) {
|
|
|
19265
19413
|
const controller = new AbortController();
|
|
19266
19414
|
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
19267
19415
|
try {
|
|
19268
|
-
const response = await fetch(`http://${host
|
|
19416
|
+
const response = await fetch(`http://${formatAuthority(host, port)}${PING_PATH}`, {
|
|
19269
19417
|
method: "GET",
|
|
19270
19418
|
signal: controller.signal
|
|
19271
19419
|
});
|
|
@@ -19301,7 +19449,7 @@ async function waitForAgentCoreHttpReady(host, port, path, timeoutMs = 3e4) {
|
|
|
19301
19449
|
const controller = new AbortController();
|
|
19302
19450
|
const timer = setTimeout(() => controller.abort(), 1e3);
|
|
19303
19451
|
try {
|
|
19304
|
-
await (await fetch(`http://${host
|
|
19452
|
+
await (await fetch(`http://${formatAuthority(host, port)}${path}`, {
|
|
19305
19453
|
method: "POST",
|
|
19306
19454
|
headers: { "content-type": "application/json" },
|
|
19307
19455
|
body: "{}",
|
|
@@ -19317,7 +19465,7 @@ async function waitForAgentCoreHttpReady(host, port, path, timeoutMs = 3e4) {
|
|
|
19317
19465
|
await setTimeout$1(150);
|
|
19318
19466
|
}
|
|
19319
19467
|
const tail = lastDetail ? `: ${lastDetail}` : "";
|
|
19320
|
-
throw new Error(`AgentCore agent did not become ready on ${host
|
|
19468
|
+
throw new Error(`AgentCore agent did not become ready on ${formatAuthority(host, port)} within ${timeoutMs}ms${tail}. The container may have exited early or may not serve POST ${path} — check 'docker logs' output.`);
|
|
19321
19469
|
}
|
|
19322
19470
|
/**
|
|
19323
19471
|
* `fetch()` failures during container boot manifest as a generic
|
|
@@ -19345,7 +19493,7 @@ function isTransientNetworkError$2(err) {
|
|
|
19345
19493
|
* a missing sink) is buffered into `raw` and returned verbatim.
|
|
19346
19494
|
*/
|
|
19347
19495
|
async function invokeAgentCore(host, port, event, options) {
|
|
19348
|
-
const url = `http://${host
|
|
19496
|
+
const url = `http://${formatAuthority(host, port)}${INVOCATIONS_PATH}`;
|
|
19349
19497
|
const body = JSON.stringify(event ?? {});
|
|
19350
19498
|
const controller = new AbortController();
|
|
19351
19499
|
const timer = setTimeout(() => controller.abort(), options.timeoutMs);
|
|
@@ -19452,7 +19600,7 @@ async function signAgentCoreInvocation(opts) {
|
|
|
19452
19600
|
path: opts.path,
|
|
19453
19601
|
headers: {
|
|
19454
19602
|
"Content-Type": "application/json",
|
|
19455
|
-
Host:
|
|
19603
|
+
Host: formatAuthority(opts.host, opts.port),
|
|
19456
19604
|
[AGENTCORE_SESSION_ID_HEADER]: opts.sessionId
|
|
19457
19605
|
},
|
|
19458
19606
|
body: opts.body
|
|
@@ -19513,7 +19661,7 @@ const PROTOCOL_VERSION_HEADER = "MCP-Protocol-Version";
|
|
|
19513
19661
|
*/
|
|
19514
19662
|
async function mcpInvokeOnce(host, port, request, options = {}) {
|
|
19515
19663
|
const fetchImpl = options.fetchImpl ?? fetch;
|
|
19516
|
-
const url = `http://${host
|
|
19664
|
+
const url = `http://${formatAuthority(host, port)}${MCP_PATH}`;
|
|
19517
19665
|
const requestTimeoutMs = options.requestTimeoutMs ?? 12e4;
|
|
19518
19666
|
const sessionId = await initializeWithRetry(fetchImpl, url, options.readyTimeoutMs ?? 3e4);
|
|
19519
19667
|
await postMcp(fetchImpl, url, {
|
|
@@ -19689,7 +19837,7 @@ const A2A_PATH = "/";
|
|
|
19689
19837
|
*/
|
|
19690
19838
|
async function a2aInvokeOnce(host, port, request, options = {}) {
|
|
19691
19839
|
const fetchImpl = options.fetchImpl ?? fetch;
|
|
19692
|
-
const url = `http://${host
|
|
19840
|
+
const url = `http://${formatAuthority(host, port)}${"/"}`;
|
|
19693
19841
|
const requestTimeoutMs = options.requestTimeoutMs ?? 12e4;
|
|
19694
19842
|
const readyTimeoutMs = options.readyTimeoutMs ?? 3e4;
|
|
19695
19843
|
const message = await postWithReadyRetry(fetchImpl, url, {
|
|
@@ -19801,7 +19949,7 @@ function decodeWsFrame(data) {
|
|
|
19801
19949
|
* BridgeAgentCoreWsOptions.onMessage}.
|
|
19802
19950
|
*/
|
|
19803
19951
|
function bridgeAgentCoreWs(host, port, options) {
|
|
19804
|
-
const ws = new (options.webSocketImpl ?? WebSocket)(`ws://${host
|
|
19952
|
+
const ws = new (options.webSocketImpl ?? WebSocket)(`ws://${formatAuthority(host, port)}${WS_PATH}`, { headers: {
|
|
19805
19953
|
[AGENTCORE_SESSION_ID_HEADER]: options.sessionId,
|
|
19806
19954
|
...options.authorization && { Authorization: options.authorization }
|
|
19807
19955
|
} });
|
|
@@ -19862,7 +20010,7 @@ function bridgeAgentCoreWs(host, port, options) {
|
|
|
19862
20010
|
*/
|
|
19863
20011
|
async function invokeAgentCoreWs(host, port, event, options) {
|
|
19864
20012
|
const Impl = options.webSocketImpl ?? WebSocket;
|
|
19865
|
-
const url = `ws://${host
|
|
20013
|
+
const url = `ws://${formatAuthority(host, port)}${WS_PATH}`;
|
|
19866
20014
|
const body = JSON.stringify(event ?? {});
|
|
19867
20015
|
return new Promise((resolve, reject) => {
|
|
19868
20016
|
const ws = new Impl(url, { headers: {
|
|
@@ -22364,7 +22512,7 @@ function buildDockerRunArgs(opts) {
|
|
|
22364
22512
|
const hostPort = opts.hostPortOverrides?.[pm.containerPort] ?? declaredHostPort;
|
|
22365
22513
|
const overridden = hostPort !== declaredHostPort;
|
|
22366
22514
|
const overrideNote = opts.autoRemappedContainerPorts?.has(pm.containerPort) ?? false ? " (privileged-port auto-remap)" : overridden ? " (--host-port override)" : "";
|
|
22367
|
-
getLogger().child("ecs").info(`Container '${container.name}' container port ${pm.containerPort} published on ${containerHost
|
|
22515
|
+
getLogger().child("ecs").info(`Container '${container.name}' container port ${pm.containerPort} published on ${formatAuthority(containerHost, hostPort)}${overrideNote}. Reach it at ${formatAuthority(containerHost, hostPort)}.`);
|
|
22368
22516
|
args.push("-p", `${containerHost}:${hostPort}:${pm.containerPort}/${pm.protocol}`);
|
|
22369
22517
|
publishedEndpoints.push({
|
|
22370
22518
|
containerName: container.name,
|
|
@@ -24790,7 +24938,7 @@ function buildRedirectLocation(action, req, listenerPort, scheme = "http") {
|
|
|
24790
24938
|
const rawHost = req.headers["host"];
|
|
24791
24939
|
const placeholders = {
|
|
24792
24940
|
protocol: scheme,
|
|
24793
|
-
host: ((Array.isArray(rawHost) ? rawHost[0] : rawHost) ?? "")
|
|
24941
|
+
host: hostFromAuthority((Array.isArray(rawHost) ? rawHost[0] : rawHost) ?? ""),
|
|
24794
24942
|
port: String(listenerPort),
|
|
24795
24943
|
path: reqPath.replace(/^\//, ""),
|
|
24796
24944
|
query: reqQuery
|
|
@@ -24801,7 +24949,7 @@ function buildRedirectLocation(action, req, listenerPort, scheme = "http") {
|
|
|
24801
24949
|
const port = action.port ? fill(action.port) : placeholders["port"];
|
|
24802
24950
|
const path = fill(action.path ?? "/#{path}");
|
|
24803
24951
|
const query = fill(action.query ?? "#{query}");
|
|
24804
|
-
return `${protocol}://${protocol === "http" && port === "80" || protocol === "https" && port === "443" || port === "" ? host :
|
|
24952
|
+
return `${protocol}://${protocol === "http" && port === "80" || protocol === "https" && port === "443" || port === "" ? formatHostForAuthority(host) : formatAuthority(host, port)}${path.startsWith("/") ? path : `/${path}`}${query ? `?${query}` : ""}`;
|
|
24805
24953
|
}
|
|
24806
24954
|
/** Synthesize an ALB-style fixed-response. */
|
|
24807
24955
|
function writeFixedResponse(res, action) {
|
|
@@ -27462,7 +27610,7 @@ async function buildFrontDoor(plan, options, logger, extraStateProviders) {
|
|
|
27462
27610
|
} else throw bindErr;
|
|
27463
27611
|
}
|
|
27464
27612
|
servers.push(server);
|
|
27465
|
-
logger.info(`ALB front-door: ${server.scheme}://${server.host
|
|
27613
|
+
logger.info(`ALB front-door: ${server.scheme}://${formatAuthority(server.host, server.port)} (listener port ${listener.listenerPort})`);
|
|
27466
27614
|
if (degradedHttps) logger.warn(`listener port ${listener.listenerPort} is HTTPS in the cloud but serving HTTP locally (X-Forwarded-Proto: https preserved). Pass --tls to terminate TLS locally with a self-signed or user-supplied cert.`);
|
|
27467
27615
|
if (listener.defaultAction) logger.info(` default -> ${describeAction(listener.defaultAction)}`);
|
|
27468
27616
|
for (const r of [...listener.rules].sort((a, b) => a.priority - b.priority)) logger.info(` ${describeConditions(r)} (priority ${r.priority}) -> ${describeAction(r.action)}`);
|
|
@@ -27724,12 +27872,12 @@ function logEndpointsBanner(perTarget, frontDoorServers, logger) {
|
|
|
27724
27872
|
for (const ep of endpoints) {
|
|
27725
27873
|
const scheme = ep.protocol.toLowerCase() === "udp" ? "udp" : "http";
|
|
27726
27874
|
const override = ep.overridden ? " (--host-port override)" : "";
|
|
27727
|
-
lines.push(` ${ep.containerName} container port ${ep.containerPort}/${ep.protocol} -> ${scheme}://${ep.host
|
|
27875
|
+
lines.push(` ${ep.containerName} container port ${ep.containerPort}/${ep.protocol} -> ${scheme}://${formatAuthority(ep.host, ep.hostPort)}${override}`);
|
|
27728
27876
|
}
|
|
27729
27877
|
}
|
|
27730
27878
|
if (frontDoorServers.length > 0) {
|
|
27731
27879
|
lines.push(" ALB front-door");
|
|
27732
|
-
for (const s of frontDoorServers) lines.push(` ${s.scheme}://${s.host
|
|
27880
|
+
for (const s of frontDoorServers) lines.push(` ${s.scheme}://${formatAuthority(s.host, s.port)}`);
|
|
27733
27881
|
}
|
|
27734
27882
|
if (lines.length === 0) return;
|
|
27735
27883
|
logger.info("Service endpoints:");
|
|
@@ -30607,7 +30755,7 @@ async function startCloudFrontServer(options) {
|
|
|
30607
30755
|
}, handler) : createServer$1(handler);
|
|
30608
30756
|
const port = await listen(server, options.host, options.port);
|
|
30609
30757
|
return {
|
|
30610
|
-
url: `${scheme}://${options.host
|
|
30758
|
+
url: `${scheme}://${formatAuthority(options.host, port)}`,
|
|
30611
30759
|
port,
|
|
30612
30760
|
scheme,
|
|
30613
30761
|
update(distribution) {
|
|
@@ -31884,7 +32032,7 @@ function startAgentCoreWsBridge(config) {
|
|
|
31884
32032
|
httpServer.on("error", (err) => getLogger().debug(`agentcore-ws bridge server error: ${err.message}`));
|
|
31885
32033
|
const port = httpServer.address().port;
|
|
31886
32034
|
resolve({
|
|
31887
|
-
url: `ws://${host
|
|
32035
|
+
url: `ws://${formatAuthority(host, port)}${attached.path}`,
|
|
31888
32036
|
port,
|
|
31889
32037
|
close: () => new Promise((res) => {
|
|
31890
32038
|
attached.close().then(() => httpServer.close(() => res()));
|
|
@@ -32057,8 +32205,8 @@ function startAgentCoreHttpServer(config) {
|
|
|
32057
32205
|
httpServer.on("error", (err) => getLogger().debug(`agentcore http serve server error: ${err.message}`));
|
|
32058
32206
|
const port = httpServer.address().port;
|
|
32059
32207
|
resolve({
|
|
32060
|
-
httpUrl: `http://${host
|
|
32061
|
-
...bridge && { wsUrl: `ws://${host
|
|
32208
|
+
httpUrl: `http://${formatAuthority(host, port)}`,
|
|
32209
|
+
...bridge && { wsUrl: `ws://${formatAuthority(host, port)}${bridge.path}` },
|
|
32062
32210
|
port,
|
|
32063
32211
|
setContainerPort: (newPort) => {
|
|
32064
32212
|
config.containerPort = newPort;
|
|
@@ -36256,7 +36404,7 @@ async function startStudioServer(options) {
|
|
|
36256
36404
|
const server = createServer$1((req, res) => handleRequest(req, res, options.bus, html, () => targetsJson, options, instanceId));
|
|
36257
36405
|
const boundPort = await listenWithBump(server, host, options.port, maxBump);
|
|
36258
36406
|
return {
|
|
36259
|
-
url: `http://${host
|
|
36407
|
+
url: `http://${formatAuthority(host, boundPort)}`,
|
|
36260
36408
|
port: boundPort,
|
|
36261
36409
|
close: () => new Promise((resolveClose, reject) => {
|
|
36262
36410
|
server.close((err) => err ? reject(err) : resolveClose());
|
|
@@ -37271,7 +37419,7 @@ function startStudioProxy(config) {
|
|
|
37271
37419
|
server.removeListener("error", reject);
|
|
37272
37420
|
const port = server.address().port;
|
|
37273
37421
|
resolve({
|
|
37274
|
-
url: `http://${host
|
|
37422
|
+
url: `http://${formatAuthority(host, port)}`,
|
|
37275
37423
|
port,
|
|
37276
37424
|
close: () => new Promise((resolveClose, rejectClose) => {
|
|
37277
37425
|
for (const sock of upgradeSockets) sock.destroy();
|
|
@@ -37413,6 +37561,12 @@ const SERVE_SPECS = {
|
|
|
37413
37561
|
}
|
|
37414
37562
|
};
|
|
37415
37563
|
/**
|
|
37564
|
+
* The `ecs-task-runner` replica publish banner, with its authority captured.
|
|
37565
|
+
* The authority is a dotted-quad IPv4 or a bracketed IPv6 literal, each
|
|
37566
|
+
* followed by `:<port>`.
|
|
37567
|
+
*/
|
|
37568
|
+
const PUBLISHED_ENDPOINT_RE = /^Container '[^']*' container port \d+ published on ((?:\d{1,3}(?:\.\d{1,3}){3}|\[[0-9A-Fa-f:.]{2,45}\]):\d+)/;
|
|
37569
|
+
/**
|
|
37416
37570
|
* Parse an auto-published replica host endpoint from an `ecs` serve child's
|
|
37417
37571
|
* stdout (issue #392). `start-service` publishes each replica's declared
|
|
37418
37572
|
* container port on the host — auto-remapping a privileged port (< 1024) to a
|
|
@@ -37432,9 +37586,17 @@ const SERVE_SPECS = {
|
|
|
37432
37586
|
* The loopback bound is applied by the CALLER (a parsed endpoint is still only
|
|
37433
37587
|
* adopted when {@link normalizeLocalUpstream} accepts it), so this stays a pure
|
|
37434
37588
|
* reader of the banner.
|
|
37589
|
+
*
|
|
37590
|
+
* The authority half accepts a BRACKETED IPv6 literal alongside the dotted
|
|
37591
|
+
* quad (issue go-to-k/cdk-local#599). `ecs-task-runner` composes that banner
|
|
37592
|
+
* through `formatAuthority`, so `--container-host ::1` prints
|
|
37593
|
+
* `[::1]:54321` — an emitter that brackets and a reader that only knows IPv4
|
|
37594
|
+
* is the same defect moved one file over. Brackets are REQUIRED here rather
|
|
37595
|
+
* than optional: a bare `::1:54321` has no unambiguous split into host and
|
|
37596
|
+
* port, and it is not what the emitter writes.
|
|
37435
37597
|
*/
|
|
37436
37598
|
function parsePublishedHostEndpoint(line) {
|
|
37437
|
-
const m =
|
|
37599
|
+
const m = PUBLISHED_ENDPOINT_RE.exec(line);
|
|
37438
37600
|
return m ? `http://${m[1]}` : void 0;
|
|
37439
37601
|
}
|
|
37440
37602
|
/**
|
|
@@ -38836,4 +38998,4 @@ function addStudioSpecificOptions(cmd) {
|
|
|
38836
38998
|
|
|
38837
38999
|
//#endregion
|
|
38838
39000
|
export { applyEdgeResponseResult as $, buildJwksUrlFromIssuer as $n, resolveCfnStackName as $r, buildCloudMapIndex as $t, startAgentCoreHttpServer as A, describeCredentialLoadFailure as Ai, classifySourceChange as An, ConnectionRegistry as Ar, addRunTaskSpecificOptions as At, idFromArn as B, buildStageMap as Bn, resolveRuntimeFileExtension as Br, resolveEcsAssumeRoleOption as Bt, addListSpecificOptions as C, resolveAgentCoreTarget as Ci, waitForAgentCorePing as Cn, tryParseStatus as Cr, parseLbPortOverrides as Ct, createLocalStartAgentCoreCommand as D, tryResolveImageFnJoin as Di, computeCodeImageTag as Dn, probeHostGatewaySupport as Dr, addStartServiceSpecificOptions as Dt, addStartAgentCoreSpecificOptions as E, substituteImagePlaceholders as Ei, buildAgentCoreCodeImage as En, HOST_GATEWAY_MIN_VERSION as Er, resolveAlbFrontDoor as Et, createLocalStartCloudFrontCommand as F, createWatchPredicates as Fn, buildDisconnectEvent as Fr, addImageOverrideOptions as Ft, classifyS3Error as G, filterRoutesByApiIdentifiers as Gn, substituteEnvVarsFromState as Gr, enforceImageOverrideOrphans as Gt, createDeployedKvsDataSource as H, resolveEnvVars$1 as Hn, EcsTaskResolutionError as Hr, runEcsServiceEmulator as Ht, normalizeKvsFileKeys as I, resolveApiTargetSubset as In, buildMessageEvent as Ir, buildEcsImageResolutionContext$1 as It, startCloudFrontServer as J, startApiServer as Jn, createLocalStateProvider as Jr, resolveImageOverrides as Jt, createS3OriginReader as K, groupRoutesByServer as Kn, substituteEnvVarsFromStateAsync as Kr, mergeForService as Kt, parseKvsFileOverrides as L, createAuthorizerCache as Ln, architectureToPlatform as Lr, ecsClusterOption as Lt, startAgentCoreWsBridge as M, resolveProfileCredentials as Mi, createLocalInvokeCommand as Mn, handleConnectionsRequest as Mr, MAX_TASKS_SUBNET_RANGE_CAP as Mt, LocalStartCloudFrontError as N, addStartApiSpecificOptions as Nn, parseConnectionsPath as Nr, addCommonEcsServiceOptions as Nt, buildAgentCoreServeAuthCheck as O, LocalInvokeBuildError as Oi, renderCodeDockerfile as On, resolveHostGatewayExtraHosts as Or, createLocalStartServiceCommand as Ot, addStartCloudFrontSpecificOptions as P, createLocalStartApiCommand as Pn, buildConnectEvent as Pr, addEcsAssumeRoleOptions as Pt, applyEdgeRequestResult as Q, buildCognitoJwksUrl as Qn, resolveCfnRegion as Qr, listPinnedTargets as Qt, parseOriginOverrides as R, createFileWatcher as Rn, buildContainerImage as Rr, parseMaxTasks as Rt, StudioEventBus as S, pickAgentCoreCandidateStack as Si, waitForAgentCoreHttpReady as Sn, selectIntegrationResponse as Sr, createLocalStartAlbCommand as St, formatTargetListing as T, formatStateRemedy as Ti, SUPPORTED_CODE_RUNTIMES as Tn, HOST_DOCKER_INTERNAL_GATEWAY as Tr, isApplicationLoadBalancer as Tt, resolveDeployedKvsArnByName as U, availableApiIdentifiers as Un, substituteAgainstState as Ur, ImageOverrideError as Ut, resolveKvsModulesForDistribution as V, materializeLayerFromArn as Vn, resolveRuntimeImage as Vr, resolveSharedSidecarCredentials as Vt, resolveDeployedOriginBucket as W, filterRoutesByApiIdentifier as Wn, substituteAgainstStateAsync as Wr, buildImageOverrideTag as Wt, serveFromStaticOrigin as X, resolveServiceIntegrationParameters as Xn, rejectExplicitCfnStackWithMultipleStacks as Xr, describePinnedImageUri as Xt, resolveErrorResponseCandidates as Y, resolveSelectionExpression as Yn, isCfnFlagPresent as Yr, runImageOverrideBuilds as Yt, serveLambdaUrlOrigin as Z, defaultCredentialsLoader as Zn, resolveCfnFallbackRegion as Zr, isLocalCdkAssetImage as Zt, filterStudioTargetGroups as _, AGENTCORE_AGUI_PROTOCOL as _i, parseSseForJsonRpc as _n, applyAuthorizerOverlay as _r, createCloudFrontModule as _t, createLocalStudioCommand as a, countTargets as ai, attachContainerLogStreamer as an, computeRequestIdentityHash as ar, describeS3OriginDomain as at, renderStudioHtml as b, AGENTCORE_RUNTIME_TYPE as bi, AGENTCORE_SESSION_ID_HEADER as bn, evaluateResponseParameters as br, addAlbSpecificOptions as bt, startStudioProxy as c, discoverWebSocketApis as ci, bridgeAgentCoreWs as cn, invokeTokenAuthorizer as cr, pickFunctionUrlLogicalIdFromOrigin as ct, createStudioDispatcher as d, parseSelectionExpressionPath as di, A2A_PATH as dn, buildCorsConfigByApiId as dr, pickTargetFunctionLogicalId as dt, CfnLocalStateProvider as ei, CloudMapRegistry as en, createJwksCache as er, buildEdgeRequestEvent as et, filterStudioCustomResources as f, webSocketApiMatchesIdentifier as fi, a2aInvokeOnce as fn, buildCorsConfigFromCloudFrontChain as fr, resolveCloudFrontDistribution as ft, annotatePinnedEcsTargets as g, AGENTCORE_A2A_PROTOCOL as gi, mcpInvokeOnce as gn, translateLambdaResponse as gr, stripCloudFrontImport as gt, annotateEcsTaskPinnedTargets as h, resolveLambdaArnIntrinsic as hi, MCP_PROTOCOL_VERSION as hn, matchRoute as hr, runViewerResponse as ht, coerceStopRequest as i, resolveSingleTarget as ii, getContainerNetworkIp as in, buildMethodArn as ir, CLOUDFRONT_DISTRIBUTION_TYPE as it, attachAgentCoreWsBridge as j, buildStsClientConfig as ji, addInvokeSpecificOptions as jn, buildMgmtEndpointEnvUrl as jr, createLocalRunTaskCommand as jt, selectServeInboundAuth as k, describeAwsFailureForWarn as ki, toCmdArgv as kn, bufferToBody as kr, serviceStrategy as kt, relayServeRequest as l, discoverWebSocketApisOrThrow as li, invokeAgentCoreWs as ln, attachAuthorizers as lr, pickKvsLogicalIdFromArn as lt, annotateAlbPinnedBackingServices as m, pickRefLogicalId as mi, MCP_PATH as mn, matchPreflight as mr, runViewerRequest as mt, coerceRunRequest as n, resolveSsmParameters as ni, SOFT_RELOAD_COMPLETION_LOG_SUFFIX as nn, verifyJwtAuthorizer as nr, edgeHeadersToHttp as nt, resolveServeBaseUrl as o, listTargets as oi, addInvokeAgentCoreSpecificOptions as on, evaluateCachedLambdaPolicy as or, extractKvsAssociations as ot, isCustomResourceLambdaTarget as p, discoverRoutes as pi, MCP_CONTAINER_PORT as pn, isFunctionUrlOacFronted as pr, compileCloudFrontFunction as pt, matchBehavior as q, readMtlsMaterialsFromDisk as qn, LocalStateSourceError as qr, parseImageOverrideFlags as qt, coerceServeRequest as r, resolveWatchConfig as ri, setShadowReadyTimeoutMs as rn, verifyJwtViaDiscovery as rr, httpHeadersToEdge as rt, createStudioServeManager as s, availableWebSocketApiIdentifiers as si, createLocalInvokeAgentCoreCommand as sn, invokeRequestAuthorizer as sr, isCloudFrontDistribution as st, addStudioSpecificOptions as t, collectSsmParameterRefs as ti, DEFAULT_SHADOW_READY_TIMEOUT_MS as tn, verifyCognitoJwt as tr, buildEdgeResponseEvent as tt, reinvoke as u, filterWebSocketApisByIdentifiers as ui, A2A_CONTAINER_PORT as un, applyCorsResponseHeaders as ur, pickLambdaEdgeFunctionLogicalId as ut, startStudioServer as v, AGENTCORE_HTTP_PROTOCOL as vi, AGENTCORE_SIGV4_SERVICE as vn, buildHttpApiV2Event as vr, createLocalFileKvsDataSource as vt, createLocalListCommand as w, derivePseudoParametersFromRegion as wi, downloadAndExtractS3Bundle as wn, VtlEvaluationError as wr, resolveAlbTarget as wt, createStudioStore as x, AgentCoreResolutionError as xi, invokeAgentCore as xn, pickResponseTemplate as xr, albStrategy as xt, toStudioTargetGroups as y, AGENTCORE_MCP_PROTOCOL as yi, signAgentCoreInvocation as yn, buildRestV1Event as yr, createUnboundCloudFrontModule as yt, resolveCloudFrontTarget as z, attachStageContext as zn, resolveRuntimeCodeMountPath as zr, parseRestartPolicy as zt };
|
|
38839
|
-
//# sourceMappingURL=local-studio-
|
|
39001
|
+
//# sourceMappingURL=local-studio-BIHN-Erp.js.map
|