unplugin-https-reverse-proxy 1.0.0-beta.2 → 1.0.0-beta.20
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 +105 -2
- package/dist/chunk-2VGRJ3QS.js +45 -0
- package/dist/chunk-I6DP2OII.js +695 -0
- package/dist/esbuild.cjs +334 -160
- package/dist/esbuild.js +2 -2
- package/dist/index.cjs +334 -160
- package/dist/index.d.cts +1 -2
- package/dist/index.d.ts +1 -2
- package/dist/index.js +2 -2
- package/dist/nuxt.cjs +270 -234
- package/dist/nuxt.js +24 -22
- package/dist/rollup.cjs +334 -160
- package/dist/rollup.js +2 -2
- package/dist/rspack.cjs +760 -0
- package/dist/rspack.d.cts +5 -0
- package/dist/rspack.d.ts +5 -0
- package/dist/rspack.js +10 -0
- package/dist/types.cjs +1 -1
- package/dist/utils.cjs +2 -2
- package/dist/utils.js +1 -1
- package/dist/vite.cjs +334 -160
- package/dist/vite.d.cts +1 -2
- package/dist/vite.d.ts +1 -2
- package/dist/vite.js +7 -4
- package/dist/webpack.cjs +334 -160
- package/dist/webpack.js +7 -4
- package/package.json +48 -28
- package/scripts/postinstall.cjs +308 -0
- package/src/caddy/constants.ts +14 -1
- package/src/caddy/index.ts +230 -76
- package/src/caddy/utils.ts +18 -0
- package/src/host/index.ts +9 -15
- package/src/index.ts +110 -83
- package/src/nuxt.ts +26 -19
- package/src/rspack.ts +5 -0
- package/dist/chunk-DDD5N75Y.js +0 -11
- package/dist/chunk-N6ZBBGYD.js +0 -516
- package/dist/chunk-RUJE3YFB.js +0 -63
- package/dist/chunk-VGLXVBHU.js +0 -11
- package/scripts/postinstall.ts +0 -19
package/src/caddy/index.ts
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { platform } from 'node:os'
|
|
2
2
|
import process from 'node:process'
|
|
3
|
-
import { chmodSync, createWriteStream, existsSync, unlinkSync } from 'node:fs'
|
|
3
|
+
import { chmodSync, createWriteStream, existsSync, mkdirSync, unlinkSync, writeFileSync } from 'node:fs'
|
|
4
4
|
import { spawn } from 'node:child_process'
|
|
5
|
+
import { readFile, unlink, writeFile } from 'node:fs/promises'
|
|
5
6
|
import { got } from 'got-cjs'
|
|
6
7
|
import { HttpProxyAgent } from 'http-proxy-agent'
|
|
7
8
|
import { HttpsProxyAgent } from 'https-proxy-agent'
|
|
8
|
-
import
|
|
9
|
-
import { consola } from '../utils'
|
|
9
|
+
import * as lockfile from 'proper-lockfile'
|
|
10
|
+
import { chmodRecursive, consola, once } from '../utils'
|
|
10
11
|
import { addHost, removeHost } from '../host'
|
|
11
|
-
import { caddyPath, supportList } from './constants'
|
|
12
|
-
import { logProgress, logProgressOver, tryPort } from './utils'
|
|
12
|
+
import { TEMP_DIR, caddyFilePath, caddyLockFilePath, caddyPath, supportList } from './constants'
|
|
13
|
+
import { kill, logProgress, logProgressOver, tryPort } from './utils'
|
|
13
14
|
|
|
14
15
|
export async function download() {
|
|
15
16
|
if (await testCaddy())
|
|
@@ -18,6 +19,11 @@ export async function download() {
|
|
|
18
19
|
return new Promise<string>((resolve, reject) => {
|
|
19
20
|
// https://caddyserver.com/api/download?os=darwin&arch=amd64
|
|
20
21
|
|
|
22
|
+
if (!existsSync(TEMP_DIR)) {
|
|
23
|
+
mkdirSync(TEMP_DIR, { recursive: true })
|
|
24
|
+
chmodSync(TEMP_DIR, 0o777)
|
|
25
|
+
}
|
|
26
|
+
|
|
21
27
|
const file = createWriteStream(caddyPath)
|
|
22
28
|
|
|
23
29
|
let _platform = platform().toString()
|
|
@@ -42,6 +48,11 @@ export async function download() {
|
|
|
42
48
|
const httpAgent = httpProxy ? new HttpProxyAgent(httpProxy) : undefined
|
|
43
49
|
const httpsAgent = httpsProxy ? new HttpsProxyAgent(httpsProxy) : undefined
|
|
44
50
|
|
|
51
|
+
const chmodCaddyOnce = once(() => {
|
|
52
|
+
// chmod +x
|
|
53
|
+
chmodSync(caddyPath, 0o777)
|
|
54
|
+
})
|
|
55
|
+
|
|
45
56
|
got.stream(dowmloadLink, {
|
|
46
57
|
agent: {
|
|
47
58
|
http: httpAgent,
|
|
@@ -49,12 +60,13 @@ export async function download() {
|
|
|
49
60
|
},
|
|
50
61
|
}).on('downloadProgress', (progress) => {
|
|
51
62
|
logProgress(progress.percent)
|
|
63
|
+
chmodCaddyOnce()
|
|
52
64
|
}).pipe(file).on('finish', () => {
|
|
53
65
|
logProgressOver()
|
|
54
66
|
if (process.platform === 'win32')
|
|
55
67
|
return resolve(caddyPath)
|
|
56
68
|
// chmod +x
|
|
57
|
-
chmodSync(caddyPath,
|
|
69
|
+
chmodSync(caddyPath, 0o777)
|
|
58
70
|
resolve(caddyPath)
|
|
59
71
|
}).on('error', (err) => {
|
|
60
72
|
// consola.error(err)
|
|
@@ -67,7 +79,7 @@ function testCaddy() {
|
|
|
67
79
|
return new Promise((resolve, reject) => {
|
|
68
80
|
if (!existsSync(caddyPath))
|
|
69
81
|
return resolve(false)
|
|
70
|
-
chmodSync(caddyPath,
|
|
82
|
+
chmodSync(caddyPath, 0o777)
|
|
71
83
|
const child = process.platform === 'win32' ? spawn(caddyPath, []) : spawn('sudo', ['-E', caddyPath])
|
|
72
84
|
child.on('close', () => {
|
|
73
85
|
return resolve(false)
|
|
@@ -92,10 +104,57 @@ export class CaddyInstant {
|
|
|
92
104
|
private inited = false
|
|
93
105
|
private stoped = false
|
|
94
106
|
|
|
107
|
+
/** has locked */
|
|
108
|
+
private locked = false
|
|
109
|
+
private caddyfile: string | undefined
|
|
110
|
+
|
|
111
|
+
private _caddyChild: ReturnType<typeof spawn> | undefined
|
|
112
|
+
|
|
113
|
+
private _source: string | undefined
|
|
114
|
+
private _target: string | undefined
|
|
115
|
+
|
|
95
116
|
constructor() {
|
|
96
|
-
testCaddy().then(() => {
|
|
117
|
+
testCaddy().then(async () => {
|
|
118
|
+
await this.getCaddyfile()
|
|
119
|
+
|
|
97
120
|
this.inited = true
|
|
98
121
|
})
|
|
122
|
+
|
|
123
|
+
this.locked = this.checkLock()
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
checkLock() {
|
|
127
|
+
if (!existsSync(caddyLockFilePath))
|
|
128
|
+
writeFileSync(caddyLockFilePath, '')
|
|
129
|
+
return lockfile.checkSync(caddyLockFilePath)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
async getCaddyfile() {
|
|
133
|
+
if (!existsSync(caddyFilePath))
|
|
134
|
+
await this.initCaddyfile()
|
|
135
|
+
|
|
136
|
+
this.caddyfile = await readFile(caddyFilePath, 'utf-8')
|
|
137
|
+
return this.caddyfile
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
async initCaddyfile() {
|
|
141
|
+
const contet = `
|
|
142
|
+
{
|
|
143
|
+
debug
|
|
144
|
+
auto_https disable_redirects
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
`
|
|
148
|
+
await writeFile(caddyFilePath, contet)
|
|
149
|
+
this.caddyfile = contet
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
async writeCaddyfile() {
|
|
153
|
+
return await writeFile(caddyFilePath, this.caddyfile || '')
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
async deleteCaddyfile() {
|
|
157
|
+
return await unlink(caddyFilePath)
|
|
99
158
|
}
|
|
100
159
|
|
|
101
160
|
async init() {
|
|
@@ -117,95 +176,190 @@ export class CaddyInstant {
|
|
|
117
176
|
https = false,
|
|
118
177
|
} = options || {}
|
|
119
178
|
|
|
179
|
+
this._source = source
|
|
180
|
+
this._target = target
|
|
181
|
+
|
|
120
182
|
if (!this.inited)
|
|
121
183
|
await this.init()
|
|
122
184
|
|
|
123
|
-
if (https && await tryPort(443))
|
|
124
|
-
await kill(443, 'tcp')
|
|
125
|
-
if ((process.platform === 'win32' || !https) && await tryPort(80))
|
|
126
|
-
await kill(80, 'tcp')
|
|
127
|
-
|
|
128
185
|
if (!await addHost(source.split(':')[0], target.split(':')[0]))
|
|
129
186
|
throw new Error('update host failed')
|
|
130
187
|
consola.success('update host success\n')
|
|
131
188
|
|
|
189
|
+
await this.getCaddyfile()
|
|
190
|
+
|
|
191
|
+
if (!(this.caddyfile || '').includes(`${target.split(':')[0]}${https ? '' : ':80'}`)) {
|
|
192
|
+
this.caddyfile = `${this.caddyfile}
|
|
193
|
+
${target.split(':')[0]}${https ? '' : ':80'} {
|
|
194
|
+
${https ? 'tls internal' : ''}
|
|
195
|
+
reverse_proxy http://${source} {
|
|
196
|
+
health_uri /
|
|
197
|
+
health_interval 2s
|
|
198
|
+
health_timeout 5s
|
|
199
|
+
fail_duration 2s
|
|
200
|
+
unhealthy_status 502 503 504 404
|
|
201
|
+
lb_try_duration 3s
|
|
202
|
+
lb_try_interval 300ms
|
|
203
|
+
|
|
204
|
+
@error status 502 503 504 404
|
|
205
|
+
handle_response @error {
|
|
206
|
+
respond * 503 {
|
|
207
|
+
body "Service Unavailable"
|
|
208
|
+
close
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
`
|
|
215
|
+
|
|
216
|
+
await this.writeCaddyfile()
|
|
217
|
+
}
|
|
218
|
+
if (!existsSync(caddyLockFilePath))
|
|
219
|
+
writeFileSync(caddyLockFilePath, '')
|
|
220
|
+
|
|
221
|
+
if (!this.locked) {
|
|
222
|
+
if (await tryPort(443))
|
|
223
|
+
await kill(443)
|
|
224
|
+
if ((process.platform === 'win32' || !https) && await tryPort(80))
|
|
225
|
+
await kill(80)
|
|
226
|
+
}
|
|
227
|
+
|
|
132
228
|
return new Promise<void>((resolve, reject) => {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
229
|
+
const setupCleanup = () => {
|
|
230
|
+
process.on('SIGINT', async () => {
|
|
231
|
+
if (this.stoped)
|
|
232
|
+
return
|
|
137
233
|
|
|
138
|
-
|
|
139
|
-
return reject(err)
|
|
140
|
-
})
|
|
234
|
+
process.stdin.resume()
|
|
141
235
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
236
|
+
try {
|
|
237
|
+
await this.baseCleanup(restore)
|
|
238
|
+
}
|
|
239
|
+
finally {
|
|
240
|
+
this.stoped = true
|
|
241
|
+
process.nextTick(() => {
|
|
242
|
+
process.exit()
|
|
243
|
+
})
|
|
244
|
+
}
|
|
245
|
+
})
|
|
145
246
|
|
|
146
|
-
|
|
147
|
-
if (await removeHost(source.split(':')[0], target.split(':')[0]))
|
|
148
|
-
consola.success('restore host success\n')
|
|
247
|
+
const originalExit = process.exit.bind(process)
|
|
149
248
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
consola.fail('restore host failed\n')
|
|
156
|
-
}
|
|
157
|
-
finally {
|
|
158
|
-
this.stoped = true
|
|
159
|
-
process.nextTick(() => {
|
|
160
|
-
process.exit()
|
|
161
|
-
})
|
|
162
|
-
}
|
|
163
|
-
})
|
|
249
|
+
// @ts-expect-error override
|
|
250
|
+
process.exit = async (code?: number) => {
|
|
251
|
+
const port = Number(source.split(':')[1])
|
|
252
|
+
if (!Number.isNaN(port) && await tryPort(port))
|
|
253
|
+
await kill(port)
|
|
164
254
|
|
|
165
|
-
|
|
255
|
+
// fix `Error: EPERM: operation not permitted`
|
|
256
|
+
const pwd = process.cwd()
|
|
257
|
+
const viteCacheDir = `${pwd}/node_modules/.vite`
|
|
258
|
+
if (existsSync(viteCacheDir))
|
|
259
|
+
await chmodRecursive(viteCacheDir, 0o777).catch(() => { })
|
|
260
|
+
const nuxtCacheDir = `${pwd}/.nuxt`
|
|
261
|
+
if (existsSync(nuxtCacheDir))
|
|
262
|
+
await chmodRecursive(nuxtCacheDir, 0o777).catch(() => { })
|
|
263
|
+
const webpackCacheDir = `${pwd}/node_modules/.cache`
|
|
264
|
+
if (existsSync(webpackCacheDir))
|
|
265
|
+
await chmodRecursive(webpackCacheDir, 0o777).catch(() => { })
|
|
166
266
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
if (!restore || this.stoped)
|
|
170
|
-
return originalExit(code)
|
|
267
|
+
if (this.stoped)
|
|
268
|
+
return originalExit(code)
|
|
171
269
|
|
|
172
|
-
|
|
173
|
-
if (await removeHost(source.split(':')[0], target.split(':')[0]))
|
|
174
|
-
consola.success('restore host success\n')
|
|
270
|
+
process.stdin.resume()
|
|
175
271
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
originalExit(code)
|
|
187
|
-
})
|
|
272
|
+
try {
|
|
273
|
+
await this.baseCleanup()
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
finally {
|
|
277
|
+
this.stoped = true
|
|
278
|
+
process.nextTick(() => {
|
|
279
|
+
originalExit(code)
|
|
280
|
+
})
|
|
281
|
+
}
|
|
188
282
|
}
|
|
189
283
|
}
|
|
190
284
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
285
|
+
if (!this.locked) {
|
|
286
|
+
this._caddyChild = process.platform !== 'win32'
|
|
287
|
+
? spawn('sudo', ['-E', caddyPath, 'run', '--config', caddyFilePath, '--watch'])
|
|
288
|
+
: spawn(caddyPath, ['run', '--config', caddyFilePath, '--watch'])
|
|
289
|
+
|
|
290
|
+
lockfile.lockSync(caddyLockFilePath)
|
|
291
|
+
|
|
292
|
+
this._caddyChild!.on('error', (err) => {
|
|
293
|
+
return reject(err)
|
|
294
|
+
})
|
|
295
|
+
|
|
296
|
+
this._caddyChild!.stderr?.on('data', async (data) => {
|
|
297
|
+
const lines = (data.toString() as string).split('\n').map(line => line.trim())
|
|
298
|
+
for (const line of lines) {
|
|
299
|
+
// caddy log
|
|
300
|
+
// eslint-disable-next-line no-console
|
|
301
|
+
showCaddyLog && line && console.info(line)
|
|
302
|
+
if (line.includes('Error:') || (line && JSON.parse(line).level === 'error')) {
|
|
303
|
+
if (line.includes('parsing caddyfile tokens')) {
|
|
304
|
+
consola.error('Caddyfile syntax error, please contact the author:\n', `${this.caddyfile}\n\n${line}\n`)
|
|
305
|
+
await this.baseCleanup()
|
|
306
|
+
process.exit()
|
|
307
|
+
}
|
|
308
|
+
else {
|
|
309
|
+
consola.error(`${line}\n`)
|
|
310
|
+
// child.kill()
|
|
311
|
+
return reject(line)
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
if (line.includes('config file changed'))
|
|
315
|
+
consola.success('Detect added a new reverse proxy config, restarted.\n')
|
|
316
|
+
|
|
317
|
+
if (line.includes('caddy proxying') || line.includes('serving initial'))
|
|
318
|
+
return resolve()
|
|
201
319
|
}
|
|
202
|
-
}
|
|
203
|
-
|
|
320
|
+
})
|
|
321
|
+
|
|
322
|
+
this._caddyChild!.stdout?.on('data', (_data) => {
|
|
323
|
+
consola.info(_data.toString())
|
|
324
|
+
resolve()
|
|
325
|
+
})
|
|
326
|
+
|
|
327
|
+
setupCleanup()
|
|
328
|
+
}
|
|
329
|
+
else {
|
|
330
|
+
consola.info('Caddy is running in another process.')
|
|
331
|
+
|
|
332
|
+
setupCleanup()
|
|
204
333
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
resolve()
|
|
208
|
-
})
|
|
334
|
+
return resolve()
|
|
335
|
+
}
|
|
209
336
|
})
|
|
210
337
|
}
|
|
338
|
+
|
|
339
|
+
async baseCleanup(restore: boolean = true) {
|
|
340
|
+
try {
|
|
341
|
+
if (restore && this._source && this._target) {
|
|
342
|
+
if (await removeHost(this._source.split(':')[0], this._target.split(':')[0]))
|
|
343
|
+
consola.success('Restore host success.\n')
|
|
344
|
+
|
|
345
|
+
else
|
|
346
|
+
consola.fail('Restore host failed.\n')
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
catch (e) {
|
|
350
|
+
consola.error(e)
|
|
351
|
+
consola.fail('Restore host failed.\n')
|
|
352
|
+
}
|
|
353
|
+
if (!this.locked && !this.stoped) {
|
|
354
|
+
this._caddyChild?.kill()
|
|
355
|
+
try {
|
|
356
|
+
await lockfile.unlock(caddyLockFilePath).catch(() => { })
|
|
357
|
+
await unlink(caddyFilePath).catch(() => { })
|
|
358
|
+
await unlink(caddyLockFilePath).catch(() => { })
|
|
359
|
+
}
|
|
360
|
+
catch (e) {
|
|
361
|
+
consola.error(e)
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
}
|
|
211
365
|
}
|
package/src/caddy/utils.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createServer } from 'node:net'
|
|
2
|
+
import { exec } from 'node:child_process'
|
|
2
3
|
import ora from 'ora'
|
|
3
4
|
import { consola } from '../utils'
|
|
4
5
|
|
|
@@ -28,6 +29,23 @@ export function tryPort(port: number) {
|
|
|
28
29
|
})
|
|
29
30
|
}
|
|
30
31
|
|
|
32
|
+
/**
|
|
33
|
+
* npx free-port :port
|
|
34
|
+
*/
|
|
35
|
+
export async function kill(port: number) {
|
|
36
|
+
return new Promise<void>((resolve, reject) => {
|
|
37
|
+
exec(`npx @maxbo/free-port ${port} -s`, (err, stdout, stderr) => {
|
|
38
|
+
if (err) {
|
|
39
|
+
reject(err)
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
consola.log(stdout)
|
|
43
|
+
resolve()
|
|
44
|
+
}
|
|
45
|
+
})
|
|
46
|
+
})
|
|
47
|
+
}
|
|
48
|
+
|
|
31
49
|
function getNumber(number: number) {
|
|
32
50
|
if (number <= 0)
|
|
33
51
|
return '0%'
|
package/src/host/index.ts
CHANGED
|
@@ -1,17 +1,13 @@
|
|
|
1
1
|
import process from 'node:process'
|
|
2
2
|
import { exec } from 'node:child_process'
|
|
3
3
|
import { chmodSync } from 'node:fs'
|
|
4
|
+
import { promisify } from 'node:util'
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
import _Hosts from 'hosts-so-easy'
|
|
6
|
+
import hostile from 'hostile'
|
|
7
7
|
import { consola } from '../utils'
|
|
8
8
|
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
const hostInstance = new Hosts({
|
|
12
|
-
debounceTime: 50,
|
|
13
|
-
hostsFile: getPathOfSystemHostsPath(),
|
|
14
|
-
})
|
|
9
|
+
const _setHost = promisify(hostile.set)
|
|
10
|
+
const _removeHost = promisify(hostile.remove)
|
|
15
11
|
|
|
16
12
|
function getPathOfSystemHostsPath() {
|
|
17
13
|
return process.platform === 'win32'
|
|
@@ -38,20 +34,18 @@ async function syncHost() {
|
|
|
38
34
|
export async function addHost(ip: string, host: string) {
|
|
39
35
|
if (process.platform !== 'win32')
|
|
40
36
|
chmodSync(getPathOfSystemHostsPath(), 0o777)
|
|
41
|
-
|
|
42
|
-
|
|
37
|
+
await _setHost('127.0.0.1', 'localhost')
|
|
38
|
+
await _setHost(ip, host)
|
|
43
39
|
if (ip === 'localhost')
|
|
44
|
-
|
|
45
|
-
await hostInstance.updateFinish()
|
|
40
|
+
await _setHost('127.0.0.1', host)
|
|
46
41
|
return await syncHost()
|
|
47
42
|
}
|
|
48
43
|
|
|
49
44
|
export async function removeHost(ip: string, host: string) {
|
|
50
45
|
if (process.platform !== 'win32')
|
|
51
46
|
chmodSync(getPathOfSystemHostsPath(), 0o777)
|
|
52
|
-
|
|
47
|
+
await _removeHost(ip, host)
|
|
53
48
|
if (ip === 'localhost')
|
|
54
|
-
|
|
55
|
-
await hostInstance.updateFinish()
|
|
49
|
+
await _removeHost('127.0.0.1', host)
|
|
56
50
|
return await syncHost()
|
|
57
51
|
}
|