Skip to content

Commit b2b9274

Browse files
authored
feat: support configuration of multiple URL mappings (#4)
* feat: support configuration of multiple URL mappings * chore: bump version
1 parent 18fb699 commit b2b9274

File tree

9 files changed

+202
-198
lines changed

9 files changed

+202
-198
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.1.6 (2025-4-24)
2+
3+
- feat: support configuration of multiple URL mappings
4+
15
## 0.1.5 (2025-4-23)
26

37
- chore: update readme

api/hooks/pre-start.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
require('@blocklet/sdk/lib/error-handler');
22
require('dotenv-flow').config();
3-
4-
const isUrl = require('is-absolute-url');
3+
const { mappings } = require('../libs/env');
54

65
(() => {
7-
if (isUrl(process.env.UPSTREAM_URL)) {
8-
console.info(`Proxy to upstream: ${process.env.UPSTREAM_URL}`);
6+
if (Array.isArray(mappings)) {
7+
console.info(`Proxy to upstream:`, mappings);
98
process.exit(0);
109
} else {
1110
console.error('UPSTREAM_URL must be an absolute URL');

api/index.js

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,25 @@
11
require('dotenv-flow').config();
22

33
const express = require('express');
4-
const logger = require('@blocklet/logger');
54
const { createProxyMiddleware } = require('http-proxy-middleware');
6-
5+
const { mappings } = require('./libs/env');
6+
const logger = require('@blocklet/logger');
77
const env = require('./libs/env');
88

99
const app = express();
1010

1111
const port = process.env.BLOCKLET_PORT || process.env.PORT || 3030;
1212
logger.setupAccessLogger(app);
1313

14-
app.use(createProxyMiddleware({ target: env.upstreamUrl, changeOrigin: false, followRedirects: false, ws: true }));
14+
for (const mapping of mappings) {
15+
console.error(`Proxy to ${mapping.url} on ${mapping.mountPoint}`);
16+
app.use(mapping.mountPoint, createProxyMiddleware({
17+
target: mapping.url,
18+
changeOrigin: false,
19+
followRedirects: false,
20+
ws: true,
21+
}));
22+
}
1523

1624
app.listen(port, () => {
1725
console.log(`${env.name} v${env.version} listening on port ${port}`);

api/libs/env.js

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,58 @@
11
const env = require('@blocklet/sdk/lib/env');
22
const { name, version } = require('../../package.json');
3+
const config = require('@blocklet/sdk/lib/config');
4+
const uniqBy = require('lodash/uniqBy');
5+
const isUrl = require('is-absolute-url');
6+
const logger = require('./logger');
7+
8+
/**
9+
* @type {string}
10+
*/
11+
const upstreamUrl = process.env.UPSTREAM_URL;
12+
13+
/**
14+
* @returns {Array<{mountPoint: string, url: string}>}
15+
*/
16+
function getMappings() {
17+
/**
18+
* @type {Array<{mountPoint: string, url: string}>}
19+
*/
20+
let mappings = [];
21+
22+
if (Array.isArray(config.env.preferences.mappings)) {
23+
mappings = [
24+
...mappings,
25+
...config.env.preferences.mappings,
26+
]
27+
}
28+
29+
if (isUrl(upstreamUrl)) {
30+
mappings.push({
31+
mountPoint: '/',
32+
url: upstreamUrl,
33+
})
34+
}
35+
36+
if (!mappings.length) {
37+
throw new Error('No mappings found, please check your blocklet preferences or upstream url');
38+
}
39+
40+
mappings.sort((a, b) => b.mountPoint.length - a.mountPoint.length);
41+
42+
logger.info('mappings', uniqBy(mappings, 'mountPoint'));
43+
44+
return uniqBy(mappings, 'mountPoint');
45+
}
46+
47+
/**
48+
* @type {Array<{mountPoint: string, url: string}>}
49+
*/
50+
const mappings = getMappings();
351

452
module.exports = {
553
...env,
654
name,
755
version,
8-
upstreamUrl: process.env.UPSTREAM_URL,
56+
upstreamUrl,
57+
mappings,
958
};

blocklet.prefs.json

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
{
2+
"form": {
3+
"labelCol": 6,
4+
"wrapperCol": 12
5+
},
6+
"schema": {
7+
"type": "object",
8+
"properties": {
9+
"mappings": {
10+
"type": "array",
11+
"x-decorator": "FormItem",
12+
"x-component": "ArrayCards",
13+
"x-component-props": {
14+
"title": "Mapping"
15+
},
16+
"x-validator": [],
17+
"x-decorator-props": {},
18+
"name": "mappings",
19+
"default": "[]",
20+
"x-designable-id": "2dgz1hi0vnf",
21+
"x-index": 0,
22+
"required": false,
23+
"items": {
24+
"type": "object",
25+
"required": true,
26+
"x-designable-id": "25yx3oraexj",
27+
"x-validator": [],
28+
"properties": {
29+
"mountPoint": {
30+
"type": "string",
31+
"title": "Mount point",
32+
"x-decorator": "FormItem",
33+
"x-component": "Input",
34+
"x-validator": [],
35+
"x-component-props": {
36+
"placeholder": "Please input mount point, example: /abc"
37+
},
38+
"x-decorator-props": {
39+
"colon": false
40+
},
41+
"name": "mountPoint",
42+
"description": "",
43+
"default": "/",
44+
"required": true,
45+
"x-designable-id": "vgizlbk908b",
46+
"x-index": 0
47+
},
48+
"url": {
49+
"type": "string",
50+
"title": "Url ",
51+
"x-decorator": "FormItem",
52+
"x-component": "Input",
53+
"x-validator": [],
54+
"x-component-props": {
55+
"placeholder": "Please input mount point, example: /abc",
56+
"style": {
57+
"margin": "0px 0px 0px 56px",
58+
"padding": "0px 0px 0px 0px"
59+
}
60+
},
61+
"x-decorator-props": {
62+
"colon": false
63+
},
64+
"name": "url",
65+
"description": "",
66+
"default": "/",
67+
"required": true,
68+
"x-designable-id": "wowqneg4sfa",
69+
"x-index": 1
70+
},
71+
"q4b4szpt0jm": {
72+
"type": "void",
73+
"x-component": "ArrayCards.Remove",
74+
"x-designable-id": "q4b4szpt0jm",
75+
"x-index": 2
76+
},
77+
"10ydkmv5l87": {
78+
"type": "void",
79+
"x-component": "ArrayCards.MoveDown",
80+
"x-designable-id": "10ydkmv5l87",
81+
"x-index": 3
82+
},
83+
"x2jjnlipu1i": {
84+
"type": "void",
85+
"x-component": "ArrayCards.MoveUp",
86+
"x-designable-id": "x2jjnlipu1i",
87+
"x-index": 4
88+
}
89+
}
90+
},
91+
"properties": {
92+
"h2c23502iwl": {
93+
"type": "void",
94+
"title": "Addition",
95+
"x-component": "ArrayCards.Addition",
96+
"x-component-props": {},
97+
"x-designable-id": "h2c23502iwl",
98+
"x-index": 0
99+
},
100+
"mountPoint": {
101+
"type": "string",
102+
"title": "Mount point",
103+
"x-decorator": "FormItem",
104+
"x-component": "Input",
105+
"x-validator": [],
106+
"x-component-props": {
107+
"placeholder": "Please input mount point, example: /abc"
108+
},
109+
"x-decorator-props": {},
110+
"name": "mountPoint",
111+
"description": "",
112+
"default": "/",
113+
"required": false,
114+
"x-designable-id": "js2t4onseqx",
115+
"x-index": 1
116+
}
117+
}
118+
}
119+
},
120+
"x-designable-id": "yrr9cqfq3hx"
121+
}
122+
}

blocklet.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ repository:
1313
type: git
1414
url: git+https://github.com/blocklet/general-proxy.git
1515
specVersion: 1.2.8
16-
version: 0.1.5
16+
version: 0.1.6
1717
logo: logo.png
1818
files:
1919
- logo.png
@@ -45,7 +45,7 @@ scripts:
4545
environments:
4646
- name: UPSTREAM_URL
4747
description: What'url endpoint of the upstream?
48-
required: true
48+
required: false
4949
default: ''
5050
secure: false
5151
shared: false

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "general-proxy",
3-
"version": "0.1.5",
3+
"version": "0.1.6",
44
"description": "",
55
"main": "api/index.js",
66
"scripts": {
@@ -44,6 +44,6 @@
4444
"nodemon": "^2.0.20",
4545
"prettier": "^2.8.3",
4646
"rimraf": "^3.0.2",
47-
"zx": "^7.1.1"
47+
"zx": "^8.5.3"
4848
}
4949
}

version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.1.5
1+
0.1.6

0 commit comments

Comments
 (0)