unplugin-https-reverse-proxy 4.0.3 → 4.1.0-beta.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -6
- package/dist/{chunk-RSBXFJ3Z.js → chunk-C5A7XLKL.js} +9 -2
- package/dist/{chunk-2P7SUCQ3.js → chunk-EY3HXBJ4.js} +0 -26
- package/dist/chunk-RKHJN6KY.js +53 -0
- package/dist/{chunk-MD5CVZP7.js → chunk-U7KAIPZC.js} +982 -797
- package/dist/chunk-WOMR3ZLM.js +17 -0
- package/dist/esbuild.cjs +1086 -867
- package/dist/esbuild.js +5 -3
- package/dist/hmr-sse-bridge.cjs +12 -4
- package/dist/hmr-sse-bridge.d.cts +4 -3
- package/dist/hmr-sse-bridge.d.ts +4 -3
- package/dist/hmr-sse-bridge.js +5 -3
- package/dist/index.cjs +1086 -867
- package/dist/index.js +5 -3
- package/dist/nuxt.cjs +1057 -852
- package/dist/nuxt.js +6 -9
- package/dist/privilege-state.cjs +44 -0
- package/dist/privilege-state.d.cts +7 -0
- package/dist/privilege-state.d.ts +7 -0
- package/dist/privilege-state.js +10 -0
- package/dist/privileged-helper.cjs +824 -0
- package/dist/privileged-helper.d.cts +2 -0
- package/dist/privileged-helper.d.ts +2 -0
- package/dist/privileged-helper.js +797 -0
- package/dist/rollup.cjs +1086 -867
- package/dist/rollup.js +5 -3
- package/dist/rspack.cjs +1086 -867
- package/dist/rspack.js +5 -3
- package/dist/utils.cjs +0 -28
- package/dist/utils.d.cts +1 -3
- package/dist/utils.d.ts +1 -3
- package/dist/utils.js +1 -5
- package/dist/vite.cjs +1086 -867
- package/dist/vite.js +5 -3
- package/dist/webpack.cjs +1086 -867
- package/dist/webpack.js +5 -3
- package/package.json +1 -4
- package/src/caddy/caddyfile.ts +3 -0
- package/src/caddy/config.ts +195 -53
- package/src/caddy/constants.ts +30 -1
- package/src/caddy/index.ts +239 -206
- package/src/caddy/privileged.ts +124 -0
- package/src/caddy/utils.ts +0 -43
- package/src/hmr-sse-bridge.ts +14 -3
- package/src/index.ts +52 -25
- package/src/nuxt.ts +1 -6
- package/src/privilege-state.ts +23 -0
- package/src/privileged/bootstrap.ts +289 -0
- package/src/privileged/client.ts +288 -0
- package/src/privileged/entry.ts +73 -0
- package/src/privileged/hosts-file.ts +142 -0
- package/src/privileged/launch.ts +332 -0
- package/src/privileged/path-guard.ts +74 -0
- package/src/privileged/ports.ts +45 -0
- package/src/privileged/protocol.ts +111 -0
- package/src/privileged/server.ts +578 -0
- package/src/privileged/session.ts +169 -0
- package/src/privileged/validation.ts +38 -0
- package/src/privileged/windows-elevation.ts +80 -0
- package/src/privileged-helper.ts +123 -0
- package/src/utils.ts +0 -28
- package/src/host/index.ts +0 -52
package/README.md
CHANGED
|
@@ -314,15 +314,39 @@ Please check [caddy path](https://github.com/zcf0508/unplugin-https-reverse-prox
|
|
|
314
314
|
## Usage
|
|
315
315
|
|
|
316
316
|
```bash
|
|
317
|
-
# macOS
|
|
318
|
-
sudo -E npm run dev # your dev script
|
|
319
|
-
# ^ `-E` is important
|
|
320
|
-
|
|
321
|
-
# windows
|
|
322
|
-
# use powershell as administrator
|
|
317
|
+
# macOS / Linux / Windows
|
|
323
318
|
npm run dev # your dev script
|
|
324
319
|
```
|
|
325
320
|
|
|
321
|
+
Run it as your normal user. The plugin starts a small privileged helper that
|
|
322
|
+
runs as administrator, and only that helper touches `/etc/hosts` and ports
|
|
323
|
+
80/443. Your dev server, its caches and `node_modules` stay owned by you.
|
|
324
|
+
|
|
325
|
+
On macOS and Linux the plugin asks for your password once when the dev server
|
|
326
|
+
starts, then reuses the sudo credential for the rest of the session. If you
|
|
327
|
+
already ran `sudo -v` in the same terminal, no prompt is shown.
|
|
328
|
+
|
|
329
|
+
The helper restores the hosts entries by itself when the dev server exits,
|
|
330
|
+
including when it is killed or crashes.
|
|
331
|
+
|
|
332
|
+
### Granting the permission once (optional)
|
|
333
|
+
|
|
334
|
+
To skip the password prompt entirely, allow the plugin's helper in
|
|
335
|
+
`/etc/sudoers.d/` (edit with `sudo visudo -f /etc/sudoers.d/uhrp`):
|
|
336
|
+
|
|
337
|
+
```
|
|
338
|
+
yourname ALL=(root) NOPASSWD: /usr/bin/killall -HUP mDNSResponder
|
|
339
|
+
yourname ALL=(root) NOPASSWD: /usr/bin/install -m 644 -o root -g wheel /tmp/uhrp-hosts.* /etc/hosts
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
The second rule only matters when the helper rewrites `/etc/hosts` through
|
|
343
|
+
`install`; adjust the paths to your platform.
|
|
344
|
+
|
|
345
|
+
### Windows
|
|
346
|
+
|
|
347
|
+
Run `npm run dev` normally. Windows raises a UAC prompt once, when the helper
|
|
348
|
+
is started through `Start-Process -Verb RunAs`.
|
|
349
|
+
|
|
326
350
|
If your broswer shows a not trusted certificate warning, please check the keychain.
|
|
327
351
|
|
|
328
352
|

|
|
@@ -99,10 +99,16 @@ function handleClientMessage(req, res, server) {
|
|
|
99
99
|
}
|
|
100
100
|
});
|
|
101
101
|
}
|
|
102
|
+
function shouldUseHmrSseBridge(protocol, userAgent) {
|
|
103
|
+
if (protocol !== "https:")
|
|
104
|
+
return false;
|
|
105
|
+
const isApplePlatform = /Macintosh|iPhone|iPad|iPod/.test(userAgent);
|
|
106
|
+
const isSafari = /Version\//.test(userAgent) && /Safari\//.test(userAgent) && !/(?:Chrome|Chromium|CriOS|Edg|EdgiOS|OPR|OPiOS|Firefox|FxiOS)\//.test(userAgent);
|
|
107
|
+
return isApplePlatform && isSafari;
|
|
108
|
+
}
|
|
102
109
|
var hmrSseBridgeClientScript = `
|
|
103
110
|
(function() {
|
|
104
|
-
|
|
105
|
-
if (location.protocol !== 'https:') return;
|
|
111
|
+
if (!(${shouldUseHmrSseBridge.toString()})(location.protocol, navigator.userAgent)) return;
|
|
106
112
|
|
|
107
113
|
var OriginalWebSocket = window.WebSocket;
|
|
108
114
|
|
|
@@ -228,5 +234,6 @@ var hmrSseBridgeClientScript = `
|
|
|
228
234
|
|
|
229
235
|
export {
|
|
230
236
|
setupHmrSseBridge,
|
|
237
|
+
shouldUseHmrSseBridge,
|
|
231
238
|
hmrSseBridgeClientScript
|
|
232
239
|
};
|
|
@@ -1,23 +1,11 @@
|
|
|
1
1
|
// src/utils.ts
|
|
2
|
-
import { execSync } from "node:child_process";
|
|
3
|
-
import { chmod, readdir, stat } from "node:fs/promises";
|
|
4
2
|
import { networkInterfaces } from "node:os";
|
|
5
|
-
import path from "node:path";
|
|
6
|
-
import process from "node:process";
|
|
7
3
|
import { createConsola } from "consola";
|
|
8
4
|
import c from "picocolors";
|
|
9
5
|
import qrcode from "qrcode-terminal";
|
|
10
6
|
var consola = createConsola({
|
|
11
7
|
level: 3
|
|
12
8
|
}).withTag("reverse-proxy");
|
|
13
|
-
async function chmodRecursive(_path, mode) {
|
|
14
|
-
await chmod(_path, mode);
|
|
15
|
-
if ((await stat(_path)).isDirectory()) {
|
|
16
|
-
const children = await readdir(_path);
|
|
17
|
-
for (const child of children)
|
|
18
|
-
await chmodRecursive(path.join(_path, child), mode);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
9
|
function once(fn) {
|
|
22
10
|
let called = false;
|
|
23
11
|
return (...args) => {
|
|
@@ -27,18 +15,6 @@ function once(fn) {
|
|
|
27
15
|
return fn(...args);
|
|
28
16
|
};
|
|
29
17
|
}
|
|
30
|
-
function isAdmin() {
|
|
31
|
-
if (process.platform === "win32") {
|
|
32
|
-
try {
|
|
33
|
-
execSync("net session", { stdio: "ignore" });
|
|
34
|
-
return true;
|
|
35
|
-
} catch {
|
|
36
|
-
return false;
|
|
37
|
-
}
|
|
38
|
-
} else {
|
|
39
|
-
return !!(process.getuid && process.getuid() === 0);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
18
|
function getIpv4List() {
|
|
43
19
|
const interfaces = networkInterfaces();
|
|
44
20
|
return Object.values(interfaces).flatMap((nInterface) => nInterface ?? []).filter(
|
|
@@ -55,9 +31,7 @@ async function generateQrcode(input) {
|
|
|
55
31
|
|
|
56
32
|
export {
|
|
57
33
|
consola,
|
|
58
|
-
chmodRecursive,
|
|
59
34
|
once,
|
|
60
|
-
isAdmin,
|
|
61
35
|
getIpv4List,
|
|
62
36
|
generateQrcode
|
|
63
37
|
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// src/privileged/protocol.ts
|
|
2
|
+
function serializeMessage(message) {
|
|
3
|
+
return `${JSON.stringify(message)}
|
|
4
|
+
`;
|
|
5
|
+
}
|
|
6
|
+
function splitLines(buffer, chunk) {
|
|
7
|
+
const parts = (buffer + chunk).split("\n");
|
|
8
|
+
const rest = parts.pop() ?? "";
|
|
9
|
+
return { lines: parts.filter((line) => line.trim() !== ""), rest };
|
|
10
|
+
}
|
|
11
|
+
function isRecord(value) {
|
|
12
|
+
return typeof value === "object" && value !== null;
|
|
13
|
+
}
|
|
14
|
+
function decodeMessage(line) {
|
|
15
|
+
let parsed;
|
|
16
|
+
try {
|
|
17
|
+
parsed = JSON.parse(line);
|
|
18
|
+
} catch (error) {
|
|
19
|
+
return { ok: false, error: `invalid JSON: ${error.message}` };
|
|
20
|
+
}
|
|
21
|
+
if (!isRecord(parsed))
|
|
22
|
+
return { ok: false, error: "message must be an object" };
|
|
23
|
+
if (parsed.type === "event") {
|
|
24
|
+
if (typeof parsed.kind !== "string")
|
|
25
|
+
return { ok: false, error: "event.kind must be a string" };
|
|
26
|
+
return { ok: true, message: parsed };
|
|
27
|
+
}
|
|
28
|
+
if (typeof parsed.id !== "number")
|
|
29
|
+
return { ok: false, error: "response.id must be a number" };
|
|
30
|
+
if (parsed.ok === true)
|
|
31
|
+
return { ok: true, message: { id: parsed.id, ok: true, result: parsed.result } };
|
|
32
|
+
if (parsed.ok === false) {
|
|
33
|
+
const error = isRecord(parsed.error) ? parsed.error : {};
|
|
34
|
+
return {
|
|
35
|
+
ok: true,
|
|
36
|
+
message: {
|
|
37
|
+
id: parsed.id,
|
|
38
|
+
ok: false,
|
|
39
|
+
error: {
|
|
40
|
+
message: typeof error.message === "string" ? error.message : "helper request failed",
|
|
41
|
+
code: typeof error.code === "string" ? error.code : void 0
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
return { ok: false, error: "response.ok must be a boolean" };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export {
|
|
50
|
+
serializeMessage,
|
|
51
|
+
splitLines,
|
|
52
|
+
decodeMessage
|
|
53
|
+
};
|