unplugin-https-reverse-proxy 4.0.2 → 4.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/{chunk-JA3D5AWS.js → chunk-MD5CVZP7.js} +166 -16
- package/dist/esbuild.cjs +166 -16
- package/dist/esbuild.js +1 -1
- package/dist/index.cjs +166 -16
- package/dist/index.js +1 -1
- package/dist/nuxt.cjs +166 -16
- package/dist/nuxt.js +1 -1
- package/dist/rollup.cjs +166 -16
- package/dist/rollup.js +1 -1
- package/dist/rspack.cjs +166 -16
- package/dist/rspack.js +1 -1
- package/dist/vite.cjs +166 -16
- package/dist/vite.js +1 -1
- package/dist/webpack.cjs +166 -16
- package/dist/webpack.js +1 -1
- package/package.json +1 -1
- package/src/caddy/caddyfile.ts +1 -1
- package/src/caddy/index.ts +86 -16
- package/src/caddy/log.ts +16 -0
- package/src/caddy/tls-health.ts +142 -0
package/dist/vite.cjs
CHANGED
|
@@ -13455,7 +13455,7 @@ function validateTemplateContext(ctx) {
|
|
|
13455
13455
|
}
|
|
13456
13456
|
var caddyTemplate = `{
|
|
13457
13457
|
debug
|
|
13458
|
-
auto_https disable_redirects
|
|
13458
|
+
auto_https disable_redirects ignore_loaded_certs
|
|
13459
13459
|
}
|
|
13460
13460
|
|
|
13461
13461
|
:7601 {
|
|
@@ -13722,6 +13722,97 @@ function useCaddyConfig() {
|
|
|
13722
13722
|
};
|
|
13723
13723
|
}
|
|
13724
13724
|
|
|
13725
|
+
// src/caddy/log.ts
|
|
13726
|
+
function isCaddyReloadCancellation(line) {
|
|
13727
|
+
try {
|
|
13728
|
+
const entry = JSON.parse(line);
|
|
13729
|
+
return entry.logger === "tls" && typeof entry.error === "string" && entry.error.endsWith("context canceled");
|
|
13730
|
+
} catch {
|
|
13731
|
+
return false;
|
|
13732
|
+
}
|
|
13733
|
+
}
|
|
13734
|
+
|
|
13735
|
+
// src/caddy/tls-health.ts
|
|
13736
|
+
var import_node_tls = require("tls");
|
|
13737
|
+
function assessTlsCertificate(certificate, hostname, now = Date.now(), verifyHostname = import_node_tls.checkServerIdentity) {
|
|
13738
|
+
if (!certificate.valid_to)
|
|
13739
|
+
return { healthy: false, reason: "certificate_missing" };
|
|
13740
|
+
const expiresAt = new Date(certificate.valid_to);
|
|
13741
|
+
if (Number.isNaN(expiresAt.getTime()))
|
|
13742
|
+
return { healthy: false, reason: "certificate_invalid" };
|
|
13743
|
+
if (expiresAt.getTime() <= now)
|
|
13744
|
+
return { healthy: false, reason: "certificate_expired", expiresAt };
|
|
13745
|
+
try {
|
|
13746
|
+
if (verifyHostname(hostname, certificate))
|
|
13747
|
+
return { healthy: false, reason: "hostname_mismatch" };
|
|
13748
|
+
} catch {
|
|
13749
|
+
return { healthy: false, reason: "certificate_invalid" };
|
|
13750
|
+
}
|
|
13751
|
+
return { healthy: true, expiresAt };
|
|
13752
|
+
}
|
|
13753
|
+
function probeLocalTls(hostname, options = {}) {
|
|
13754
|
+
const {
|
|
13755
|
+
connect: openTlsConnection = import_node_tls.connect,
|
|
13756
|
+
port = 443,
|
|
13757
|
+
timeoutMs = 1e3
|
|
13758
|
+
} = options;
|
|
13759
|
+
return new Promise((resolve2) => {
|
|
13760
|
+
let settled = false;
|
|
13761
|
+
let timeout;
|
|
13762
|
+
const socket = openTlsConnection({
|
|
13763
|
+
host: "127.0.0.1",
|
|
13764
|
+
port,
|
|
13765
|
+
servername: hostname,
|
|
13766
|
+
rejectUnauthorized: false
|
|
13767
|
+
});
|
|
13768
|
+
const finish = (result) => {
|
|
13769
|
+
if (settled)
|
|
13770
|
+
return;
|
|
13771
|
+
settled = true;
|
|
13772
|
+
if (timeout)
|
|
13773
|
+
clearTimeout(timeout);
|
|
13774
|
+
socket.destroy();
|
|
13775
|
+
resolve2(result);
|
|
13776
|
+
};
|
|
13777
|
+
timeout = setTimeout(() => {
|
|
13778
|
+
finish({ healthy: false, reason: "connection_failed" });
|
|
13779
|
+
}, timeoutMs);
|
|
13780
|
+
socket.once("secureConnect", () => {
|
|
13781
|
+
finish(assessTlsCertificate(socket.getPeerCertificate(), hostname));
|
|
13782
|
+
});
|
|
13783
|
+
socket.once("error", () => {
|
|
13784
|
+
finish({ healthy: false, reason: "connection_failed" });
|
|
13785
|
+
});
|
|
13786
|
+
});
|
|
13787
|
+
}
|
|
13788
|
+
function sleep(ms) {
|
|
13789
|
+
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
13790
|
+
}
|
|
13791
|
+
async function waitForLocalTls(hostname, options = {}) {
|
|
13792
|
+
const {
|
|
13793
|
+
probe: checkTls = probeLocalTls,
|
|
13794
|
+
retryIntervalMs = 250,
|
|
13795
|
+
retryWindowMs = 3e4,
|
|
13796
|
+
sleep: wait = sleep,
|
|
13797
|
+
...probeOptions
|
|
13798
|
+
} = options;
|
|
13799
|
+
const deadline = Date.now() + retryWindowMs;
|
|
13800
|
+
let result = { healthy: false, reason: "connection_failed" };
|
|
13801
|
+
do {
|
|
13802
|
+
result = await checkTls(hostname, probeOptions);
|
|
13803
|
+
if (result.healthy)
|
|
13804
|
+
return result;
|
|
13805
|
+
const remaining = deadline - Date.now();
|
|
13806
|
+
if (remaining > 0)
|
|
13807
|
+
await wait(Math.min(retryIntervalMs, remaining));
|
|
13808
|
+
} while (Date.now() < deadline);
|
|
13809
|
+
return result;
|
|
13810
|
+
}
|
|
13811
|
+
function formatTlsHealthFailure(hostname, result) {
|
|
13812
|
+
const reason = result.reason === "certificate_expired" && result.expiresAt ? `the certificate expired at ${result.expiresAt.toISOString()}` : result.reason.replaceAll("_", " ");
|
|
13813
|
+
return `[unplugin-https-reverse-proxy] Caddy cannot serve valid HTTPS for ${hostname}: ${reason}. Restart Caddy to retry its automatic certificate renewal. Do not remove Caddy PKI data automatically because that replaces the trusted local root certificate.`;
|
|
13814
|
+
}
|
|
13815
|
+
|
|
13725
13816
|
// src/caddy/utils.ts
|
|
13726
13817
|
var import_node_child_process3 = require("child_process");
|
|
13727
13818
|
var import_node_net = require("net");
|
|
@@ -13911,6 +14002,39 @@ var CaddyInstant = class {
|
|
|
13911
14002
|
await download();
|
|
13912
14003
|
this.inited = true;
|
|
13913
14004
|
}
|
|
14005
|
+
async ensureTlsReady(targetHost) {
|
|
14006
|
+
const health = await waitForLocalTls(targetHost);
|
|
14007
|
+
if (!health.healthy)
|
|
14008
|
+
throw new Error(formatTlsHealthFailure(targetHost, health));
|
|
14009
|
+
}
|
|
14010
|
+
async updateCaddyfile() {
|
|
14011
|
+
const { configJsonRef } = getCaddyConfig();
|
|
14012
|
+
const proxies = Object.values(configJsonRef() || {});
|
|
14013
|
+
const ctx = validateTemplateContext({
|
|
14014
|
+
caddy_root: this.caddyRoot,
|
|
14015
|
+
proxies
|
|
14016
|
+
});
|
|
14017
|
+
this.caddyfile = await genCaddyfile(ctx);
|
|
14018
|
+
await this.writeCaddyfile();
|
|
14019
|
+
}
|
|
14020
|
+
async stopCaddy() {
|
|
14021
|
+
var _a4;
|
|
14022
|
+
try {
|
|
14023
|
+
await import_got_cjs.got.post("http://127.0.0.1:2019/stop", {
|
|
14024
|
+
headers: {
|
|
14025
|
+
Origin: "http://localhost:2019"
|
|
14026
|
+
},
|
|
14027
|
+
retry: {
|
|
14028
|
+
limit: 0
|
|
14029
|
+
},
|
|
14030
|
+
timeout: {
|
|
14031
|
+
request: 2e3
|
|
14032
|
+
}
|
|
14033
|
+
});
|
|
14034
|
+
} catch {
|
|
14035
|
+
}
|
|
14036
|
+
(_a4 = this._caddyChild) == null ? void 0 : _a4.kill();
|
|
14037
|
+
}
|
|
13914
14038
|
/**
|
|
13915
14039
|
* @param source like `127.0.0.1:8080`
|
|
13916
14040
|
* @param target like `test.abc.com`. And if you provide a port ,it will be ignore.
|
|
@@ -13955,16 +14079,16 @@ var CaddyInstant = class {
|
|
|
13955
14079
|
];
|
|
13956
14080
|
const { writeCaddyConfig } = getCaddyConfig();
|
|
13957
14081
|
writeCaddyConfig(proxies);
|
|
14082
|
+
await this.updateCaddyfile();
|
|
14083
|
+
let skipInitialCaddyfileEffect = true;
|
|
13958
14084
|
this._stopEffects.push(
|
|
13959
|
-
effect(
|
|
13960
|
-
|
|
13961
|
-
|
|
13962
|
-
|
|
13963
|
-
|
|
13964
|
-
|
|
13965
|
-
|
|
13966
|
-
this.caddyfile = await genCaddyfile(ctx);
|
|
13967
|
-
await this.writeCaddyfile();
|
|
14085
|
+
effect(() => {
|
|
14086
|
+
getCaddyConfig().configJsonRef();
|
|
14087
|
+
if (skipInitialCaddyfileEffect) {
|
|
14088
|
+
skipInitialCaddyfileEffect = false;
|
|
14089
|
+
return;
|
|
14090
|
+
}
|
|
14091
|
+
void this.updateCaddyfile();
|
|
13968
14092
|
})
|
|
13969
14093
|
);
|
|
13970
14094
|
if (!(0, import_node_fs3.existsSync)(caddyLockFilePath))
|
|
@@ -13977,6 +14101,21 @@ var CaddyInstant = class {
|
|
|
13977
14101
|
}
|
|
13978
14102
|
return new Promise((resolve2, reject2) => {
|
|
13979
14103
|
var _a4, _b3;
|
|
14104
|
+
let startupCheckStarted = false;
|
|
14105
|
+
const resolveWhenReady = async () => {
|
|
14106
|
+
if (startupCheckStarted)
|
|
14107
|
+
return;
|
|
14108
|
+
startupCheckStarted = true;
|
|
14109
|
+
try {
|
|
14110
|
+
if (https)
|
|
14111
|
+
await this.ensureTlsReady(targetHost);
|
|
14112
|
+
resolve2();
|
|
14113
|
+
} catch (error) {
|
|
14114
|
+
if (!this.locked)
|
|
14115
|
+
await this.baseCleanup(restore);
|
|
14116
|
+
reject2(error);
|
|
14117
|
+
}
|
|
14118
|
+
};
|
|
13980
14119
|
const setupCleanup = () => {
|
|
13981
14120
|
import_node_process4.default.on("SIGINT", async () => {
|
|
13982
14121
|
if (this.stoped)
|
|
@@ -14036,6 +14175,10 @@ var CaddyInstant = class {
|
|
|
14036
14175
|
const lines = data.toString().split("\n").map((line) => line.trim());
|
|
14037
14176
|
for (const line of lines) {
|
|
14038
14177
|
showCaddyLog && line && console.info(line);
|
|
14178
|
+
if (isCaddyReloadCancellation(line)) {
|
|
14179
|
+
consola.info("Caddy restarted before TLS issuance completed; retrying.\n");
|
|
14180
|
+
continue;
|
|
14181
|
+
}
|
|
14039
14182
|
try {
|
|
14040
14183
|
if (line.includes("Error:") || line && JSON.parse(line).level === "error") {
|
|
14041
14184
|
if (line.includes("parsing caddyfile tokens")) {
|
|
@@ -14056,23 +14199,30 @@ ${line}
|
|
|
14056
14199
|
if (line.includes("config file changed"))
|
|
14057
14200
|
consola.success("Detect added a new reverse proxy config, restarted.\n");
|
|
14058
14201
|
if (line.includes("caddy proxying") || line.includes("serving initial"))
|
|
14059
|
-
|
|
14202
|
+
void resolveWhenReady();
|
|
14060
14203
|
}
|
|
14061
14204
|
});
|
|
14062
14205
|
(_b3 = this._caddyChild.stdout) == null ? void 0 : _b3.on("data", (_data) => {
|
|
14063
14206
|
consola.info(_data.toString());
|
|
14064
|
-
|
|
14207
|
+
void resolveWhenReady();
|
|
14065
14208
|
});
|
|
14066
14209
|
setupCleanup();
|
|
14067
14210
|
} else {
|
|
14068
14211
|
consola.info("Caddy is running in another process.");
|
|
14069
|
-
|
|
14070
|
-
|
|
14212
|
+
void (async () => {
|
|
14213
|
+
try {
|
|
14214
|
+
if (https)
|
|
14215
|
+
await this.ensureTlsReady(targetHost);
|
|
14216
|
+
setupCleanup();
|
|
14217
|
+
resolve2();
|
|
14218
|
+
} catch (error) {
|
|
14219
|
+
reject2(error);
|
|
14220
|
+
}
|
|
14221
|
+
})();
|
|
14071
14222
|
}
|
|
14072
14223
|
});
|
|
14073
14224
|
}
|
|
14074
14225
|
async baseCleanup(restore = true) {
|
|
14075
|
-
var _a4;
|
|
14076
14226
|
this._stopEffects.forEach((fn) => fn());
|
|
14077
14227
|
try {
|
|
14078
14228
|
if (restore && this._source && this._target) {
|
|
@@ -14086,7 +14236,7 @@ ${line}
|
|
|
14086
14236
|
consola.fail("Restore host failed.\n");
|
|
14087
14237
|
}
|
|
14088
14238
|
if (!this.locked && !this.stoped) {
|
|
14089
|
-
|
|
14239
|
+
await this.stopCaddy();
|
|
14090
14240
|
try {
|
|
14091
14241
|
await lockfile.unlock(caddyLockFilePath).catch(() => {
|
|
14092
14242
|
});
|
package/dist/vite.js
CHANGED
package/dist/webpack.cjs
CHANGED
|
@@ -13455,7 +13455,7 @@ function validateTemplateContext(ctx) {
|
|
|
13455
13455
|
}
|
|
13456
13456
|
var caddyTemplate = `{
|
|
13457
13457
|
debug
|
|
13458
|
-
auto_https disable_redirects
|
|
13458
|
+
auto_https disable_redirects ignore_loaded_certs
|
|
13459
13459
|
}
|
|
13460
13460
|
|
|
13461
13461
|
:7601 {
|
|
@@ -13722,6 +13722,97 @@ function useCaddyConfig() {
|
|
|
13722
13722
|
};
|
|
13723
13723
|
}
|
|
13724
13724
|
|
|
13725
|
+
// src/caddy/log.ts
|
|
13726
|
+
function isCaddyReloadCancellation(line) {
|
|
13727
|
+
try {
|
|
13728
|
+
const entry = JSON.parse(line);
|
|
13729
|
+
return entry.logger === "tls" && typeof entry.error === "string" && entry.error.endsWith("context canceled");
|
|
13730
|
+
} catch {
|
|
13731
|
+
return false;
|
|
13732
|
+
}
|
|
13733
|
+
}
|
|
13734
|
+
|
|
13735
|
+
// src/caddy/tls-health.ts
|
|
13736
|
+
var import_node_tls = require("tls");
|
|
13737
|
+
function assessTlsCertificate(certificate, hostname, now = Date.now(), verifyHostname = import_node_tls.checkServerIdentity) {
|
|
13738
|
+
if (!certificate.valid_to)
|
|
13739
|
+
return { healthy: false, reason: "certificate_missing" };
|
|
13740
|
+
const expiresAt = new Date(certificate.valid_to);
|
|
13741
|
+
if (Number.isNaN(expiresAt.getTime()))
|
|
13742
|
+
return { healthy: false, reason: "certificate_invalid" };
|
|
13743
|
+
if (expiresAt.getTime() <= now)
|
|
13744
|
+
return { healthy: false, reason: "certificate_expired", expiresAt };
|
|
13745
|
+
try {
|
|
13746
|
+
if (verifyHostname(hostname, certificate))
|
|
13747
|
+
return { healthy: false, reason: "hostname_mismatch" };
|
|
13748
|
+
} catch {
|
|
13749
|
+
return { healthy: false, reason: "certificate_invalid" };
|
|
13750
|
+
}
|
|
13751
|
+
return { healthy: true, expiresAt };
|
|
13752
|
+
}
|
|
13753
|
+
function probeLocalTls(hostname, options = {}) {
|
|
13754
|
+
const {
|
|
13755
|
+
connect: openTlsConnection = import_node_tls.connect,
|
|
13756
|
+
port = 443,
|
|
13757
|
+
timeoutMs = 1e3
|
|
13758
|
+
} = options;
|
|
13759
|
+
return new Promise((resolve2) => {
|
|
13760
|
+
let settled = false;
|
|
13761
|
+
let timeout;
|
|
13762
|
+
const socket = openTlsConnection({
|
|
13763
|
+
host: "127.0.0.1",
|
|
13764
|
+
port,
|
|
13765
|
+
servername: hostname,
|
|
13766
|
+
rejectUnauthorized: false
|
|
13767
|
+
});
|
|
13768
|
+
const finish = (result) => {
|
|
13769
|
+
if (settled)
|
|
13770
|
+
return;
|
|
13771
|
+
settled = true;
|
|
13772
|
+
if (timeout)
|
|
13773
|
+
clearTimeout(timeout);
|
|
13774
|
+
socket.destroy();
|
|
13775
|
+
resolve2(result);
|
|
13776
|
+
};
|
|
13777
|
+
timeout = setTimeout(() => {
|
|
13778
|
+
finish({ healthy: false, reason: "connection_failed" });
|
|
13779
|
+
}, timeoutMs);
|
|
13780
|
+
socket.once("secureConnect", () => {
|
|
13781
|
+
finish(assessTlsCertificate(socket.getPeerCertificate(), hostname));
|
|
13782
|
+
});
|
|
13783
|
+
socket.once("error", () => {
|
|
13784
|
+
finish({ healthy: false, reason: "connection_failed" });
|
|
13785
|
+
});
|
|
13786
|
+
});
|
|
13787
|
+
}
|
|
13788
|
+
function sleep(ms) {
|
|
13789
|
+
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
13790
|
+
}
|
|
13791
|
+
async function waitForLocalTls(hostname, options = {}) {
|
|
13792
|
+
const {
|
|
13793
|
+
probe: checkTls = probeLocalTls,
|
|
13794
|
+
retryIntervalMs = 250,
|
|
13795
|
+
retryWindowMs = 3e4,
|
|
13796
|
+
sleep: wait = sleep,
|
|
13797
|
+
...probeOptions
|
|
13798
|
+
} = options;
|
|
13799
|
+
const deadline = Date.now() + retryWindowMs;
|
|
13800
|
+
let result = { healthy: false, reason: "connection_failed" };
|
|
13801
|
+
do {
|
|
13802
|
+
result = await checkTls(hostname, probeOptions);
|
|
13803
|
+
if (result.healthy)
|
|
13804
|
+
return result;
|
|
13805
|
+
const remaining = deadline - Date.now();
|
|
13806
|
+
if (remaining > 0)
|
|
13807
|
+
await wait(Math.min(retryIntervalMs, remaining));
|
|
13808
|
+
} while (Date.now() < deadline);
|
|
13809
|
+
return result;
|
|
13810
|
+
}
|
|
13811
|
+
function formatTlsHealthFailure(hostname, result) {
|
|
13812
|
+
const reason = result.reason === "certificate_expired" && result.expiresAt ? `the certificate expired at ${result.expiresAt.toISOString()}` : result.reason.replaceAll("_", " ");
|
|
13813
|
+
return `[unplugin-https-reverse-proxy] Caddy cannot serve valid HTTPS for ${hostname}: ${reason}. Restart Caddy to retry its automatic certificate renewal. Do not remove Caddy PKI data automatically because that replaces the trusted local root certificate.`;
|
|
13814
|
+
}
|
|
13815
|
+
|
|
13725
13816
|
// src/caddy/utils.ts
|
|
13726
13817
|
var import_node_child_process3 = require("child_process");
|
|
13727
13818
|
var import_node_net = require("net");
|
|
@@ -13911,6 +14002,39 @@ var CaddyInstant = class {
|
|
|
13911
14002
|
await download();
|
|
13912
14003
|
this.inited = true;
|
|
13913
14004
|
}
|
|
14005
|
+
async ensureTlsReady(targetHost) {
|
|
14006
|
+
const health = await waitForLocalTls(targetHost);
|
|
14007
|
+
if (!health.healthy)
|
|
14008
|
+
throw new Error(formatTlsHealthFailure(targetHost, health));
|
|
14009
|
+
}
|
|
14010
|
+
async updateCaddyfile() {
|
|
14011
|
+
const { configJsonRef } = getCaddyConfig();
|
|
14012
|
+
const proxies = Object.values(configJsonRef() || {});
|
|
14013
|
+
const ctx = validateTemplateContext({
|
|
14014
|
+
caddy_root: this.caddyRoot,
|
|
14015
|
+
proxies
|
|
14016
|
+
});
|
|
14017
|
+
this.caddyfile = await genCaddyfile(ctx);
|
|
14018
|
+
await this.writeCaddyfile();
|
|
14019
|
+
}
|
|
14020
|
+
async stopCaddy() {
|
|
14021
|
+
var _a4;
|
|
14022
|
+
try {
|
|
14023
|
+
await import_got_cjs.got.post("http://127.0.0.1:2019/stop", {
|
|
14024
|
+
headers: {
|
|
14025
|
+
Origin: "http://localhost:2019"
|
|
14026
|
+
},
|
|
14027
|
+
retry: {
|
|
14028
|
+
limit: 0
|
|
14029
|
+
},
|
|
14030
|
+
timeout: {
|
|
14031
|
+
request: 2e3
|
|
14032
|
+
}
|
|
14033
|
+
});
|
|
14034
|
+
} catch {
|
|
14035
|
+
}
|
|
14036
|
+
(_a4 = this._caddyChild) == null ? void 0 : _a4.kill();
|
|
14037
|
+
}
|
|
13914
14038
|
/**
|
|
13915
14039
|
* @param source like `127.0.0.1:8080`
|
|
13916
14040
|
* @param target like `test.abc.com`. And if you provide a port ,it will be ignore.
|
|
@@ -13955,16 +14079,16 @@ var CaddyInstant = class {
|
|
|
13955
14079
|
];
|
|
13956
14080
|
const { writeCaddyConfig } = getCaddyConfig();
|
|
13957
14081
|
writeCaddyConfig(proxies);
|
|
14082
|
+
await this.updateCaddyfile();
|
|
14083
|
+
let skipInitialCaddyfileEffect = true;
|
|
13958
14084
|
this._stopEffects.push(
|
|
13959
|
-
effect(
|
|
13960
|
-
|
|
13961
|
-
|
|
13962
|
-
|
|
13963
|
-
|
|
13964
|
-
|
|
13965
|
-
|
|
13966
|
-
this.caddyfile = await genCaddyfile(ctx);
|
|
13967
|
-
await this.writeCaddyfile();
|
|
14085
|
+
effect(() => {
|
|
14086
|
+
getCaddyConfig().configJsonRef();
|
|
14087
|
+
if (skipInitialCaddyfileEffect) {
|
|
14088
|
+
skipInitialCaddyfileEffect = false;
|
|
14089
|
+
return;
|
|
14090
|
+
}
|
|
14091
|
+
void this.updateCaddyfile();
|
|
13968
14092
|
})
|
|
13969
14093
|
);
|
|
13970
14094
|
if (!(0, import_node_fs3.existsSync)(caddyLockFilePath))
|
|
@@ -13977,6 +14101,21 @@ var CaddyInstant = class {
|
|
|
13977
14101
|
}
|
|
13978
14102
|
return new Promise((resolve2, reject2) => {
|
|
13979
14103
|
var _a4, _b3;
|
|
14104
|
+
let startupCheckStarted = false;
|
|
14105
|
+
const resolveWhenReady = async () => {
|
|
14106
|
+
if (startupCheckStarted)
|
|
14107
|
+
return;
|
|
14108
|
+
startupCheckStarted = true;
|
|
14109
|
+
try {
|
|
14110
|
+
if (https)
|
|
14111
|
+
await this.ensureTlsReady(targetHost);
|
|
14112
|
+
resolve2();
|
|
14113
|
+
} catch (error) {
|
|
14114
|
+
if (!this.locked)
|
|
14115
|
+
await this.baseCleanup(restore);
|
|
14116
|
+
reject2(error);
|
|
14117
|
+
}
|
|
14118
|
+
};
|
|
13980
14119
|
const setupCleanup = () => {
|
|
13981
14120
|
import_node_process4.default.on("SIGINT", async () => {
|
|
13982
14121
|
if (this.stoped)
|
|
@@ -14036,6 +14175,10 @@ var CaddyInstant = class {
|
|
|
14036
14175
|
const lines = data.toString().split("\n").map((line) => line.trim());
|
|
14037
14176
|
for (const line of lines) {
|
|
14038
14177
|
showCaddyLog && line && console.info(line);
|
|
14178
|
+
if (isCaddyReloadCancellation(line)) {
|
|
14179
|
+
consola.info("Caddy restarted before TLS issuance completed; retrying.\n");
|
|
14180
|
+
continue;
|
|
14181
|
+
}
|
|
14039
14182
|
try {
|
|
14040
14183
|
if (line.includes("Error:") || line && JSON.parse(line).level === "error") {
|
|
14041
14184
|
if (line.includes("parsing caddyfile tokens")) {
|
|
@@ -14056,23 +14199,30 @@ ${line}
|
|
|
14056
14199
|
if (line.includes("config file changed"))
|
|
14057
14200
|
consola.success("Detect added a new reverse proxy config, restarted.\n");
|
|
14058
14201
|
if (line.includes("caddy proxying") || line.includes("serving initial"))
|
|
14059
|
-
|
|
14202
|
+
void resolveWhenReady();
|
|
14060
14203
|
}
|
|
14061
14204
|
});
|
|
14062
14205
|
(_b3 = this._caddyChild.stdout) == null ? void 0 : _b3.on("data", (_data) => {
|
|
14063
14206
|
consola.info(_data.toString());
|
|
14064
|
-
|
|
14207
|
+
void resolveWhenReady();
|
|
14065
14208
|
});
|
|
14066
14209
|
setupCleanup();
|
|
14067
14210
|
} else {
|
|
14068
14211
|
consola.info("Caddy is running in another process.");
|
|
14069
|
-
|
|
14070
|
-
|
|
14212
|
+
void (async () => {
|
|
14213
|
+
try {
|
|
14214
|
+
if (https)
|
|
14215
|
+
await this.ensureTlsReady(targetHost);
|
|
14216
|
+
setupCleanup();
|
|
14217
|
+
resolve2();
|
|
14218
|
+
} catch (error) {
|
|
14219
|
+
reject2(error);
|
|
14220
|
+
}
|
|
14221
|
+
})();
|
|
14071
14222
|
}
|
|
14072
14223
|
});
|
|
14073
14224
|
}
|
|
14074
14225
|
async baseCleanup(restore = true) {
|
|
14075
|
-
var _a4;
|
|
14076
14226
|
this._stopEffects.forEach((fn) => fn());
|
|
14077
14227
|
try {
|
|
14078
14228
|
if (restore && this._source && this._target) {
|
|
@@ -14086,7 +14236,7 @@ ${line}
|
|
|
14086
14236
|
consola.fail("Restore host failed.\n");
|
|
14087
14237
|
}
|
|
14088
14238
|
if (!this.locked && !this.stoped) {
|
|
14089
|
-
|
|
14239
|
+
await this.stopCaddy();
|
|
14090
14240
|
try {
|
|
14091
14241
|
await lockfile.unlock(caddyLockFilePath).catch(() => {
|
|
14092
14242
|
});
|
package/dist/webpack.js
CHANGED
package/package.json
CHANGED
package/src/caddy/caddyfile.ts
CHANGED
package/src/caddy/index.ts
CHANGED
|
@@ -14,6 +14,8 @@ import { chmodRecursive, consola, once } from '../utils'
|
|
|
14
14
|
import { genCaddyfile, validateTemplateContext } from './caddyfile'
|
|
15
15
|
import { useCaddyConfig } from './config'
|
|
16
16
|
import { caddyFilePath, caddyLockFilePath, caddyPath, supportList, TEMP_DIR } from './constants'
|
|
17
|
+
import { isCaddyReloadCancellation } from './log'
|
|
18
|
+
import { formatTlsHealthFailure, waitForLocalTls } from './tls-health'
|
|
17
19
|
import { kill, logProgress, logProgressOver, tryPort } from './utils'
|
|
18
20
|
|
|
19
21
|
export async function download(): Promise<string> {
|
|
@@ -187,6 +189,43 @@ export class CaddyInstant {
|
|
|
187
189
|
this.inited = true
|
|
188
190
|
}
|
|
189
191
|
|
|
192
|
+
private async ensureTlsReady(targetHost: string): Promise<void> {
|
|
193
|
+
const health = await waitForLocalTls(targetHost)
|
|
194
|
+
if (!health.healthy)
|
|
195
|
+
throw new Error(formatTlsHealthFailure(targetHost, health))
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
private async updateCaddyfile(): Promise<void> {
|
|
199
|
+
const { configJsonRef } = getCaddyConfig()
|
|
200
|
+
const proxies = Object.values(configJsonRef() || {})
|
|
201
|
+
const ctx = validateTemplateContext({
|
|
202
|
+
caddy_root: this.caddyRoot,
|
|
203
|
+
proxies,
|
|
204
|
+
})
|
|
205
|
+
|
|
206
|
+
this.caddyfile = await genCaddyfile(ctx)
|
|
207
|
+
await this.writeCaddyfile()
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
private async stopCaddy(): Promise<void> {
|
|
211
|
+
try {
|
|
212
|
+
await got.post('http://127.0.0.1:2019/stop', {
|
|
213
|
+
headers: {
|
|
214
|
+
Origin: 'http://localhost:2019',
|
|
215
|
+
},
|
|
216
|
+
retry: {
|
|
217
|
+
limit: 0,
|
|
218
|
+
},
|
|
219
|
+
timeout: {
|
|
220
|
+
request: 2000,
|
|
221
|
+
},
|
|
222
|
+
})
|
|
223
|
+
}
|
|
224
|
+
catch {}
|
|
225
|
+
|
|
226
|
+
this._caddyChild?.kill()
|
|
227
|
+
}
|
|
228
|
+
|
|
190
229
|
/**
|
|
191
230
|
* @param source like `127.0.0.1:8080`
|
|
192
231
|
* @param target like `test.abc.com`. And if you provide a port ,it will be ignore.
|
|
@@ -239,17 +278,17 @@ export class CaddyInstant {
|
|
|
239
278
|
const { writeCaddyConfig } = getCaddyConfig()
|
|
240
279
|
writeCaddyConfig(proxies)
|
|
241
280
|
|
|
242
|
-
this.
|
|
243
|
-
effect(async () => {
|
|
244
|
-
const { configJsonRef } = getCaddyConfig()
|
|
245
|
-
const proxies = Object.values(configJsonRef() || {})
|
|
246
|
-
const ctx = validateTemplateContext({
|
|
247
|
-
caddy_root: this.caddyRoot,
|
|
248
|
-
proxies,
|
|
249
|
-
})
|
|
281
|
+
await this.updateCaddyfile()
|
|
250
282
|
|
|
251
|
-
|
|
252
|
-
|
|
283
|
+
let skipInitialCaddyfileEffect = true
|
|
284
|
+
this._stopEffects.push(
|
|
285
|
+
effect(() => {
|
|
286
|
+
getCaddyConfig().configJsonRef()
|
|
287
|
+
if (skipInitialCaddyfileEffect) {
|
|
288
|
+
skipInitialCaddyfileEffect = false
|
|
289
|
+
return
|
|
290
|
+
}
|
|
291
|
+
void this.updateCaddyfile()
|
|
253
292
|
}),
|
|
254
293
|
)
|
|
255
294
|
|
|
@@ -264,6 +303,25 @@ export class CaddyInstant {
|
|
|
264
303
|
}
|
|
265
304
|
|
|
266
305
|
return new Promise<void>((resolve, reject) => {
|
|
306
|
+
let startupCheckStarted = false
|
|
307
|
+
|
|
308
|
+
const resolveWhenReady = async (): Promise<void> => {
|
|
309
|
+
if (startupCheckStarted)
|
|
310
|
+
return
|
|
311
|
+
startupCheckStarted = true
|
|
312
|
+
|
|
313
|
+
try {
|
|
314
|
+
if (https)
|
|
315
|
+
await this.ensureTlsReady(targetHost)
|
|
316
|
+
resolve()
|
|
317
|
+
}
|
|
318
|
+
catch (error) {
|
|
319
|
+
if (!this.locked)
|
|
320
|
+
await this.baseCleanup(restore)
|
|
321
|
+
reject(error)
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
267
325
|
const setupCleanup = (): void => {
|
|
268
326
|
process.on('SIGINT', async () => {
|
|
269
327
|
if (this.stoped)
|
|
@@ -340,6 +398,10 @@ export class CaddyInstant {
|
|
|
340
398
|
// caddy log
|
|
341
399
|
// eslint-disable-next-line no-console
|
|
342
400
|
showCaddyLog && line && console.info(line)
|
|
401
|
+
if (isCaddyReloadCancellation(line)) {
|
|
402
|
+
consola.info('Caddy restarted before TLS issuance completed; retrying.\n')
|
|
403
|
+
continue
|
|
404
|
+
}
|
|
343
405
|
try {
|
|
344
406
|
if (line.includes('Error:') || (line && JSON.parse(line).level === 'error')) {
|
|
345
407
|
if (line.includes('parsing caddyfile tokens')) {
|
|
@@ -360,13 +422,13 @@ export class CaddyInstant {
|
|
|
360
422
|
consola.success('Detect added a new reverse proxy config, restarted.\n')
|
|
361
423
|
|
|
362
424
|
if (line.includes('caddy proxying') || line.includes('serving initial'))
|
|
363
|
-
|
|
425
|
+
void resolveWhenReady()
|
|
364
426
|
}
|
|
365
427
|
})
|
|
366
428
|
|
|
367
429
|
this._caddyChild!.stdout?.on('data', (_data) => {
|
|
368
430
|
consola.info(_data.toString())
|
|
369
|
-
|
|
431
|
+
void resolveWhenReady()
|
|
370
432
|
})
|
|
371
433
|
|
|
372
434
|
setupCleanup()
|
|
@@ -374,9 +436,17 @@ export class CaddyInstant {
|
|
|
374
436
|
else {
|
|
375
437
|
consola.info('Caddy is running in another process.')
|
|
376
438
|
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
439
|
+
void (async () => {
|
|
440
|
+
try {
|
|
441
|
+
if (https)
|
|
442
|
+
await this.ensureTlsReady(targetHost)
|
|
443
|
+
setupCleanup()
|
|
444
|
+
resolve()
|
|
445
|
+
}
|
|
446
|
+
catch (error) {
|
|
447
|
+
reject(error)
|
|
448
|
+
}
|
|
449
|
+
})()
|
|
380
450
|
}
|
|
381
451
|
})
|
|
382
452
|
}
|
|
@@ -398,7 +468,7 @@ export class CaddyInstant {
|
|
|
398
468
|
consola.fail('Restore host failed.\n')
|
|
399
469
|
}
|
|
400
470
|
if (!this.locked && !this.stoped) {
|
|
401
|
-
this.
|
|
471
|
+
await this.stopCaddy()
|
|
402
472
|
try {
|
|
403
473
|
await lockfile.unlock(caddyLockFilePath).catch(() => { })
|
|
404
474
|
await unlink(caddyFilePath).catch(() => { })
|