@cloud-cli/px 3.3.1 → 3.4.1
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 +26 -12
- package/dist/proxy.js +6 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
# PX
|
|
2
2
|
|
|
3
|
-
Reverse proxy to map local services
|
|
3
|
+
Reverse proxy to map local services and external http(s) domains
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Usage
|
|
6
6
|
|
|
7
7
|
Use it with [Cloudy](https://github.com/cloud-cli/cli)
|
|
8
8
|
|
|
@@ -14,11 +14,11 @@ import proxy from '@cloud-cli/px';
|
|
|
14
14
|
export default { proxy };
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
## API
|
|
18
18
|
|
|
19
19
|
**Add a proxy to a local service**
|
|
20
20
|
|
|
21
|
-
```
|
|
21
|
+
```bash
|
|
22
22
|
cy proxy.add --domain "foo.example.com" --target "http://localhost:1234"
|
|
23
23
|
```
|
|
24
24
|
|
|
@@ -26,42 +26,43 @@ All available options:
|
|
|
26
26
|
|
|
27
27
|
- `domain`: entrypoint for reverse proxy
|
|
28
28
|
- `target`: any target for requests, can be local or remote
|
|
29
|
+
- `cors`: handle CORS request on proxy level. See notes below!
|
|
29
30
|
- `redirect`: if request comes as http, redirect to https
|
|
30
31
|
- `redirectUrl`: if provided, issues a `Location` header and terminates with status 302 instead of proxying a request
|
|
31
32
|
|
|
32
33
|
**Remove a proxy**
|
|
33
34
|
|
|
34
|
-
```
|
|
35
|
+
```bash
|
|
35
36
|
cy proxy.remove --domain "foo.example.com"
|
|
36
37
|
```
|
|
37
38
|
|
|
38
39
|
**Get details of a proxy**
|
|
39
40
|
|
|
40
|
-
```
|
|
41
|
+
```bash
|
|
41
42
|
cy proxy.get --domain "foo.example.com"
|
|
42
43
|
```
|
|
43
44
|
|
|
44
45
|
**List proxies**
|
|
45
46
|
|
|
46
|
-
```
|
|
47
|
+
```bash
|
|
47
48
|
cy proxy.list
|
|
48
49
|
```
|
|
49
50
|
|
|
50
51
|
**List registered domains**
|
|
51
52
|
|
|
52
|
-
```
|
|
53
|
+
```bash
|
|
53
54
|
cy proxy.domains
|
|
54
55
|
```
|
|
55
56
|
|
|
56
57
|
**Reload all configurations**
|
|
57
58
|
|
|
58
|
-
```
|
|
59
|
+
```bash
|
|
59
60
|
cy proxy.reload
|
|
60
61
|
```
|
|
61
62
|
|
|
62
63
|
## Certificate file resolution
|
|
63
64
|
|
|
64
|
-
```
|
|
65
|
+
```bash
|
|
65
66
|
certificatesFolder = '/etc/letsencrypt/live' or process.env.PX_CERTS_FOLDER
|
|
66
67
|
rootDomain = 'example.com' in 'xyz.example.com'
|
|
67
68
|
cert = certificatesFolder + '/' + rootDomain + '/' + certificateFile
|
|
@@ -70,7 +71,20 @@ key = certificatesFolder + '/' + rootDomain + '/' + keyFile
|
|
|
70
71
|
|
|
71
72
|
So xyz.example.com points to:
|
|
72
73
|
|
|
73
|
-
```
|
|
74
|
+
```bash
|
|
74
75
|
/etc/letsencrypt/live/example.com/fullchain.pem for certificate
|
|
75
76
|
/etc/letsencrypt/live/example.com/privkey.pem for private key
|
|
76
77
|
```
|
|
78
|
+
|
|
79
|
+
## Notes
|
|
80
|
+
|
|
81
|
+
CORS handling on proxy level is convenient, **but a security risk**. Beware:
|
|
82
|
+
|
|
83
|
+
- All origins are allowed, all common methods and headers, and credentials are enabled.
|
|
84
|
+
- In case of an `OPTIONS` request, if coming via CORS (a preflight), an empty response will be send and the request ends before calling the proxied target.
|
|
85
|
+
|
|
86
|
+
Every request has 2 additional headers:
|
|
87
|
+
|
|
88
|
+
- x-forwarded-for: the host of the original request.
|
|
89
|
+
If a proxy is from 'https://foo.example.com' to 'http://localhost:1234', the header will be 'foo.example.com'
|
|
90
|
+
- x-forwarded-proto: 'http:' or 'https:', depends on the original request
|
package/dist/proxy.js
CHANGED
|
@@ -68,7 +68,9 @@ export class ProxyServer {
|
|
|
68
68
|
return status.isDirectory() ? dir : '';
|
|
69
69
|
}));
|
|
70
70
|
folders.filter(Boolean).forEach(async (rootDomain) => {
|
|
71
|
-
|
|
71
|
+
if (process.env.DEBUG) {
|
|
72
|
+
console.log(`Loading certificate for ${rootDomain}`);
|
|
73
|
+
}
|
|
72
74
|
certs[rootDomain] = createSecureContext({
|
|
73
75
|
cert: await readFile(join(certificatesFolder, rootDomain, certificateFile), 'utf8'),
|
|
74
76
|
key: await readFile(join(certificatesFolder, rootDomain, keyFile), 'utf8'),
|
|
@@ -113,6 +115,8 @@ export class ProxyServer {
|
|
|
113
115
|
const proxyRequest = (url.protocol === 'https:' ? httpsRequest : httpRequest)(url, { method: req.method });
|
|
114
116
|
setHeaders(req, proxyRequest);
|
|
115
117
|
proxyRequest.setHeader('host', getHost(target));
|
|
118
|
+
proxyRequest.setHeader('x-forwarded-for', req.headers.host);
|
|
119
|
+
proxyRequest.setHeader('x-forwarded-proto', insecure ? 'http:' : 'https:');
|
|
116
120
|
req.on('data', (chunk) => proxyRequest.write(chunk));
|
|
117
121
|
req.on('end', () => proxyRequest.end());
|
|
118
122
|
proxyRequest.on('error', (error) => handleError(error, res));
|
|
@@ -160,7 +164,7 @@ function setHeaders(from, to) {
|
|
|
160
164
|
}
|
|
161
165
|
}
|
|
162
166
|
function handleError(error, res) {
|
|
163
|
-
console.
|
|
167
|
+
console.error(error);
|
|
164
168
|
if (error.code === 'ECONNREFUSED') {
|
|
165
169
|
res.writeHead(502);
|
|
166
170
|
res.end();
|