unplugin-https-reverse-proxy 4.0.1 → 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-QURDG7SD.js → chunk-MD5CVZP7.js} +187 -20
- package/dist/esbuild.cjs +187 -20
- package/dist/esbuild.js +1 -1
- package/dist/index.cjs +187 -20
- package/dist/index.js +1 -1
- package/dist/nuxt.cjs +187 -20
- package/dist/nuxt.js +1 -1
- package/dist/rollup.cjs +187 -20
- package/dist/rollup.js +1 -1
- package/dist/rspack.cjs +187 -20
- package/dist/rspack.js +1 -1
- package/dist/vite.cjs +187 -20
- package/dist/vite.js +1 -1
- package/dist/webpack.cjs +187 -20
- package/dist/webpack.js +1 -1
- package/package.json +1 -1
- package/src/caddy/caddyfile.ts +1 -1
- package/src/caddy/index.ts +110 -21
- package/src/caddy/log.ts +16 -0
- package/src/caddy/tls-health.ts +142 -0
|
@@ -13374,7 +13374,7 @@ function validateTemplateContext(ctx) {
|
|
|
13374
13374
|
}
|
|
13375
13375
|
var caddyTemplate = `{
|
|
13376
13376
|
debug
|
|
13377
|
-
auto_https disable_redirects
|
|
13377
|
+
auto_https disable_redirects ignore_loaded_certs
|
|
13378
13378
|
}
|
|
13379
13379
|
|
|
13380
13380
|
:7601 {
|
|
@@ -13641,6 +13641,97 @@ function useCaddyConfig() {
|
|
|
13641
13641
|
};
|
|
13642
13642
|
}
|
|
13643
13643
|
|
|
13644
|
+
// src/caddy/log.ts
|
|
13645
|
+
function isCaddyReloadCancellation(line) {
|
|
13646
|
+
try {
|
|
13647
|
+
const entry = JSON.parse(line);
|
|
13648
|
+
return entry.logger === "tls" && typeof entry.error === "string" && entry.error.endsWith("context canceled");
|
|
13649
|
+
} catch {
|
|
13650
|
+
return false;
|
|
13651
|
+
}
|
|
13652
|
+
}
|
|
13653
|
+
|
|
13654
|
+
// src/caddy/tls-health.ts
|
|
13655
|
+
import { checkServerIdentity, connect } from "node:tls";
|
|
13656
|
+
function assessTlsCertificate(certificate, hostname, now = Date.now(), verifyHostname = checkServerIdentity) {
|
|
13657
|
+
if (!certificate.valid_to)
|
|
13658
|
+
return { healthy: false, reason: "certificate_missing" };
|
|
13659
|
+
const expiresAt = new Date(certificate.valid_to);
|
|
13660
|
+
if (Number.isNaN(expiresAt.getTime()))
|
|
13661
|
+
return { healthy: false, reason: "certificate_invalid" };
|
|
13662
|
+
if (expiresAt.getTime() <= now)
|
|
13663
|
+
return { healthy: false, reason: "certificate_expired", expiresAt };
|
|
13664
|
+
try {
|
|
13665
|
+
if (verifyHostname(hostname, certificate))
|
|
13666
|
+
return { healthy: false, reason: "hostname_mismatch" };
|
|
13667
|
+
} catch {
|
|
13668
|
+
return { healthy: false, reason: "certificate_invalid" };
|
|
13669
|
+
}
|
|
13670
|
+
return { healthy: true, expiresAt };
|
|
13671
|
+
}
|
|
13672
|
+
function probeLocalTls(hostname, options = {}) {
|
|
13673
|
+
const {
|
|
13674
|
+
connect: openTlsConnection = connect,
|
|
13675
|
+
port = 443,
|
|
13676
|
+
timeoutMs = 1e3
|
|
13677
|
+
} = options;
|
|
13678
|
+
return new Promise((resolve2) => {
|
|
13679
|
+
let settled = false;
|
|
13680
|
+
let timeout;
|
|
13681
|
+
const socket = openTlsConnection({
|
|
13682
|
+
host: "127.0.0.1",
|
|
13683
|
+
port,
|
|
13684
|
+
servername: hostname,
|
|
13685
|
+
rejectUnauthorized: false
|
|
13686
|
+
});
|
|
13687
|
+
const finish = (result) => {
|
|
13688
|
+
if (settled)
|
|
13689
|
+
return;
|
|
13690
|
+
settled = true;
|
|
13691
|
+
if (timeout)
|
|
13692
|
+
clearTimeout(timeout);
|
|
13693
|
+
socket.destroy();
|
|
13694
|
+
resolve2(result);
|
|
13695
|
+
};
|
|
13696
|
+
timeout = setTimeout(() => {
|
|
13697
|
+
finish({ healthy: false, reason: "connection_failed" });
|
|
13698
|
+
}, timeoutMs);
|
|
13699
|
+
socket.once("secureConnect", () => {
|
|
13700
|
+
finish(assessTlsCertificate(socket.getPeerCertificate(), hostname));
|
|
13701
|
+
});
|
|
13702
|
+
socket.once("error", () => {
|
|
13703
|
+
finish({ healthy: false, reason: "connection_failed" });
|
|
13704
|
+
});
|
|
13705
|
+
});
|
|
13706
|
+
}
|
|
13707
|
+
function sleep(ms) {
|
|
13708
|
+
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
13709
|
+
}
|
|
13710
|
+
async function waitForLocalTls(hostname, options = {}) {
|
|
13711
|
+
const {
|
|
13712
|
+
probe: checkTls = probeLocalTls,
|
|
13713
|
+
retryIntervalMs = 250,
|
|
13714
|
+
retryWindowMs = 3e4,
|
|
13715
|
+
sleep: wait = sleep,
|
|
13716
|
+
...probeOptions
|
|
13717
|
+
} = options;
|
|
13718
|
+
const deadline = Date.now() + retryWindowMs;
|
|
13719
|
+
let result = { healthy: false, reason: "connection_failed" };
|
|
13720
|
+
do {
|
|
13721
|
+
result = await checkTls(hostname, probeOptions);
|
|
13722
|
+
if (result.healthy)
|
|
13723
|
+
return result;
|
|
13724
|
+
const remaining = deadline - Date.now();
|
|
13725
|
+
if (remaining > 0)
|
|
13726
|
+
await wait(Math.min(retryIntervalMs, remaining));
|
|
13727
|
+
} while (Date.now() < deadline);
|
|
13728
|
+
return result;
|
|
13729
|
+
}
|
|
13730
|
+
function formatTlsHealthFailure(hostname, result) {
|
|
13731
|
+
const reason = result.reason === "certificate_expired" && result.expiresAt ? `the certificate expired at ${result.expiresAt.toISOString()}` : result.reason.replaceAll("_", " ");
|
|
13732
|
+
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.`;
|
|
13733
|
+
}
|
|
13734
|
+
|
|
13644
13735
|
// src/caddy/utils.ts
|
|
13645
13736
|
import { exec as exec2 } from "node:child_process";
|
|
13646
13737
|
import { createServer } from "node:net";
|
|
@@ -13778,6 +13869,17 @@ function getCaddyConfig() {
|
|
|
13778
13869
|
}
|
|
13779
13870
|
return caddyConfig;
|
|
13780
13871
|
}
|
|
13872
|
+
function splitHostPort(addr) {
|
|
13873
|
+
const lastColon = addr.lastIndexOf(":");
|
|
13874
|
+
if (lastColon === -1)
|
|
13875
|
+
return { host: addr, port: "" };
|
|
13876
|
+
if (addr.startsWith("[")) {
|
|
13877
|
+
const end = addr.indexOf("]");
|
|
13878
|
+
if (end !== -1 && addr[end + 1] === ":")
|
|
13879
|
+
return { host: addr.slice(1, end), port: addr.slice(end + 2) };
|
|
13880
|
+
}
|
|
13881
|
+
return { host: addr.slice(0, lastColon), port: addr.slice(lastColon + 1) };
|
|
13882
|
+
}
|
|
13781
13883
|
var CaddyInstant = class {
|
|
13782
13884
|
constructor() {
|
|
13783
13885
|
this.inited = false;
|
|
@@ -13819,12 +13921,46 @@ var CaddyInstant = class {
|
|
|
13819
13921
|
await download();
|
|
13820
13922
|
this.inited = true;
|
|
13821
13923
|
}
|
|
13924
|
+
async ensureTlsReady(targetHost) {
|
|
13925
|
+
const health = await waitForLocalTls(targetHost);
|
|
13926
|
+
if (!health.healthy)
|
|
13927
|
+
throw new Error(formatTlsHealthFailure(targetHost, health));
|
|
13928
|
+
}
|
|
13929
|
+
async updateCaddyfile() {
|
|
13930
|
+
const { configJsonRef } = getCaddyConfig();
|
|
13931
|
+
const proxies = Object.values(configJsonRef() || {});
|
|
13932
|
+
const ctx = validateTemplateContext({
|
|
13933
|
+
caddy_root: this.caddyRoot,
|
|
13934
|
+
proxies
|
|
13935
|
+
});
|
|
13936
|
+
this.caddyfile = await genCaddyfile(ctx);
|
|
13937
|
+
await this.writeCaddyfile();
|
|
13938
|
+
}
|
|
13939
|
+
async stopCaddy() {
|
|
13940
|
+
var _a4;
|
|
13941
|
+
try {
|
|
13942
|
+
await got.post("http://127.0.0.1:2019/stop", {
|
|
13943
|
+
headers: {
|
|
13944
|
+
Origin: "http://localhost:2019"
|
|
13945
|
+
},
|
|
13946
|
+
retry: {
|
|
13947
|
+
limit: 0
|
|
13948
|
+
},
|
|
13949
|
+
timeout: {
|
|
13950
|
+
request: 2e3
|
|
13951
|
+
}
|
|
13952
|
+
});
|
|
13953
|
+
} catch {
|
|
13954
|
+
}
|
|
13955
|
+
(_a4 = this._caddyChild) == null ? void 0 : _a4.kill();
|
|
13956
|
+
}
|
|
13822
13957
|
/**
|
|
13823
13958
|
* @param source like `127.0.0.1:8080`
|
|
13824
13959
|
* @param target like `test.abc.com`. And if you provide a port ,it will be ignore.
|
|
13825
13960
|
*/
|
|
13826
13961
|
async run(source, target, options) {
|
|
13827
13962
|
source = source.replace("0.0.0.0", "127.0.0.1");
|
|
13963
|
+
source = source.replace(/^localhost(?=:)/i, "127.0.0.1");
|
|
13828
13964
|
const {
|
|
13829
13965
|
restore = true,
|
|
13830
13966
|
base = "/",
|
|
@@ -13836,10 +13972,11 @@ var CaddyInstant = class {
|
|
|
13836
13972
|
this._target = target;
|
|
13837
13973
|
if (!this.inited)
|
|
13838
13974
|
await this.init();
|
|
13839
|
-
|
|
13975
|
+
const sourceHost = splitHostPort(source).host;
|
|
13976
|
+
const targetHost = splitHostPort(target).host;
|
|
13977
|
+
if (!await addHost(sourceHost, targetHost))
|
|
13840
13978
|
throw new Error("update host failed");
|
|
13841
13979
|
consola.success("update host success\n");
|
|
13842
|
-
const targetHost = target.split(":")[0];
|
|
13843
13980
|
const normalizeBase = (b) => {
|
|
13844
13981
|
let out = b || "/";
|
|
13845
13982
|
if (!out.startsWith("/"))
|
|
@@ -13861,16 +13998,16 @@ var CaddyInstant = class {
|
|
|
13861
13998
|
];
|
|
13862
13999
|
const { writeCaddyConfig } = getCaddyConfig();
|
|
13863
14000
|
writeCaddyConfig(proxies);
|
|
14001
|
+
await this.updateCaddyfile();
|
|
14002
|
+
let skipInitialCaddyfileEffect = true;
|
|
13864
14003
|
this._stopEffects.push(
|
|
13865
|
-
effect(
|
|
13866
|
-
|
|
13867
|
-
|
|
13868
|
-
|
|
13869
|
-
|
|
13870
|
-
|
|
13871
|
-
|
|
13872
|
-
this.caddyfile = await genCaddyfile(ctx);
|
|
13873
|
-
await this.writeCaddyfile();
|
|
14004
|
+
effect(() => {
|
|
14005
|
+
getCaddyConfig().configJsonRef();
|
|
14006
|
+
if (skipInitialCaddyfileEffect) {
|
|
14007
|
+
skipInitialCaddyfileEffect = false;
|
|
14008
|
+
return;
|
|
14009
|
+
}
|
|
14010
|
+
void this.updateCaddyfile();
|
|
13874
14011
|
})
|
|
13875
14012
|
);
|
|
13876
14013
|
if (!existsSync3(caddyLockFilePath))
|
|
@@ -13883,6 +14020,21 @@ var CaddyInstant = class {
|
|
|
13883
14020
|
}
|
|
13884
14021
|
return new Promise((resolve2, reject2) => {
|
|
13885
14022
|
var _a4, _b3;
|
|
14023
|
+
let startupCheckStarted = false;
|
|
14024
|
+
const resolveWhenReady = async () => {
|
|
14025
|
+
if (startupCheckStarted)
|
|
14026
|
+
return;
|
|
14027
|
+
startupCheckStarted = true;
|
|
14028
|
+
try {
|
|
14029
|
+
if (https)
|
|
14030
|
+
await this.ensureTlsReady(targetHost);
|
|
14031
|
+
resolve2();
|
|
14032
|
+
} catch (error) {
|
|
14033
|
+
if (!this.locked)
|
|
14034
|
+
await this.baseCleanup(restore);
|
|
14035
|
+
reject2(error);
|
|
14036
|
+
}
|
|
14037
|
+
};
|
|
13886
14038
|
const setupCleanup = () => {
|
|
13887
14039
|
process4.on("SIGINT", async () => {
|
|
13888
14040
|
if (this.stoped)
|
|
@@ -13899,7 +14051,7 @@ var CaddyInstant = class {
|
|
|
13899
14051
|
});
|
|
13900
14052
|
const originalExit = process4.exit.bind(process4);
|
|
13901
14053
|
process4.exit = async (code) => {
|
|
13902
|
-
const port = Number(source.
|
|
14054
|
+
const port = Number(splitHostPort(source).port);
|
|
13903
14055
|
if (!Number.isNaN(port) && await tryPort(port))
|
|
13904
14056
|
await kill(port);
|
|
13905
14057
|
const pwd = process4.cwd();
|
|
@@ -13907,6 +14059,10 @@ var CaddyInstant = class {
|
|
|
13907
14059
|
if (existsSync3(viteCacheDir))
|
|
13908
14060
|
await chmodRecursive(viteCacheDir, 511).catch(() => {
|
|
13909
14061
|
});
|
|
14062
|
+
const viteTempCacheDir = `${pwd}/node_modules/.vite-temp`;
|
|
14063
|
+
if (existsSync3(viteTempCacheDir))
|
|
14064
|
+
await chmodRecursive(viteTempCacheDir, 511).catch(() => {
|
|
14065
|
+
});
|
|
13910
14066
|
const nuxtCacheDir = `${pwd}/.nuxt`;
|
|
13911
14067
|
if (existsSync3(nuxtCacheDir))
|
|
13912
14068
|
await chmodRecursive(nuxtCacheDir, 511).catch(() => {
|
|
@@ -13938,6 +14094,10 @@ var CaddyInstant = class {
|
|
|
13938
14094
|
const lines = data.toString().split("\n").map((line) => line.trim());
|
|
13939
14095
|
for (const line of lines) {
|
|
13940
14096
|
showCaddyLog && line && console.info(line);
|
|
14097
|
+
if (isCaddyReloadCancellation(line)) {
|
|
14098
|
+
consola.info("Caddy restarted before TLS issuance completed; retrying.\n");
|
|
14099
|
+
continue;
|
|
14100
|
+
}
|
|
13941
14101
|
try {
|
|
13942
14102
|
if (line.includes("Error:") || line && JSON.parse(line).level === "error") {
|
|
13943
14103
|
if (line.includes("parsing caddyfile tokens")) {
|
|
@@ -13958,27 +14118,34 @@ ${line}
|
|
|
13958
14118
|
if (line.includes("config file changed"))
|
|
13959
14119
|
consola.success("Detect added a new reverse proxy config, restarted.\n");
|
|
13960
14120
|
if (line.includes("caddy proxying") || line.includes("serving initial"))
|
|
13961
|
-
|
|
14121
|
+
void resolveWhenReady();
|
|
13962
14122
|
}
|
|
13963
14123
|
});
|
|
13964
14124
|
(_b3 = this._caddyChild.stdout) == null ? void 0 : _b3.on("data", (_data) => {
|
|
13965
14125
|
consola.info(_data.toString());
|
|
13966
|
-
|
|
14126
|
+
void resolveWhenReady();
|
|
13967
14127
|
});
|
|
13968
14128
|
setupCleanup();
|
|
13969
14129
|
} else {
|
|
13970
14130
|
consola.info("Caddy is running in another process.");
|
|
13971
|
-
|
|
13972
|
-
|
|
14131
|
+
void (async () => {
|
|
14132
|
+
try {
|
|
14133
|
+
if (https)
|
|
14134
|
+
await this.ensureTlsReady(targetHost);
|
|
14135
|
+
setupCleanup();
|
|
14136
|
+
resolve2();
|
|
14137
|
+
} catch (error) {
|
|
14138
|
+
reject2(error);
|
|
14139
|
+
}
|
|
14140
|
+
})();
|
|
13973
14141
|
}
|
|
13974
14142
|
});
|
|
13975
14143
|
}
|
|
13976
14144
|
async baseCleanup(restore = true) {
|
|
13977
|
-
var _a4;
|
|
13978
14145
|
this._stopEffects.forEach((fn) => fn());
|
|
13979
14146
|
try {
|
|
13980
14147
|
if (restore && this._source && this._target) {
|
|
13981
|
-
if (await removeHost(this._source.
|
|
14148
|
+
if (await removeHost(splitHostPort(this._source).host, splitHostPort(this._target).host))
|
|
13982
14149
|
consola.success("Restore host success.\n");
|
|
13983
14150
|
else
|
|
13984
14151
|
consola.fail("Restore host failed.\n");
|
|
@@ -13988,7 +14155,7 @@ ${line}
|
|
|
13988
14155
|
consola.fail("Restore host failed.\n");
|
|
13989
14156
|
}
|
|
13990
14157
|
if (!this.locked && !this.stoped) {
|
|
13991
|
-
|
|
14158
|
+
await this.stopCaddy();
|
|
13992
14159
|
try {
|
|
13993
14160
|
await lockfile.unlock(caddyLockFilePath).catch(() => {
|
|
13994
14161
|
});
|
package/dist/esbuild.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");
|
|
@@ -13859,6 +13950,17 @@ function getCaddyConfig() {
|
|
|
13859
13950
|
}
|
|
13860
13951
|
return caddyConfig;
|
|
13861
13952
|
}
|
|
13953
|
+
function splitHostPort(addr) {
|
|
13954
|
+
const lastColon = addr.lastIndexOf(":");
|
|
13955
|
+
if (lastColon === -1)
|
|
13956
|
+
return { host: addr, port: "" };
|
|
13957
|
+
if (addr.startsWith("[")) {
|
|
13958
|
+
const end = addr.indexOf("]");
|
|
13959
|
+
if (end !== -1 && addr[end + 1] === ":")
|
|
13960
|
+
return { host: addr.slice(1, end), port: addr.slice(end + 2) };
|
|
13961
|
+
}
|
|
13962
|
+
return { host: addr.slice(0, lastColon), port: addr.slice(lastColon + 1) };
|
|
13963
|
+
}
|
|
13862
13964
|
var CaddyInstant = class {
|
|
13863
13965
|
constructor() {
|
|
13864
13966
|
this.inited = false;
|
|
@@ -13900,12 +14002,46 @@ var CaddyInstant = class {
|
|
|
13900
14002
|
await download();
|
|
13901
14003
|
this.inited = true;
|
|
13902
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
|
+
}
|
|
13903
14038
|
/**
|
|
13904
14039
|
* @param source like `127.0.0.1:8080`
|
|
13905
14040
|
* @param target like `test.abc.com`. And if you provide a port ,it will be ignore.
|
|
13906
14041
|
*/
|
|
13907
14042
|
async run(source, target, options) {
|
|
13908
14043
|
source = source.replace("0.0.0.0", "127.0.0.1");
|
|
14044
|
+
source = source.replace(/^localhost(?=:)/i, "127.0.0.1");
|
|
13909
14045
|
const {
|
|
13910
14046
|
restore = true,
|
|
13911
14047
|
base = "/",
|
|
@@ -13917,10 +14053,11 @@ var CaddyInstant = class {
|
|
|
13917
14053
|
this._target = target;
|
|
13918
14054
|
if (!this.inited)
|
|
13919
14055
|
await this.init();
|
|
13920
|
-
|
|
14056
|
+
const sourceHost = splitHostPort(source).host;
|
|
14057
|
+
const targetHost = splitHostPort(target).host;
|
|
14058
|
+
if (!await addHost(sourceHost, targetHost))
|
|
13921
14059
|
throw new Error("update host failed");
|
|
13922
14060
|
consola.success("update host success\n");
|
|
13923
|
-
const targetHost = target.split(":")[0];
|
|
13924
14061
|
const normalizeBase = (b) => {
|
|
13925
14062
|
let out = b || "/";
|
|
13926
14063
|
if (!out.startsWith("/"))
|
|
@@ -13942,16 +14079,16 @@ var CaddyInstant = class {
|
|
|
13942
14079
|
];
|
|
13943
14080
|
const { writeCaddyConfig } = getCaddyConfig();
|
|
13944
14081
|
writeCaddyConfig(proxies);
|
|
14082
|
+
await this.updateCaddyfile();
|
|
14083
|
+
let skipInitialCaddyfileEffect = true;
|
|
13945
14084
|
this._stopEffects.push(
|
|
13946
|
-
effect(
|
|
13947
|
-
|
|
13948
|
-
|
|
13949
|
-
|
|
13950
|
-
|
|
13951
|
-
|
|
13952
|
-
|
|
13953
|
-
this.caddyfile = await genCaddyfile(ctx);
|
|
13954
|
-
await this.writeCaddyfile();
|
|
14085
|
+
effect(() => {
|
|
14086
|
+
getCaddyConfig().configJsonRef();
|
|
14087
|
+
if (skipInitialCaddyfileEffect) {
|
|
14088
|
+
skipInitialCaddyfileEffect = false;
|
|
14089
|
+
return;
|
|
14090
|
+
}
|
|
14091
|
+
void this.updateCaddyfile();
|
|
13955
14092
|
})
|
|
13956
14093
|
);
|
|
13957
14094
|
if (!(0, import_node_fs3.existsSync)(caddyLockFilePath))
|
|
@@ -13964,6 +14101,21 @@ var CaddyInstant = class {
|
|
|
13964
14101
|
}
|
|
13965
14102
|
return new Promise((resolve2, reject2) => {
|
|
13966
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
|
+
};
|
|
13967
14119
|
const setupCleanup = () => {
|
|
13968
14120
|
import_node_process4.default.on("SIGINT", async () => {
|
|
13969
14121
|
if (this.stoped)
|
|
@@ -13980,7 +14132,7 @@ var CaddyInstant = class {
|
|
|
13980
14132
|
});
|
|
13981
14133
|
const originalExit = import_node_process4.default.exit.bind(import_node_process4.default);
|
|
13982
14134
|
import_node_process4.default.exit = async (code) => {
|
|
13983
|
-
const port = Number(source.
|
|
14135
|
+
const port = Number(splitHostPort(source).port);
|
|
13984
14136
|
if (!Number.isNaN(port) && await tryPort(port))
|
|
13985
14137
|
await kill(port);
|
|
13986
14138
|
const pwd = import_node_process4.default.cwd();
|
|
@@ -13988,6 +14140,10 @@ var CaddyInstant = class {
|
|
|
13988
14140
|
if ((0, import_node_fs3.existsSync)(viteCacheDir))
|
|
13989
14141
|
await chmodRecursive(viteCacheDir, 511).catch(() => {
|
|
13990
14142
|
});
|
|
14143
|
+
const viteTempCacheDir = `${pwd}/node_modules/.vite-temp`;
|
|
14144
|
+
if ((0, import_node_fs3.existsSync)(viteTempCacheDir))
|
|
14145
|
+
await chmodRecursive(viteTempCacheDir, 511).catch(() => {
|
|
14146
|
+
});
|
|
13991
14147
|
const nuxtCacheDir = `${pwd}/.nuxt`;
|
|
13992
14148
|
if ((0, import_node_fs3.existsSync)(nuxtCacheDir))
|
|
13993
14149
|
await chmodRecursive(nuxtCacheDir, 511).catch(() => {
|
|
@@ -14019,6 +14175,10 @@ var CaddyInstant = class {
|
|
|
14019
14175
|
const lines = data.toString().split("\n").map((line) => line.trim());
|
|
14020
14176
|
for (const line of lines) {
|
|
14021
14177
|
showCaddyLog && line && console.info(line);
|
|
14178
|
+
if (isCaddyReloadCancellation(line)) {
|
|
14179
|
+
consola.info("Caddy restarted before TLS issuance completed; retrying.\n");
|
|
14180
|
+
continue;
|
|
14181
|
+
}
|
|
14022
14182
|
try {
|
|
14023
14183
|
if (line.includes("Error:") || line && JSON.parse(line).level === "error") {
|
|
14024
14184
|
if (line.includes("parsing caddyfile tokens")) {
|
|
@@ -14039,27 +14199,34 @@ ${line}
|
|
|
14039
14199
|
if (line.includes("config file changed"))
|
|
14040
14200
|
consola.success("Detect added a new reverse proxy config, restarted.\n");
|
|
14041
14201
|
if (line.includes("caddy proxying") || line.includes("serving initial"))
|
|
14042
|
-
|
|
14202
|
+
void resolveWhenReady();
|
|
14043
14203
|
}
|
|
14044
14204
|
});
|
|
14045
14205
|
(_b3 = this._caddyChild.stdout) == null ? void 0 : _b3.on("data", (_data) => {
|
|
14046
14206
|
consola.info(_data.toString());
|
|
14047
|
-
|
|
14207
|
+
void resolveWhenReady();
|
|
14048
14208
|
});
|
|
14049
14209
|
setupCleanup();
|
|
14050
14210
|
} else {
|
|
14051
14211
|
consola.info("Caddy is running in another process.");
|
|
14052
|
-
|
|
14053
|
-
|
|
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
|
+
})();
|
|
14054
14222
|
}
|
|
14055
14223
|
});
|
|
14056
14224
|
}
|
|
14057
14225
|
async baseCleanup(restore = true) {
|
|
14058
|
-
var _a4;
|
|
14059
14226
|
this._stopEffects.forEach((fn) => fn());
|
|
14060
14227
|
try {
|
|
14061
14228
|
if (restore && this._source && this._target) {
|
|
14062
|
-
if (await removeHost(this._source.
|
|
14229
|
+
if (await removeHost(splitHostPort(this._source).host, splitHostPort(this._target).host))
|
|
14063
14230
|
consola.success("Restore host success.\n");
|
|
14064
14231
|
else
|
|
14065
14232
|
consola.fail("Restore host failed.\n");
|
|
@@ -14069,7 +14236,7 @@ ${line}
|
|
|
14069
14236
|
consola.fail("Restore host failed.\n");
|
|
14070
14237
|
}
|
|
14071
14238
|
if (!this.locked && !this.stoped) {
|
|
14072
|
-
|
|
14239
|
+
await this.stopCaddy();
|
|
14073
14240
|
try {
|
|
14074
14241
|
await lockfile.unlock(caddyLockFilePath).catch(() => {
|
|
14075
14242
|
});
|