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

Express+Handlebars表单提交404及属性访问权限报错求助

问题解决:POST请求404与Handlebars警告

控制台错误信息

GET /admin/add-product 200 70.156 ms - 3932
Handlebars: 解析属性"status"被拒绝,因为它不是父级的"自有属性"。
你可以添加运行时选项来禁用检查或此警告,详情可查看Handlebars官方文档的运行时选项章节。
POST /admin/add-product 404 31.120 ms - 3921

问题描述

我在Admin页面提交表单收集数据时,POST请求返回404"not found",控制台输出上述错误,但nodemon还在正常运行。相关代码文件如下:

相关代码文件

app.js

var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
const { engine : hbs } = require("express-handlebars")
var fileUpload = require('express-fileupload')
var userRouter = require('./routes/user');
var adminRouter = require('./routes/admin');
var handlebars = require('handlebars')
const template = handlebars.compile("{{aString.trim}}");
const result = template(
  { aString: "  abc  " },
  {
    allowedProtoMethods: {
      trim: true
    }
  }
);
var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'hbs');
app.engine('hbs',hbs({extname:'hbs',defaultLayout:'layout',layoutsDir:__dirname+'/views/layout/',partialsDir:__dirname+'/views/partials/'}))
app.use(fileUpload())
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', userRouter);
app.use('/admin', adminRouter);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  next(createError(404));
});

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;

admin.js

var express = require('express');
const { log } = require('handlebars');
var router = express.Router();

/* GET users listing. */
router.get('/', function(req, res, next) {

  let products = [
    {
        name:"Apple iPhone 15",
        description:"Apple iPhone 15 (128 GB) - Black",
        category:"Mobile",
        price:"₹72,690",
        image:"https://m.media-amazon.com/images/I/71657TiFeHL._SX679_.jpg"
    },
    {
        name:"Apple iPhone 15 Plus",
        description:"Apple iPhone 15 Plus (128 GB) - Blue",
        category:"Mobile",
        price:"₹80,990",
        image:"https://m.media-amazon.com/images/I/71PjpS59XLL._SX679_.jpg"
    },
    {
        name:"Apple iPhone 15 Pro",
        description:"Apple iPhone 15 Pro (1 TB) - Black Titanium",
        category:"Mobile",
        price:"₹1,77,990",
        image:"https://m.media-amazon.com/images/I/81+GIkwqLIL._SX679_.jpg"
    },
    {
        name:"Apple iPhone 15 Pro Max",
        description:"Apple iPhone 15 Pro Max (256 GB) - Black Titanium",
        category:"Mobile",
        price:"₹1,48,900",
        image:"https://m.media-amazon.com/images/I/81Os1SDWpcL._SX679_.jpg"
    }
]

  res.render('admin/view-products',{products,admin:true})
});

router.get('/add-product',(req,res)=>{
  res.render('admin/add-product')
})

router.post('/admin/add-product',(req,res)=>{
    console.log(req.body);
    console.log(req.files.Image);
})

module.exports = router;

add-product.hbs

<section>
    <div class="container">
        <div class="row">
            <div class="col-md-6">
                <h2 class="text-center">Add Product</h2>
                <form action="/admin/add-product" method="post" enctype="multipart/form-data">
                
                    <label for="">Name</label>
                    <input type="text" name="Name" class="form-control">

                    <label for="">Description</label>
                    <input type="text" name="Description" class="form-control">

                    <label for="">Category</label>
                    <input type="text" name="Category" class="form-control">

                    <label for="">Price</label>
                    <input type="text" name="Price" class="form-control">

                    <label for="">Image</label>
                    <input type="file" name="Image" class="form-control">

                    <br>

                    <button type="submit" class="btn btn-success">Submit</button>

                </form>
            </div>
        </div>
    </div>
</section>

解决方案

1. 修复POST请求404问题

问题出在admin.js的POST路由配置:当前代码中路由是router.post('/admin/add-product', ...),但adminRouter已经通过app.use('/admin', adminRouter)挂载到/admin路径下,这会导致实际匹配的路径变成/admin/admin/add-product,和表单的action="/admin/add-product"不匹配。

修改admin.js中的POST路由:

router.post('/add-product',(req,res)=>{
    console.log(req.body);
    console.log(req.files.Image);
    // 添加响应逻辑,比如重定向回添加页面
    res.redirect('/admin/add-product');
})

2. 解决Handlebars警告问题

要消除"解析属性'status'被拒绝"的警告,需要在express-handlebars的引擎配置中添加运行时选项,允许访问原型属性或方法:

修改app.js中的引擎配置:

app.engine('hbs',hbs({
    extname:'hbs',
    defaultLayout:'layout',
    layoutsDir:__dirname+'/views/layout/',
    partialsDir:__dirname+'/views/partials/',
    runtimeOptions: {
        allowProtoPropertiesByDefault: true,
        allowProtoMethodsByDefault: true
    }
}))

内容的提问来源于stack exchange,提问作者Thejas Krishna L

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 05:42:06