Express接收HTML表单提交时出现404错误求助
问题排查与修复方案
一、Apache反向代理配置问题
你的Apache代理配置不完整,仅添加ProxyPass会导致请求转发异常,需补充以下配置:
- 确保已启用代理模块(你提到取消了注释,确认是以下两行):
LoadModule proxy_module modules/mod_proxy.so LoadModule proxy_http_module modules/mod_proxy_http.so
- 完善代理规则,添加
ProxyPassReverse并注意路径末尾的斜杠:
ProxyPass / http://localhost:8000/ ProxyPassReverse / http://localhost:8000/
- 重启Apache服务,确保配置生效。
二、Express代码中的核心问题
你的Node.js代码存在多处逻辑错误,会导致请求处理失败甚至服务异常:
1. 混用await与回调函数
con.promise().query返回Promise,无需搭配回调函数,正确写法应直接用await获取结果,且查询返回的rows是数组,需取第一个元素的id:
// 错误写法 await con.promise().query(sql, [req.body.from_country], (err, rows) => { ... }) // 正确写法 let [rows] = await con.promise().query(sql, [req.body.from_country]); const probeId = rows[0]?.id; // 可选链避免无结果时报错
2. 错误关闭数据库连接
在POST请求中调用con.end()会直接关闭数据库连接,后续所有请求都无法再访问数据库,应改用连接池管理连接,而非单次请求后关闭:
// 替换单连接为连接池 const pool = mysql.createPool({ host:'localhost', user:'root', password:'', database:'probes&anchors', connectionLimit: 10 }); const promisePool = pool.promise(); // 用连接池执行查询 let [rows] = await promisePool.query(sql, [from_country]);
3. 全局变量污染风险
probes、to_country等全局变量会导致并发请求的数据相互覆盖,应将其移至请求处理函数内部:
app.post('/', async function(req, res) { const { from_country, to_country } = req.body; let probes = []; // 局部变量,避免污染 // ...后续逻辑 });
三、修复后的完整Express代码
import mysql from 'mysql2'; import express from 'express'; import path from 'path'; const app = express(); const __dirname = path.resolve(); app.use(express.urlencoded({ extended: true })); app.use(express.static(__dirname)); // 使用连接池管理数据库连接 const pool = mysql.createPool({ host: 'localhost', user: 'root', password: '', database: 'probes&anchors', connectionLimit: 10, waitForConnections: true }); const promisePool = pool.promise(); app.post('/', async function(req, res) { try { const { from_country, to_country } = req.body; // 校验参数是否存在 if (!from_country || !to_country) { return res.status(400).send('Please select both countries'); } const sql = 'SELECT id FROM probes WHERE country=?'; const [rows] = await promisePool.query(sql, [from_country]); if (rows.length === 0) { return res.send('No matching probe found for the selected country'); } const probeId = rows[0].id; console.log('Probe id:', probeId); res.send(`Loaded successfully! Probe ID: ${probeId}`); } catch (err) { console.error('Database query error:', err); res.status(500).send('Internal Server Error'); } }); app.get('/', (req, res) => res.send('Hello World! From Node.js')); const server = app.listen(8000, () => console.log('Example app listening on port 8000!')); // 服务器关闭时释放连接池 process.on('SIGTERM', () => { pool.end(err => { if (err) console.error('Failed to close pool:', err); server.close(() => console.log('Server closed')); }); });
四、测试步骤
- 先绕过Apache代理,直接访问
http://localhost:8000,打开表单提交测试,若正常则问题在Apache配置;若仍报错,检查Express服务是否启动、数据库连接是否正常。 - 确认Apache代理配置生效后,通过Apache端口(默认80)访问测试。
内容的提问来源于stack exchange,提问作者wayta
相关产品推荐
相关产品推荐

