【问题标题】:can't understand routing in node/express4无法理解 node/express4 中的路由
【发布时间】:2015-10-08 11:07:06
【问题描述】:

请帮忙解决路由问题:

var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var methodOverride = require('method-override');
var router = express.Router();

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.engine('html', require('ejs').renderFile);
app.set('view engine', 'html');

// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(methodOverride());
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

// data storage in memory
var widgets = [
  {id: 1,
   name: 'My special widget',
   price: 100.00,
   descr: 'A widget beyond price'},
];

// routes

app.use(router);

router.get('/', function(req, res, next) {
  res.render('index');
});

router.get('/widgets', function(req, res) {
  res.send(widgets);
});

router.post('/widgets/add', function(req, res) {
  var indx = widgets.length + 1;
  widgets[widgets.length] = {  id: indx,
                               name: req.body.widgetname,
                               price: parseFloat(req.body.widgetprice),
                               descr: req.body.widgetdesc
                            };
  console.log('added ' + widgets[indx - 1]);
  res.send('Widget ' + req.body.widgetname + ' added with id ' + indx);  
});

router.get('/widgets/:id', function(req, res) {
  var indx = parseInt(req.params.id) - 1;
  if (!widgets[indx]) {
    res.send('There is no widget with id of ' + req.params.id);
  } else {
    res.send(widgets[indx]);
  }
});

router.put('/widgets/:id/update', function(req, res) {
  var indx = req.params.id - 1;
  widgets[indx] = {id: indx,
                   name: req.body.widgetname,
                   price: parseFloat(req.body.widgetprice),
                   descr: req.body.widgetdesc};
  console.log(widgets[indx]);
  res.send('updated ' + req.params.id);
});

router.delete('/widgets/:id/delete', function(req, res) {
  var indx = req.params.id - 1;
  delete widgets[indx];
  console.log('deleted ' + req.params.id);
  res.send('deleted ' + req.params.id);  
});

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// error handlers

// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
  app.use(function(err, req, res, next) {
    res.status(err.status || 500);
    res.render('error', {
      message: err.message,
      error: err
    });
  });
}

// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
  res.status(err.status || 500);
  res.render('error', {
    message: err.message,
    error: {}
  });
});


module.exports = app;

我在 VIEWS 文件夹中有 3 个 html 文件: 1 - 索引

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="utf-8" />
	<title>Widgets</title>
</head>
<body>

	<form action="/widgets/add" method="POST" enctype="application/x-www-form-urlencoded">
		
		<p>Widget name:<input type="text" name="widgetname" id="widgetname" size="25" required /></p>

		<p>Widget price:<input type="text" name="widgetprice" id="widgetprice" size="25" required
			pattern="^\$?([0-9]{1,3},([0-9]{3},)*[0-9]{3}|[0-9]+)(.[0-9][0-9])?$" /></p>

		<p>Widget description: <br/> <textarea name="widgetdesc" id="widgetdesc" cols="20"
			rows="5">Describe widget</textarea></p>
		<p>
			<input type="submit" name="submit" id="submit" value="Submit" />
			<input type="reset" name="reset" id="reset" value="Reset" />
		</p>

	</form>

</body>
</html>

2 - 更新

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="utf-8" />
	<title>Widgets</title>
</head>
<body>

	<form method="POST" action="/widgets/1/update" enctype="application/x-www-form-urlencoded">
		
		<p>Widget name:<input type="text" name="widgetname" id="widgetname" size="25" value="Me special widget" required /></p>

		<p>Widget price:<input type="text" name="widgetprice" id="widgetprice" size="25" required
			pattern="^\$?([0-9]{1,3},([0-9]{3},)*[0-9]{3}|[0-9]+)(.[0-9][0-9])?$" value="100.00" /></p>

		<p>Widget description: <br/> <textarea name="widgetdesc" id="widgetdesc" cols="20"
			rows="5">A widget beyond price</textarea></p>

		<input type="hidden" value="put" name="_method" />

		<p>
			<input type="submit" name="submit" id="submit" value="Submit" />
			<input type="reset" name="reset" id="reset" value="Reset" />
		</p>

	</form>

</body>
</html>

3 - 删除

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="utf-8" />
	<title>Widgets</title>
</head>
<body>
	<p>Are you sure you want to delete widget?</p>
	
	<form method="POST" action="/widgets/1/delete" enctype="application/x-www-form-urlencoded">
		
		<input type="hidden" value="delete" name="_method" />
		
		<p>
			<input type="submit" name="submit" id="submit" value="Delete Widget" />
		</p>

	</form>

</body>
</html>

问题是 PUT 和 DELETE 显示错误,我无法理解我应该怎么做才能更正它。

【问题讨论】:

    标签: node.js express express-4


    【解决方案1】:

    这个例子有一些问题。我会从最重要到最不重要的顺序来解决它们。

    方法混乱

    REST 或 RE表示性 State Ttransfer,定义了具有不同目的的所谓 HTTP 动词。

    • GET:获取资源
    • POST:创建资源
    • PUT:覆盖资源
    • PATCH:部分修改资源
    • DELETE:删除资源
    • 还有其他一些

    需要注意的一点是,在快速路由器中,即使 URL 相同,GET 请求也不会被 POST URL 处理程序匹配。即使 URL 相同,操作也不同。

    因此,当您尝试 POST 到 /widgets/1/update 时看到 404 错误的原因是,您没有定义 POST 处理程序,而是定义了 PUT 处理程序

    不正确的 REST URL

    因为您可以对同一个 URL 执行多个操作,所以出现了一种标准。由于 URL 旨在引用资源,而不是操作,因此请尽量将操作词放在 URL 之外。

    例如。不要为/widgets/1/update 设置一个PUT 处理程序,只需为/widgets/1 执行一个PUT 处理程序。您正在更新的事实已经很明显,因为您正在执行 PUT 请求。

    以同样的方式,为 /widgets/1 而不是 /widgets/1/delete 创建一个 DELETE 处理程序。

    请记住,这不会与 /widgets/1 的 GET 或 DELETE 处理程序发生冲突,因为动词不同。

    POST 有点不同。代替 POST /widgets/add,使用 POST /widgets

    想象一下,如果你要表达你想做什么:

    小部件

    中创建记录

    POST/widgets

    “添加”或“创建”已经很明显了,因为它是一个 POST 请求。

    代码顺序

    这是一个小小的抱怨。在实际定义路由之前,您正在 .use()ing 路由器。这是因为 javascript 处理对象变量的方式,但它向后看。

    了解快递

    您的代码中的app 可以处理.post().get() 等。没有理由在您的代码中构造和使用路由器。

    express.Router() 用于当您想在部分 URL 上挂载一大堆路径或保持一组 URL 精神分离例如:

    var app = express()
    var apiRoutes = require("./api-router")
    var frontendRoutes = require("./frontend-router")
    
    app.use("/api", apiRoutes)
    app.use(frontendRoutes)
    

    【讨论】:

      猜你喜欢
      • 2014-12-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多