huxy-server 1.0.1 → 1.0.3

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.
Files changed (3) hide show
  1. package/README.md +29 -2
  2. package/package.json +2 -2
  3. package/src/index.js +96 -93
package/README.md CHANGED
@@ -52,8 +52,6 @@ startApp(config, (huxyConfig, app, httpServer) => {
52
52
  });
53
53
  ```
54
54
 
55
- `authToken` 默认值 '1234',如不需要鉴权可以设置环境变量 `AUTH_TOKEN=false` 或设置 `config = {authToken: false}`。
56
-
57
55
  ### 直接使用 `appProxy`
58
56
 
59
57
  也可直接使用 `appProxy`,只需传入你的服务 `app` 和代理 `config` 即可。
@@ -65,6 +63,35 @@ appProxy(app, config);
65
63
 
66
64
  ```
67
65
 
66
+ ### API 鉴权配置
67
+
68
+ 包含 2 种鉴权方式:
69
+
70
+ - apiKey:在请求头中 `x-api-key`或`x-huxy-auth` 里设置 `authToken` 值。
71
+ - jwt:在请求头中 `authorization` 里设置 `Bearer ${token}` 进行用户验证。
72
+
73
+ 默认不需要鉴权 `authToken: false` ,设置环境变量 `AUTH_TOKEN=false` 或 `config = {authToken: false}` 即可。如需鉴权选择上述 2 种方式中的一种即可,优先进行 `authToken` 认证。
74
+
75
+ 可配置免认证路由,如:`whitePathList: ['/health', '/status']` 。
76
+
77
+ 也可配置免认证 `authKeys` :如:`whiteAuthKeys: ['1234', '2234']` 。
78
+
79
+ 配置示例:
80
+
81
+ ```javascript
82
+ const config = {
83
+ // apiKey
84
+ authToken: '1234',
85
+ // jwt
86
+ secret: 'your-secret-key',
87
+ expiresIn: '30d',
88
+ issuer: 'your-app',
89
+ // white list
90
+ whiteAuthKeys: ['1234', '2234'],
91
+ whitePathList: ['/health', '/status'],
92
+ };
93
+ ```
94
+
68
95
  ### 环境变量
69
96
 
70
97
  项目支持以下环境变量:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "huxy-server",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "一个精炼、高性能的 Express.js 服务器模板,为现代 Node.js 应用程序设计,提供灵活的功能和最佳实践。",
5
5
  "type": "module",
6
6
  "module": "./src/index.js",
@@ -36,7 +36,7 @@
36
36
  },
37
37
  "dependencies": {
38
38
  "http-proxy-middleware": "^3.0.5",
39
- "huxy-node-server": "^1.0.0",
39
+ "huxy-node-server": "^1.0.1",
40
40
  "jsonwebtoken": "^9.0.3"
41
41
  },
42
42
  "engines": {
package/src/index.js CHANGED
@@ -1,144 +1,147 @@
1
1
  import {
2
- startServer as O,
3
- startStatic as W,
4
- logger as Z,
5
- createLogger as q,
6
- dateTime as ee,
7
- localIPs as te,
8
- nodeArgs as re,
9
- getEnvConfig as se,
10
- checkPort as oe,
11
- getDirName as ae,
12
- resolvePath as ne,
2
+ startServer as W,
3
+ startStatic as L,
4
+ logger as q,
5
+ createLogger as ee,
6
+ dateTime as te,
7
+ localIPs as re,
8
+ nodeArgs as se,
9
+ getEnvConfig as oe,
10
+ checkPort as ae,
11
+ getDirName as ne,
12
+ resolvePath as ie,
13
13
  } from 'huxy-node-server';
14
- import {createProxyMiddleware as E} from 'http-proxy-middleware';
15
- import {dateTime as I} from 'huxy-node-server';
14
+ import {createProxyMiddleware as I} from 'http-proxy-middleware';
15
+ import {dateTime as $} from 'huxy-node-server';
16
16
  import T from 'jsonwebtoken';
17
- var m = (r, e = {secret, ...opt}) => T.verify(r, secret, opt);
18
- var f =
17
+ var f = (r, e = {secret, ...opt}) => T.verify(r, secret, opt);
18
+ var x =
19
19
  (r = {}) =>
20
20
  (e, t, s) => {
21
- let n = e.headers.authorization;
22
- if (!n) return (e.log.warn('\u8BA4\u8BC1\u5931\u8D25: \u7F3A\u5C11\u8BA4\u8BC1\u4FE1\u606F'), t.status(401).json({message: '\u7F3A\u5C11\u8BA4\u8BC1\u4FE1\u606F'}));
23
- if (!n.startsWith('Bearer '))
21
+ let o = e.headers.authorization;
22
+ if (!o) return (e.log.warn('\u8BA4\u8BC1\u5931\u8D25: \u7F3A\u5C11\u8BA4\u8BC1\u4FE1\u606F'), t.status(401).json({message: '\u7F3A\u5C11\u8BA4\u8BC1\u4FE1\u606F'}));
23
+ if (!o.startsWith('Bearer '))
24
24
  return (e.log.warn('\u8BA4\u8BC1\u5931\u8D25: \u672A\u63D0\u4F9B\u6709\u6548\u8BA4\u8BC1\u4FE1\u606F'), t.status(401).json({message: '\u672A\u63D0\u4F9B\u6709\u6548\u8BA4\u8BC1\u4FE1\u606F'}));
25
- let a = n.split(' ')[1];
26
- if (!a) return (e.log.warn('\u8BA4\u8BC1\u5931\u8D25: \u8BBF\u95EE\u4EE4\u724C\u7F3A\u5931'), t.status(401).json({message: '\u8BBF\u95EE\u4EE4\u724C\u7F3A\u5931'}));
25
+ let n = o.split(' ')[1];
26
+ if (!n) return (e.log.warn('\u8BA4\u8BC1\u5931\u8D25: \u8BBF\u95EE\u4EE4\u724C\u7F3A\u5931'), t.status(401).json({message: '\u8BBF\u95EE\u4EE4\u724C\u7F3A\u5931'}));
27
27
  try {
28
- let o = m(a, r);
29
- (e.log.info(o, '\u8BA4\u8BC1\u6210\u529F'), (e.user = o), s());
30
- } catch (o) {
31
- return o.name === 'TokenExpiredError'
28
+ let a = f(n, r);
29
+ (e.log.info(a, '\u8BA4\u8BC1\u6210\u529F'), (e.user = a), s());
30
+ } catch (a) {
31
+ return a.name === 'TokenExpiredError'
32
32
  ? (e.log.warn({ip: e.ip}, '\u8BA4\u8BC1\u5931\u8D25: \u4EE4\u724C\u5DF2\u8FC7\u671F'), t.status(401).json({message: '\u4EE4\u724C\u5DF2\u8FC7\u671F'}))
33
- : o.name === 'JsonWebTokenError'
33
+ : a.name === 'JsonWebTokenError'
34
34
  ? (e.log.warn({ip: e.ip}, '\u8BA4\u8BC1\u5931\u8D25: \u65E0\u6548\u7684\u4EE4\u724C'), t.status(403).json({message: '\u65E0\u6548\u7684\u4EE4\u724C'}))
35
- : o instanceof AuthorizationError
36
- ? (e.log.warn({ip: e.ip}, `\u8BA4\u8BC1\u5931\u8D25: ${o.message}`), t.status(o.status).json({message: o.message}))
37
- : (e.log.warn({err: o, ip: e.ip}, '\u8BA4\u8BC1\u5931\u8D25: \u5185\u90E8\u670D\u52A1\u5668\u9519\u8BEF'), t.status(500).json({message: '\u5185\u90E8\u670D\u52A1\u5668\u9519\u8BEF'}));
35
+ : a instanceof AuthorizationError
36
+ ? (e.log.warn({ip: e.ip}, `\u8BA4\u8BC1\u5931\u8D25: ${a.message}`), t.status(a.status).json({message: a.message}))
37
+ : (e.log.warn({err: a, ip: e.ip}, '\u8BA4\u8BC1\u5931\u8D25: \u5185\u90E8\u670D\u52A1\u5668\u9519\u8BEF'), t.status(500).json({message: '\u5185\u90E8\u670D\u52A1\u5668\u9519\u8BEF'}));
38
38
  }
39
39
  };
40
- var j =
40
+ var v =
41
41
  ({whiteAuthKeys: r = [], whiteAuthPaths: e = [], config: t = {}}) =>
42
- (s, n, a) => {
43
- if (s.method === 'OPTIONS' || e.includes(s.path)) return a();
44
- let {authToken: o} = t;
45
- if (o === !1 || o === 'false') return a();
46
- let p = s.headers['x-huxy-auth'] || s.headers['x-api-key'];
47
- if (p === o || r.includes(p)) return a();
48
- let {secret: c, expiresIn: u, algorithm: i, issuer: h} = t;
49
- f({secret: c, expiresIn: u, algorithm: i, issuer: h})(s, n, a);
42
+ (s, o, n) => {
43
+ if (s.method === 'OPTIONS' || e.includes(s.path)) return n();
44
+ let {authToken: a} = t;
45
+ if (a === !1 || a === 'false') return n();
46
+ let i = s.headers['x-huxy-auth'] || s.headers['x-api-key'];
47
+ if ((i && i === a) || r.includes(i)) return n();
48
+ let {secret: c, expiresIn: l, algorithm: p, issuer: h} = t;
49
+ x({secret: c, expiresIn: l, algorithm: p, issuer: h})(s, o, n);
50
50
  },
51
- x = j;
52
- var v = ['x-powered-by', 'server'],
53
- y = (r, e) => {
51
+ y = v;
52
+ var H = ['x-powered-by', 'server'],
53
+ w = (r, e) => {
54
54
  let t = new Headers(r);
55
55
  return (headersToRemove.forEach(s => t.delete(s)), t.set('Host', e), t.set('User-Agent', 'IHUXY-API/1.0'), t);
56
56
  },
57
- w = r => {
57
+ g = r => {
58
58
  let e = new Headers(r);
59
59
  return (
60
- v.forEach(t => e.delete(t)),
60
+ H.forEach(t => e.delete(t)),
61
61
  e.set('Access-Control-Allow-Origin', '*'),
62
62
  e.set('X-Content-Type-Options', 'nosniff'),
63
63
  e.get('content-type')?.includes('text/event-stream') && ((e['Cache-Control'] = 'no-cache, no-transform'), (e.Connection = 'keep-alive'), (e['X-Accel-Buffering'] = 'no')),
64
64
  e
65
65
  );
66
66
  };
67
- var H = r => Object.prototype.toString.call(r).slice(8, -1).toLowerCase(),
68
- R = r => (H(r) === 'object' ? [r] : Array.isArray(r) ? r : []),
69
- g = (r, e) => R(r).map(t => ((t.prefix = `${e}${t.prefix ?? `/${t.name}`}`.replace('//', '/')), t)),
70
- P = (r, e) => ['/', '/health', e, ...r].map(t => `${e}${t}`.replace('//', '/'));
71
- var $ = ({target: r = 'http://localhost:11434', prefix: e = '/api', ...t} = {}, s = !1) => ({
67
+ var R = r => Object.prototype.toString.call(r).slice(8, -1).toLowerCase(),
68
+ E = r => (R(r) === 'object' ? [r] : Array.isArray(r) ? r : []),
69
+ A = (r, e) => E(r).map(t => ((t.prefix = `${e}${t.prefix ?? `/${t.name}`}`.replace('//', '/')), t)),
70
+ u = r => (Array.isArray(r) ? r : []).filter(Boolean),
71
+ P = (r, e) => ['/', '/health', e, ...u(r)].map(t => `${e}${t}`.replace('//', '/'));
72
+ var S = ({target: r = 'http://localhost:11434', prefix: e = '/api', ...t} = {}, s = !1) => ({
72
73
  target: r,
73
74
  pathRewrite: {[`^${e}`]: ''},
74
75
  changeOrigin: !0,
75
76
  selfHandleResponse: !1,
76
- onProxyReq: (n, a, o) => {
77
- !s && y(n.headers, r);
77
+ onProxyReq: (o, n, a) => {
78
+ !s && w(o.headers, r);
78
79
  },
79
- onProxyRes: (n, a, o) => {
80
- !s && w(n.headers);
80
+ onProxyRes: (o, n, a) => {
81
+ !s && g(o.headers);
81
82
  },
82
- onError: (n, a, o) => {
83
- (a.log.error({err: n}, '\u4EE3\u7406\u9519\u8BEF'), o.headersSent || o.status(502).json({error: '\u7F51\u5173\u9519\u8BEF'}));
83
+ onError: (o, n, a) => {
84
+ (n.log.error({err: o}, '\u4EE3\u7406\u9519\u8BEF'), a.headersSent || a.status(502).json({error: '\u7F51\u5173\u9519\u8BEF'}));
84
85
  },
85
86
  ...t,
86
87
  }),
87
- S = (r, e) => {
88
- let t = {status: 'OK', message: `API \u670D\u52A1\u5668\u8FD0\u884C\u4E2D -> ${e}`, timestamp: I(), uptime: process.uptime(), memoryUsage: process.memoryUsage()};
89
- r.get(`${e}/health`.replace('//', '/'), (s, n) => {
90
- n.status(200).json(t);
91
- });
88
+ k = (r, e) => {
89
+ let t = {status: 'OK', message: `API \u670D\u52A1\u5668\u8FD0\u884C\u4E2D \u{1F449} ${e}`, timestamp: $(), uptime: process.uptime(), memoryUsage: process.memoryUsage()};
90
+ (r.get(e, (s, o) => {
91
+ o.status(200).json(t);
92
+ }),
93
+ r.get(`${e}/health`.replace('//', '/'), (s, o) => {
94
+ o.status(200).json(t);
95
+ }));
92
96
  },
93
- k = (r, e = {}, t) => {
94
- let {apiPrefix: s, proxys: n = [], whiteAuthKeys: a = [], whitePathList: o = [], preserve: p = !1} = e,
95
- c = g(n, s);
97
+ C = (r, e = {}, t) => {
98
+ let {apiPrefix: s, proxys: o = [], whiteAuthKeys: n = [], whitePathList: a = [], preserve: i = !1} = e,
99
+ c = A(o, s);
96
100
  if (!c.length) return;
97
- (t.info(`\u{1F4DD} API \u63A5\u53E3\u5730\u5740: http://${e.host}:${e.port}${s}`), S(r, s));
98
- let u = x({whiteAuthKeys: a, whitePathList: P(o, s), config: e});
99
- c.map(({prefix: i, target: h}) => {
100
- let A = $({prefix: i, target: h}, p);
101
- (r.use(i, u, E(A)), t.info(`\u2705 \u4EE3\u7406\u4E2D ${i} -> ${h}`));
101
+ (t.info(`\u{1F4DD} API \u63A5\u53E3\u5730\u5740: http://${e.host}:${e.port}${s}`), k(r, s));
102
+ let l = y({whiteAuthKeys: u(n), whitePathList: P(a, s), config: e});
103
+ c.map(({prefix: p, target: h}) => {
104
+ let j = S({prefix: p, target: h}, i);
105
+ (r.use(p, l, I(j)), t.info(`\u2705 \u4EE3\u7406\u4E2D ${p} \u{1F449} ${h}`));
102
106
  });
103
107
  },
104
- l = k;
105
- var C = {
108
+ d = C;
109
+ var O = {
106
110
  port: parseInt(process.env.PORT || '8080', 10),
107
111
  host: process.env.HOST || 'localhost',
108
112
  apiPrefix: process.env.API_PREFIX || '/api',
109
- authToken: '1234',
113
+ authToken: !1,
110
114
  proxys: [],
111
- whiteAuthKeys: ['ihuxy'],
112
115
  whitePathList: ['/health'],
113
116
  algorithm: 'HS256',
114
117
  secret: process.env.JWT_SECRET || 'ah.yiru@gmail.com',
115
118
  expiresIn: process.env.JWT_EXPIRES_IN || '30d',
116
119
  issuer: process.env.JWT_ISSUER || 'huxyApp',
117
120
  },
118
- d = C;
119
- var L = (r, e) =>
120
- O({...d, ...r}, async (t, s, n, a) => {
121
- (await e?.(t, s, n, a), l(s, t, a));
121
+ m = O;
122
+ var M = (r, e) =>
123
+ W({...m, ...r}, async (t, s, o, n) => {
124
+ (await e?.(t, s, o, n), d(s, t, n));
122
125
  }),
123
- ce = L,
124
- he = (r, e) =>
125
- W({...d, ...r}, async (t, s, n, a) => {
126
- (await e?.(t, s, n, a), l(s, t, a));
126
+ he = M,
127
+ le = (r, e) =>
128
+ L({...m, ...r}, async (t, s, o, n) => {
129
+ (await e?.(t, s, o, n), d(s, t, n));
127
130
  });
128
131
  export {
129
- l as appProxy,
130
- oe as checkPort,
131
- q as createLogger,
132
- ee as dateTime,
133
- ce as default,
134
- ae as getDirName,
135
- se as getEnvConfig,
136
- te as localIPs,
137
- Z as logger,
138
- re as nodeArgs,
139
- ne as resolvePath,
140
- L as startApp,
141
- O as startServer,
142
- W as startStatic,
143
- he as startStaticApp,
132
+ d as appProxy,
133
+ ae as checkPort,
134
+ ee as createLogger,
135
+ te as dateTime,
136
+ he as default,
137
+ ne as getDirName,
138
+ oe as getEnvConfig,
139
+ re as localIPs,
140
+ q as logger,
141
+ se as nodeArgs,
142
+ ie as resolvePath,
143
+ M as startApp,
144
+ W as startServer,
145
+ L as startStatic,
146
+ le as startStaticApp,
144
147
  };