@cloud-cli/px 4.0.1 → 4.1.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 +13 -11
- package/dist/index.d.ts +9 -20
- package/dist/index.js +28 -33
- package/dist/proxy-manager.d.ts +6 -32
- package/dist/proxy-manager.js +45 -39
- package/dist/types.d.ts +21 -0
- package/dist/types.js +1 -0
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -16,22 +16,24 @@ export default { proxy };
|
|
|
16
16
|
|
|
17
17
|
## API
|
|
18
18
|
|
|
19
|
+
All proxies have the following properties:
|
|
20
|
+
|
|
21
|
+
| Options | Description |
|
|
22
|
+
| --------------- | ---------------------------------------------------------------------------------------------------- |
|
|
23
|
+
| `domain` | Required. entrypoint for reverse proxy |
|
|
24
|
+
| `target` | Required. Any target address, can be local or remote |
|
|
25
|
+
| `cors` | handle CORS request on proxy level. See notes below! |
|
|
26
|
+
| `redirect` | if request comes as http, redirect to https |
|
|
27
|
+
| `redirectUrl` | if provided, issues a `Location` header and terminates with status 302 instead of proxying a request |
|
|
28
|
+
| `headers` | comma separated headers to set in the outbound connection, e.g. authorisation headers |
|
|
29
|
+
| `authorization` | matches incoming request headers against this value. If strings match, requests can continue. |
|
|
30
|
+
|
|
19
31
|
**Add a proxy to a local service**
|
|
20
32
|
|
|
21
33
|
```bash
|
|
22
34
|
cy proxy.add --domain "foo.example.com" --target "http://localhost:1234"
|
|
23
35
|
```
|
|
24
36
|
|
|
25
|
-
All available options:
|
|
26
|
-
|
|
27
|
-
- `domain`: entrypoint for reverse proxy
|
|
28
|
-
- `target`: any target for requests, can be local or remote
|
|
29
|
-
- `cors`: handle CORS request on proxy level. See notes below!
|
|
30
|
-
- `redirect`: if request comes as http, redirect to https
|
|
31
|
-
- `redirectUrl`: if provided, issues a `Location` header and terminates with status 302 instead of proxying a request
|
|
32
|
-
- `headers`: comma separated headers to set in the outbound connection, e.g. authorisation headers
|
|
33
|
-
- `authorization`: matches incoming request headers against this value. If strings match, requests can continue.
|
|
34
|
-
|
|
35
37
|
**Remove a proxy**
|
|
36
38
|
|
|
37
39
|
```bash
|
|
@@ -88,6 +90,6 @@ CORS handling on proxy level is convenient, **but a security risk**. Beware:
|
|
|
88
90
|
Every request has additional headers:
|
|
89
91
|
|
|
90
92
|
- x-forwarded-for: the host of the original request.
|
|
91
|
-
If a proxy is from 'https://foo.example.com' to 'http://localhost:1234', the header will be 'foo.example.com'
|
|
93
|
+
If a proxy is from 'https://foo.example.com' to 'http://localhost:1234', the header will be 'foo.example.com'
|
|
92
94
|
- x-forwarded-proto: 'http' or 'https', depends on the original request
|
|
93
95
|
- forwarded: the standard header with the same information as the other two above
|
package/dist/index.d.ts
CHANGED
|
@@ -1,24 +1,13 @@
|
|
|
1
1
|
import { init } from '@cloud-cli/cli';
|
|
2
|
-
import { DomainAndTarget,
|
|
3
|
-
type ExtraProps = {
|
|
4
|
-
_: string[];
|
|
5
|
-
};
|
|
6
|
-
declare function add(options: Proxy & ExtraProps): Promise<Proxy>;
|
|
7
|
-
declare function remove(options: DomainAndTarget): Promise<unknown>;
|
|
8
|
-
declare function update(options: Proxy & ExtraProps): Promise<boolean>;
|
|
9
|
-
declare function list(): Promise<Proxy[]>;
|
|
10
|
-
declare function get(options: Domain): Promise<Proxy[]>;
|
|
11
|
-
declare function domains(): Promise<string[]>;
|
|
12
|
-
declare function initServer(): Promise<import("@cloud-cli/proxy").ProxyServer>;
|
|
13
|
-
declare function reload(): Promise<void>;
|
|
2
|
+
import { DomainAndTarget, DomainName, Proxy, WithOptionalProps } from './types.js';
|
|
14
3
|
declare const _default: {
|
|
15
|
-
add:
|
|
16
|
-
remove:
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
domains:
|
|
21
|
-
|
|
22
|
-
|
|
4
|
+
add(options: WithOptionalProps<Proxy>): Promise<Proxy>;
|
|
5
|
+
remove(options: WithOptionalProps<DomainAndTarget>): Promise<boolean>;
|
|
6
|
+
update(options: WithOptionalProps<Proxy>): Promise<Proxy>;
|
|
7
|
+
list(filters: Partial<Proxy>): Promise<Proxy[]>;
|
|
8
|
+
get(options: DomainName): Proxy[];
|
|
9
|
+
domains(): Promise<string[]>;
|
|
10
|
+
[init](): Promise<import("@cloud-cli/proxy").ProxyServer>;
|
|
11
|
+
reload(): Promise<void>;
|
|
23
12
|
};
|
|
24
13
|
export default _default;
|
package/dist/index.js
CHANGED
|
@@ -1,36 +1,31 @@
|
|
|
1
1
|
import { init, logInfo } from '@cloud-cli/cli';
|
|
2
2
|
import { ProxyManager } from './proxy-manager.js';
|
|
3
3
|
const manager = new ProxyManager();
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
32
|
-
async function reload() {
|
|
33
|
-
logInfo('Reloading proxy server');
|
|
34
|
-
return await manager.reload();
|
|
35
|
-
}
|
|
36
|
-
export default { add, remove, list, get, update, domains, reload, [init]: initServer };
|
|
4
|
+
export default {
|
|
5
|
+
async add(options) {
|
|
6
|
+
return manager.addProxy(options);
|
|
7
|
+
},
|
|
8
|
+
async remove(options) {
|
|
9
|
+
return manager.removeProxy(options);
|
|
10
|
+
},
|
|
11
|
+
async update(options) {
|
|
12
|
+
return await manager.updateProxy(options);
|
|
13
|
+
},
|
|
14
|
+
list(filters) {
|
|
15
|
+
return manager.getProxyList(filters);
|
|
16
|
+
},
|
|
17
|
+
get(options) {
|
|
18
|
+
return manager.getProxyListForDomain(options);
|
|
19
|
+
},
|
|
20
|
+
domains() {
|
|
21
|
+
return manager.getDomainList();
|
|
22
|
+
},
|
|
23
|
+
async [init]() {
|
|
24
|
+
await manager.reload();
|
|
25
|
+
return manager.server;
|
|
26
|
+
},
|
|
27
|
+
async reload() {
|
|
28
|
+
logInfo('Reloading proxy server');
|
|
29
|
+
return await manager.reload();
|
|
30
|
+
},
|
|
31
|
+
};
|
package/dist/proxy-manager.d.ts
CHANGED
|
@@ -1,38 +1,12 @@
|
|
|
1
1
|
import { ProxyServer } from '@cloud-cli/proxy';
|
|
2
|
-
|
|
3
|
-
host?: string;
|
|
4
|
-
_: string[];
|
|
5
|
-
}
|
|
6
|
-
export interface Domain extends OptionalProps {
|
|
7
|
-
domain: string;
|
|
8
|
-
}
|
|
9
|
-
export interface DomainAndTarget extends Domain {
|
|
10
|
-
target: string;
|
|
11
|
-
}
|
|
12
|
-
export interface Proxy {
|
|
13
|
-
domain: string;
|
|
14
|
-
target: string;
|
|
15
|
-
redirect: boolean;
|
|
16
|
-
redirectUrl: string;
|
|
17
|
-
headers: string;
|
|
18
|
-
authorization: string;
|
|
19
|
-
cors: boolean;
|
|
20
|
-
}
|
|
21
|
-
type KeysOf<T> = {
|
|
22
|
-
[K in keyof T]: T[K] extends () => any ? never : K;
|
|
23
|
-
}[keyof T];
|
|
24
|
-
type ClassProperties<T> = {
|
|
25
|
-
[K in KeysOf<T>]: T[K] extends never ? never : T[K];
|
|
26
|
-
};
|
|
2
|
+
import type { DomainAndTarget, DomainName, Proxy, WithOptionalProps } from './types.js';
|
|
27
3
|
export declare class ProxyManager {
|
|
28
4
|
server: ProxyServer;
|
|
29
|
-
addProxy(proxy:
|
|
30
|
-
updateProxy(options:
|
|
31
|
-
removeProxy(options: DomainAndTarget): Promise<
|
|
5
|
+
addProxy(proxy: WithOptionalProps<Proxy>): Promise<Proxy>;
|
|
6
|
+
updateProxy(options: WithOptionalProps<Proxy>): Promise<Proxy>;
|
|
7
|
+
removeProxy(options: WithOptionalProps<DomainAndTarget>): Promise<boolean>;
|
|
32
8
|
getDomainList(): Promise<string[]>;
|
|
33
|
-
getProxyList(): Promise<Proxy[]>;
|
|
34
|
-
getProxyListForDomain(options:
|
|
9
|
+
getProxyList(filters?: Partial<Proxy>): Promise<Proxy[]>;
|
|
10
|
+
getProxyListForDomain(options: WithOptionalProps<DomainName>): Proxy[];
|
|
35
11
|
reload(): Promise<void>;
|
|
36
|
-
private findByDomainAndPath;
|
|
37
12
|
}
|
|
38
|
-
export {};
|
package/dist/proxy-manager.js
CHANGED
|
@@ -8,7 +8,7 @@ const defaultOptions = {
|
|
|
8
8
|
const domainNotSpecifiedError = new Error('Domain not specified');
|
|
9
9
|
const targetNotSpecifiedError = new Error('Target not specified');
|
|
10
10
|
const moduleConfig = await getConfig('px', defaultOptions);
|
|
11
|
-
const { set, remove, getAll } = getStorage('px');
|
|
11
|
+
const { set, get, has, remove, getAll } = getStorage('px');
|
|
12
12
|
const settings = new ProxySettings({
|
|
13
13
|
certificatesFolder: moduleConfig.certsFolder,
|
|
14
14
|
certificateFile: 'fullchain.pem',
|
|
@@ -26,20 +26,21 @@ const emptyProxy = {
|
|
|
26
26
|
headers: '',
|
|
27
27
|
authorization: '',
|
|
28
28
|
};
|
|
29
|
+
const readDomain = (options) => (options.domain = options.domain || options.host || options._[0]);
|
|
29
30
|
export class ProxyManager {
|
|
30
31
|
constructor() {
|
|
31
32
|
this.server = px;
|
|
32
33
|
}
|
|
33
34
|
async addProxy(proxy) {
|
|
34
|
-
|
|
35
|
+
readDomain(proxy);
|
|
36
|
+
if (!proxy.domain) {
|
|
35
37
|
throw domainNotSpecifiedError;
|
|
36
38
|
}
|
|
37
39
|
if (!proxy.target && !proxy.redirectUrl) {
|
|
38
40
|
throw targetNotSpecifiedError;
|
|
39
41
|
}
|
|
40
|
-
const domainAndPath = proxy.domain || proxy.host || proxy._[0];
|
|
41
42
|
const entry = {
|
|
42
|
-
domain:
|
|
43
|
+
domain: proxy.domain,
|
|
43
44
|
target: proxy.target,
|
|
44
45
|
cors: !!proxy.cors,
|
|
45
46
|
redirect: !!proxy.redirect,
|
|
@@ -47,49 +48,59 @@ export class ProxyManager {
|
|
|
47
48
|
headers: proxy.headers || '',
|
|
48
49
|
authorization: proxy.authorization,
|
|
49
50
|
};
|
|
50
|
-
|
|
51
|
+
set(proxy.domain, entry);
|
|
52
|
+
await this.reload();
|
|
51
53
|
return entry;
|
|
52
54
|
}
|
|
53
55
|
async updateProxy(options) {
|
|
54
|
-
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
readDomain(options);
|
|
57
|
+
const host = options.domain;
|
|
58
|
+
let proxy = get(host);
|
|
59
|
+
if (!proxy) {
|
|
60
|
+
proxy = { ...emptyProxy, domain: host };
|
|
58
61
|
}
|
|
59
62
|
const properties = ['target', 'cors', 'redirect', 'redirectUrl', 'headers', 'authorization'];
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
64
|
-
return true;
|
|
65
|
-
}
|
|
66
|
-
removeProxy(options) {
|
|
67
|
-
return new Promise(async (resolve, reject) => {
|
|
68
|
-
const host = options.domain || options.host;
|
|
69
|
-
if (!host) {
|
|
70
|
-
return reject(domainNotSpecifiedError);
|
|
71
|
-
}
|
|
72
|
-
const proxies = await this.findByDomainAndPath(host);
|
|
73
|
-
try {
|
|
74
|
-
for (const p of proxies) {
|
|
75
|
-
await remove(p.domain);
|
|
76
|
-
}
|
|
77
|
-
resolve({ found: proxies.length });
|
|
78
|
-
}
|
|
79
|
-
catch (error) {
|
|
80
|
-
reject(error);
|
|
63
|
+
properties.forEach((p) => {
|
|
64
|
+
if (p in options) {
|
|
65
|
+
proxy[p] = options[p];
|
|
81
66
|
}
|
|
82
67
|
});
|
|
68
|
+
set(proxy.domain, proxy);
|
|
69
|
+
await this.reload();
|
|
70
|
+
return proxy;
|
|
71
|
+
}
|
|
72
|
+
async removeProxy(options) {
|
|
73
|
+
readDomain(options);
|
|
74
|
+
const host = options.domain;
|
|
75
|
+
if (!host) {
|
|
76
|
+
throw domainNotSpecifiedError;
|
|
77
|
+
}
|
|
78
|
+
if (has(host)) {
|
|
79
|
+
remove(host);
|
|
80
|
+
await this.reload();
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
return false;
|
|
83
84
|
}
|
|
84
85
|
async getDomainList() {
|
|
85
|
-
const proxies =
|
|
86
|
+
const proxies = getAll();
|
|
86
87
|
return proxies.map((proxy) => proxy.domain);
|
|
87
88
|
}
|
|
88
|
-
async getProxyList() {
|
|
89
|
-
|
|
89
|
+
async getProxyList(filters = {}) {
|
|
90
|
+
const list = getAll();
|
|
91
|
+
const keys = Object.keys(filters);
|
|
92
|
+
if (!keys.length) {
|
|
93
|
+
return list;
|
|
94
|
+
}
|
|
95
|
+
return keys.reduce((list, key) => {
|
|
96
|
+
const filter = String(filters[key]).toLowerCase();
|
|
97
|
+
return list.filter((p) => String(p[key]).toLowerCase().includes(filter));
|
|
98
|
+
}, list);
|
|
90
99
|
}
|
|
91
100
|
getProxyListForDomain(options) {
|
|
92
|
-
|
|
101
|
+
readDomain(options);
|
|
102
|
+
const all = getAll();
|
|
103
|
+
return all.filter((p) => p.domain === options.domain);
|
|
93
104
|
}
|
|
94
105
|
async reload() {
|
|
95
106
|
const targets = await getAll();
|
|
@@ -109,9 +120,4 @@ export class ProxyManager {
|
|
|
109
120
|
});
|
|
110
121
|
px.start();
|
|
111
122
|
}
|
|
112
|
-
async findByDomainAndPath(string) {
|
|
113
|
-
const [domain, path = ''] = string.split('/');
|
|
114
|
-
const proxies = await getAll();
|
|
115
|
-
return proxies.filter((p) => p.domain === domain && (!path || domain === path));
|
|
116
|
-
}
|
|
117
123
|
}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
interface OptionalProps {
|
|
2
|
+
host?: string;
|
|
3
|
+
_: string[];
|
|
4
|
+
}
|
|
5
|
+
export interface DomainName extends OptionalProps {
|
|
6
|
+
domain: string;
|
|
7
|
+
}
|
|
8
|
+
export interface DomainAndTarget extends DomainName {
|
|
9
|
+
target: string;
|
|
10
|
+
}
|
|
11
|
+
export interface Proxy {
|
|
12
|
+
domain: string;
|
|
13
|
+
target: string;
|
|
14
|
+
redirect: boolean;
|
|
15
|
+
redirectUrl: string;
|
|
16
|
+
headers: string;
|
|
17
|
+
authorization: string;
|
|
18
|
+
cors: boolean;
|
|
19
|
+
}
|
|
20
|
+
export type WithOptionalProps<T extends object> = T & OptionalProps;
|
|
21
|
+
export {};
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cloud-cli/px",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.1.1",
|
|
4
4
|
"description": "Reverse Proxy",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -28,7 +28,9 @@
|
|
|
28
28
|
"access": "public"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@cloud-cli/cli": "^1.2.2",
|
|
32
31
|
"@cloud-cli/proxy": "^1.2.0"
|
|
32
|
+
},
|
|
33
|
+
"peerDependencies": {
|
|
34
|
+
"@cloud-cli/cli": "^2.0.0"
|
|
33
35
|
}
|
|
34
36
|
}
|