agent-publish-server 1.0.24 → 1.0.25

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 CHANGED
@@ -228,8 +228,9 @@ agent-publish-server --log false
228
228
 
229
229
  ### 版本历史
230
230
 
231
- - **v1.0.24**: 修复移动端兼容性问题,优化HTTP响应头设置,确保iOS和Android显示一致性
232
- - **v1.0.23**: 完善双语文档支持,优化package.json关键词,提升npm包曝光度
231
+ - **v1.0.25**: 修复 staticProxy static 类型不支持 SPA History 路由刷新的问题,添加自动 fallback 到 index.html 支持
232
+ - **v1.0.24**: 修复移动端兼容性问题,优化 HTTP 响应头设置,确保 iOS 和 Android 显示一致性
233
+ - **v1.0.23**: 完善双语文档支持,优化 package.json 关键词,提升 npm 包曝光度
233
234
  - **v1.0.22**: 优化和完善 staticProxy 功能,提升稳定性
234
235
  - **v1.0.18**: 增强 staticProxy 功能,支持静态文件代理和 HTTP 服务代理两种模式
235
236
  - **v1.0.17**: 新增静态网页代理功能(staticProxy),支持与 API 代理同时使用
package/README_EN.md CHANGED
@@ -229,6 +229,7 @@ startServer(app, config.port);
229
229
 
230
230
  ## Version History
231
231
 
232
+ - **v1.0.25**: Fixed staticProxy static type not supporting SPA History route refresh, added automatic fallback to index.html
232
233
  - **v1.0.24**: Fixed mobile compatibility issues, optimized HTTP response headers for consistent iOS and Android display
233
234
  - **v1.0.23**: Enhanced bilingual documentation support, optimized package.json keywords for better npm exposure
234
235
  - **v1.0.22**: Optimized and improved staticProxy functionality, enhanced stability
package/dist/cli.js CHANGED
File without changes
package/dist/server.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- import { AgentConfig } from './types';
1
+ import { AgentConfig } from "./types";
2
2
  export declare function createServer(config: AgentConfig): import("express-serve-static-core").Express;
3
3
  export declare function startServer(config: AgentConfig): Promise<void>;
package/dist/server.js CHANGED
@@ -11,12 +11,12 @@ const path_1 = __importDefault(require("path"));
11
11
  const fs_1 = __importDefault(require("fs"));
12
12
  function createServer(config) {
13
13
  const app = (0, express_1.default)();
14
- const staticDir = config.dir || './';
14
+ const staticDir = config.dir || "./";
15
15
  const enableLog = config.log !== false; // 默认为true
16
16
  // 检查项目路径是否存在
17
17
  const absoluteStaticDir = path_1.default.resolve(process.cwd(), staticDir);
18
18
  if (!fs_1.default.existsSync(absoluteStaticDir)) {
19
- throw new Error('项目路径错误');
19
+ throw new Error("项目路径错误");
20
20
  }
21
21
  // 添加日志中间件
22
22
  if (enableLog) {
@@ -24,8 +24,8 @@ function createServer(config) {
24
24
  const timestamp = new Date().toISOString();
25
25
  const method = req.method;
26
26
  const url = req.url;
27
- const userAgent = req.get('User-Agent') || '-';
28
- const ip = req.ip || req.connection.remoteAddress || '-';
27
+ const userAgent = req.get("User-Agent") || "-";
28
+ const ip = req.ip || req.connection.remoteAddress || "-";
29
29
  console.log(`[${timestamp}] ${ip} "${method} ${url}" "${userAgent}"`);
30
30
  next();
31
31
  });
@@ -39,41 +39,59 @@ function createServer(config) {
39
39
  // 配置静态网页代理
40
40
  if (config.staticProxy) {
41
41
  Object.entries(config.staticProxy).forEach(([proxyPath, staticProxyConfig]) => {
42
- const proxyType = staticProxyConfig.type || 'http'; // 默认为http类型
43
- if (proxyType === 'static') {
42
+ const proxyType = staticProxyConfig.type || "http"; // 默认为http类型
43
+ if (proxyType === "static") {
44
44
  // 静态文件代理
45
45
  const staticPath = path_1.default.resolve(process.cwd(), staticProxyConfig.target);
46
46
  if (!fs_1.default.existsSync(staticPath)) {
47
47
  console.warn(`Warning: Static proxy path does not exist: ${staticPath}`);
48
48
  return;
49
49
  }
50
+ // 静态文件服务
50
51
  app.use(proxyPath, express_1.default.static(staticPath, {
51
52
  setHeaders: (res, filePath, stat) => {
52
53
  // 设置通用响应头,提升移动端兼容性
53
- res.setHeader('X-Content-Type-Options', 'nosniff');
54
- res.setHeader('X-Frame-Options', 'SAMEORIGIN');
55
- res.setHeader('X-XSS-Protection', '1; mode=block');
54
+ res.setHeader("X-Content-Type-Options", "nosniff");
55
+ res.setHeader("X-Frame-Options", "SAMEORIGIN");
56
+ res.setHeader("X-XSS-Protection", "1; mode=block");
56
57
  // 针对HTML文件设置移动端优化响应头
57
- if (filePath.endsWith('.html')) {
58
- res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate');
59
- res.setHeader('Pragma', 'no-cache');
60
- res.setHeader('Expires', '0');
61
- res.setHeader('Content-Type', 'text/html; charset=utf-8');
58
+ if (filePath.endsWith(".html")) {
59
+ res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
60
+ res.setHeader("Pragma", "no-cache");
61
+ res.setHeader("Expires", "0");
62
+ res.setHeader("Content-Type", "text/html; charset=utf-8");
62
63
  }
63
64
  // 针对CSS文件确保正确的Content-Type
64
- if (filePath.endsWith('.css')) {
65
- res.setHeader('Content-Type', 'text/css; charset=utf-8');
65
+ if (filePath.endsWith(".css")) {
66
+ res.setHeader("Content-Type", "text/css; charset=utf-8");
66
67
  }
67
68
  // 针对JS文件确保正确的Content-Type
68
- if (filePath.endsWith('.js')) {
69
- res.setHeader('Content-Type', 'application/javascript; charset=utf-8');
69
+ if (filePath.endsWith(".js")) {
70
+ res.setHeader("Content-Type", "application/javascript; charset=utf-8");
70
71
  }
71
72
  // 针对图片文件设置适当的缓存
72
73
  if (filePath.match(/\.(jpg|jpeg|png|gif|webp|svg)$/i)) {
73
- res.setHeader('Cache-Control', 'public, max-age=31536000');
74
+ res.setHeader("Cache-Control", "public, max-age=31536000");
74
75
  }
75
- }
76
+ },
76
77
  }));
78
+ // SPA fallback:静态文件不存在时回退到 index.html
79
+ app.use(proxyPath, (req, res, next) => {
80
+ const reqPath = req.path === "/" ? "" : req.path;
81
+ const filePath = path_1.default.join(staticPath, reqPath);
82
+ const indexPath = path_1.default.join(staticPath, "index.html");
83
+ // 如果请求的文件存在,跳过(已被 express.static 处理)
84
+ if (fs_1.default.existsSync(filePath) && fs_1.default.statSync(filePath).isFile()) {
85
+ return next();
86
+ }
87
+ // 如果 index.html 存在,返回它(SPA fallback)
88
+ if (fs_1.default.existsSync(indexPath)) {
89
+ res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
90
+ res.setHeader("Content-Type", "text/html; charset=utf-8");
91
+ return res.sendFile(indexPath);
92
+ }
93
+ next();
94
+ });
77
95
  }
78
96
  else {
79
97
  // HTTP服务代理
@@ -81,8 +99,8 @@ function createServer(config) {
81
99
  target: staticProxyConfig.target,
82
100
  changeOrigin: staticProxyConfig.changeOrigin !== false, // 默认为true
83
101
  pathRewrite: {
84
- [`^${proxyPath}`]: '' // 移除代理路径前缀
85
- }
102
+ [`^${proxyPath}`]: "", // 移除代理路径前缀
103
+ },
86
104
  }));
87
105
  }
88
106
  });
@@ -91,39 +109,39 @@ function createServer(config) {
91
109
  app.use(express_1.default.static(staticDir, {
92
110
  setHeaders: (res, filePath, stat) => {
93
111
  // 设置通用响应头,提升移动端兼容性
94
- res.setHeader('X-Content-Type-Options', 'nosniff');
95
- res.setHeader('X-Frame-Options', 'SAMEORIGIN');
96
- res.setHeader('X-XSS-Protection', '1; mode=block');
112
+ res.setHeader("X-Content-Type-Options", "nosniff");
113
+ res.setHeader("X-Frame-Options", "SAMEORIGIN");
114
+ res.setHeader("X-XSS-Protection", "1; mode=block");
97
115
  // 针对HTML文件设置移动端优化响应头
98
- if (filePath.endsWith('.html')) {
99
- res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate');
100
- res.setHeader('Pragma', 'no-cache');
101
- res.setHeader('Expires', '0');
116
+ if (filePath.endsWith(".html")) {
117
+ res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
118
+ res.setHeader("Pragma", "no-cache");
119
+ res.setHeader("Expires", "0");
102
120
  // 确保正确的Content-Type
103
- res.setHeader('Content-Type', 'text/html; charset=utf-8');
121
+ res.setHeader("Content-Type", "text/html; charset=utf-8");
104
122
  }
105
123
  // 针对CSS文件确保正确的Content-Type
106
- if (filePath.endsWith('.css')) {
107
- res.setHeader('Content-Type', 'text/css; charset=utf-8');
124
+ if (filePath.endsWith(".css")) {
125
+ res.setHeader("Content-Type", "text/css; charset=utf-8");
108
126
  }
109
127
  // 针对JS文件确保正确的Content-Type
110
- if (filePath.endsWith('.js')) {
111
- res.setHeader('Content-Type', 'application/javascript; charset=utf-8');
128
+ if (filePath.endsWith(".js")) {
129
+ res.setHeader("Content-Type", "application/javascript; charset=utf-8");
112
130
  }
113
131
  // 针对图片文件设置适当的缓存
114
132
  if (filePath.match(/\.(jpg|jpeg|png|gif|webp|svg)$/i)) {
115
- res.setHeader('Cache-Control', 'public, max-age=31536000');
133
+ res.setHeader("Cache-Control", "public, max-age=31536000");
116
134
  }
117
- }
135
+ },
118
136
  }));
119
137
  // 添加移动端兼容性中间件
120
138
  app.use((req, res, next) => {
121
139
  // 检测移动端User-Agent并设置相应响应头
122
- const userAgent = req.get('User-Agent') || '';
140
+ const userAgent = req.get("User-Agent") || "";
123
141
  const isMobile = /Mobile|Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(userAgent);
124
142
  if (isMobile) {
125
143
  // 为移动端设置额外的响应头
126
- res.setHeader('Vary', 'User-Agent');
144
+ res.setHeader("Vary", "User-Agent");
127
145
  }
128
146
  next();
129
147
  });
@@ -131,7 +149,7 @@ function createServer(config) {
131
149
  // 只有当实际文件不存在时才回退到index.html
132
150
  app.use((req, res, next) => {
133
151
  // 排除API和已处理的代理请求
134
- if (req.path.startsWith('/api/')) {
152
+ if (req.path.startsWith("/api/")) {
135
153
  return next();
136
154
  }
137
155
  // 排除静态代理路径
@@ -146,7 +164,7 @@ function createServer(config) {
146
164
  // 检查是否为目录
147
165
  if (fs_1.default.existsSync(filePath) && fs_1.default.statSync(filePath).isDirectory()) {
148
166
  // 检查目录中是否有index.html
149
- const indexPath = path_1.default.join(filePath, 'index.html');
167
+ const indexPath = path_1.default.join(filePath, "index.html");
150
168
  if (fs_1.default.existsSync(indexPath)) {
151
169
  return res.sendFile(indexPath);
152
170
  }
@@ -156,7 +174,7 @@ function createServer(config) {
156
174
  return res.sendFile(filePath);
157
175
  }
158
176
  // 如果路径不存在,回退到index.html
159
- res.sendFile(path_1.default.join(process.cwd(), staticDir, 'index.html'));
177
+ res.sendFile(path_1.default.join(process.cwd(), staticDir, "index.html"));
160
178
  });
161
179
  return app;
162
180
  }
@@ -172,7 +190,7 @@ function startServer(config) {
172
190
  });
173
191
  }
174
192
  catch (error) {
175
- console.error('Failed to start server:', error);
193
+ console.error("Failed to start server:", error);
176
194
  reject(error);
177
195
  }
178
196
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-publish-server",
3
- "version": "1.0.24",
3
+ "version": "1.0.25",
4
4
  "description": "A powerful frontend development server with API proxy, static file serving, and dual-mode static proxy support. Built with Node.js + Express + http-proxy-middleware. 基于 Node.js + Express + http-proxy-middleware 的强大前端开发服务器,支持API代理、静态文件服务和双模式静态代理。",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",