You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Express接收HTML表单提交时出现404错误求助

问题排查与修复方案

一、Apache反向代理配置问题

你的Apache代理配置不完整,仅添加ProxyPass会导致请求转发异常,需补充以下配置:

  1. 确保已启用代理模块(你提到取消了注释,确认是以下两行):
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
  1. 完善代理规则,添加ProxyPassReverse并注意路径末尾的斜杠:
ProxyPass / http://localhost:8000/
ProxyPassReverse / http://localhost:8000/
  1. 重启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'));
    });
});

四、测试步骤

  1. 先绕过Apache代理,直接访问http://localhost:8000,打开表单提交测试,若正常则问题在Apache配置;若仍报错,检查Express服务是否启动、数据库连接是否正常。
  2. 确认Apache代理配置生效后,通过Apache端口(默认80)访问测试。

内容的提问来源于stack exchange,提问作者wayta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 07:33:52