agent-publish-server 1.0.23 → 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,7 +228,9 @@ agent-publish-server --log false
228
228
 
229
229
  ### 版本历史
230
230
 
231
- - **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 包曝光度
232
234
  - **v1.0.22**: 优化和完善 staticProxy 功能,提升稳定性
233
235
  - **v1.0.18**: 增强 staticProxy 功能,支持静态文件代理和 HTTP 服务代理两种模式
234
236
  - **v1.0.17**: 新增静态网页代理功能(staticProxy),支持与 API 代理同时使用
package/README_EN.md CHANGED
@@ -229,6 +229,9 @@ 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
233
+ - **v1.0.24**: Fixed mobile compatibility issues, optimized HTTP response headers for consistent iOS and Android display
234
+ - **v1.0.23**: Enhanced bilingual documentation support, optimized package.json keywords for better npm exposure
232
235
  - **v1.0.22**: Optimized and improved staticProxy functionality, enhanced stability
233
236
  - **v1.0.18**: Enhanced staticProxy functionality, supporting both static file proxy and HTTP service proxy modes
234
237
  - **v1.0.17**: Added static web proxy functionality (staticProxy), supports simultaneous use with API proxy
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,15 +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
- app.use(proxyPath, express_1.default.static(staticPath));
50
+ // 静态文件服务
51
+ app.use(proxyPath, express_1.default.static(staticPath, {
52
+ setHeaders: (res, filePath, stat) => {
53
+ // 设置通用响应头,提升移动端兼容性
54
+ res.setHeader("X-Content-Type-Options", "nosniff");
55
+ res.setHeader("X-Frame-Options", "SAMEORIGIN");
56
+ res.setHeader("X-XSS-Protection", "1; mode=block");
57
+ // 针对HTML文件设置移动端优化响应头
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");
63
+ }
64
+ // 针对CSS文件确保正确的Content-Type
65
+ if (filePath.endsWith(".css")) {
66
+ res.setHeader("Content-Type", "text/css; charset=utf-8");
67
+ }
68
+ // 针对JS文件确保正确的Content-Type
69
+ if (filePath.endsWith(".js")) {
70
+ res.setHeader("Content-Type", "application/javascript; charset=utf-8");
71
+ }
72
+ // 针对图片文件设置适当的缓存
73
+ if (filePath.match(/\.(jpg|jpeg|png|gif|webp|svg)$/i)) {
74
+ res.setHeader("Cache-Control", "public, max-age=31536000");
75
+ }
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
+ });
51
95
  }
52
96
  else {
53
97
  // HTTP服务代理
@@ -55,19 +99,57 @@ function createServer(config) {
55
99
  target: staticProxyConfig.target,
56
100
  changeOrigin: staticProxyConfig.changeOrigin !== false, // 默认为true
57
101
  pathRewrite: {
58
- [`^${proxyPath}`]: '' // 移除代理路径前缀
59
- }
102
+ [`^${proxyPath}`]: "", // 移除代理路径前缀
103
+ },
60
104
  }));
61
105
  }
62
106
  });
63
107
  }
64
- // 配置静态文件服务
65
- app.use(express_1.default.static(staticDir));
108
+ // 配置静态文件服务,添加移动端兼容性响应头
109
+ app.use(express_1.default.static(staticDir, {
110
+ setHeaders: (res, filePath, stat) => {
111
+ // 设置通用响应头,提升移动端兼容性
112
+ res.setHeader("X-Content-Type-Options", "nosniff");
113
+ res.setHeader("X-Frame-Options", "SAMEORIGIN");
114
+ res.setHeader("X-XSS-Protection", "1; mode=block");
115
+ // 针对HTML文件设置移动端优化响应头
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");
120
+ // 确保正确的Content-Type
121
+ res.setHeader("Content-Type", "text/html; charset=utf-8");
122
+ }
123
+ // 针对CSS文件确保正确的Content-Type
124
+ if (filePath.endsWith(".css")) {
125
+ res.setHeader("Content-Type", "text/css; charset=utf-8");
126
+ }
127
+ // 针对JS文件确保正确的Content-Type
128
+ if (filePath.endsWith(".js")) {
129
+ res.setHeader("Content-Type", "application/javascript; charset=utf-8");
130
+ }
131
+ // 针对图片文件设置适当的缓存
132
+ if (filePath.match(/\.(jpg|jpeg|png|gif|webp|svg)$/i)) {
133
+ res.setHeader("Cache-Control", "public, max-age=31536000");
134
+ }
135
+ },
136
+ }));
137
+ // 添加移动端兼容性中间件
138
+ app.use((req, res, next) => {
139
+ // 检测移动端User-Agent并设置相应响应头
140
+ const userAgent = req.get("User-Agent") || "";
141
+ const isMobile = /Mobile|Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(userAgent);
142
+ if (isMobile) {
143
+ // 为移动端设置额外的响应头
144
+ res.setHeader("Vary", "User-Agent");
145
+ }
146
+ next();
147
+ });
66
148
  // 添加SPA应用的回退路由处理
67
149
  // 只有当实际文件不存在时才回退到index.html
68
150
  app.use((req, res, next) => {
69
151
  // 排除API和已处理的代理请求
70
- if (req.path.startsWith('/api/')) {
152
+ if (req.path.startsWith("/api/")) {
71
153
  return next();
72
154
  }
73
155
  // 排除静态代理路径
@@ -82,7 +164,7 @@ function createServer(config) {
82
164
  // 检查是否为目录
83
165
  if (fs_1.default.existsSync(filePath) && fs_1.default.statSync(filePath).isDirectory()) {
84
166
  // 检查目录中是否有index.html
85
- const indexPath = path_1.default.join(filePath, 'index.html');
167
+ const indexPath = path_1.default.join(filePath, "index.html");
86
168
  if (fs_1.default.existsSync(indexPath)) {
87
169
  return res.sendFile(indexPath);
88
170
  }
@@ -92,7 +174,7 @@ function createServer(config) {
92
174
  return res.sendFile(filePath);
93
175
  }
94
176
  // 如果路径不存在,回退到index.html
95
- res.sendFile(path_1.default.join(process.cwd(), staticDir, 'index.html'));
177
+ res.sendFile(path_1.default.join(process.cwd(), staticDir, "index.html"));
96
178
  });
97
179
  return app;
98
180
  }
@@ -108,7 +190,7 @@ function startServer(config) {
108
190
  });
109
191
  }
110
192
  catch (error) {
111
- console.error('Failed to start server:', error);
193
+ console.error("Failed to start server:", error);
112
194
  reject(error);
113
195
  }
114
196
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-publish-server",
3
- "version": "1.0.23",
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",