【问题标题】:Pass a value from frontend to backend without using url在不使用 url 的情况下将值从前端传递到后端
【发布时间】:2018-02-11 23:06:33
【问题描述】:

我有一个平均堆栈应用程序。在后台,我有api.js:

var express = require('express')
var router = express.Router();

var body = 'response.send("hello fixed")';
var F = new Function ("request", "response", body);    
router.get('/api/special', F);

module.exports = router;

因此,https://localhost:3000/api/special 在浏览器中返回 hello fixed

现在,我想让前端定义body的内容。例如,我可以在网页中创建一个文本区域,用户可以随意输入例如response.send("hello flexible")。然后,我需要将此内容传递给 nodejs,以便 https://localhost:3000/api/special 现在返回 hello flexible

有谁知道如何做到这一点?

编辑1:根据李安的评论,我修改了api.js

var express = require('express')
var router = express.Router();

router.put('/endpoint', function (req, res, next) {
    console.log("api.js router.put /endpoint");
    router.get('/api/special', eval('(' + req.body.value + ')'))
})

module.exports = router;

在控制器中:

app.controller('EndpointCtrl', ['$scope', '$http', function ($scope, $http) {
    $scope.body = 'function (request, response) { response.send("Hello") }';    
    $scope.changeBody = function (body) {
        return $http.put('/endpoint', { value: body })
    }
}])

奇怪的是,它只在我第一次put /endpoint 时起作用,而后来put 似乎没有更新/api/special。有谁知道为什么?

另外,在后端的控制台中看到第二个或第三个put /endpoint需要几秒钟,这是有线的。

【问题讨论】:

  • 你为什么希望前端的人这样修改你的后端?巨大的传入安全漏洞。
  • 有时,制作像here这样灵活的api很有用。
  • 但是 RunKit 做了一些过滤和清理。您也必须实现这一点,以防止人们将您的应用用作攻击媒介。
  • 嗯,我会的……但首先,我需要知道他们是如何做到这一点的……
  • 你可以设置一个端点来接收像/api/create_endpoint/这样的函数体,然后POST到那个URL来创建一个带有输入值的新端点。

标签: javascript node.js api express routes


【解决方案1】:

为了扩展我的评论,这里有一个与您的示例相同的解决方案,但使用的是调用变量的中间件。

const express = require( "express" );
const app = express();

function rawBody( req, res, next ) {

    req.setEncoding( "utf8" );
    req.body = "";
    req.on( "data", chunk => req.body += chunk );
    req.on( "end", next );

}

app.use( rawBody );

const router = express.Router();

// f is our variable; we initialize it to just call next, likely resulting in a 404
let f = ( req, res, next ) => next();

// use an intermediary function to invoke f
// don't use just f, which is passed by value and wouldn't update
router.get( "/api/special", ( ...args ) => f( ...args ) );

router.put( "/endpoint", ( req, res ) => {

    // update f
    f = eval( "(" + req.body + ")" );

    // send a response; otherwise the request will hang
    res.sendStatus( 200 );

} );

app.use( router );

app.listen( 3000 );

spread operator (...) 有两种工作方式:将函数参数收集到数组中或将数组扩展为参数。这是 Node LTS 或更高版本的有效语法。您也可以显式使用( req, res )

我必须强调这样一个端点是非常脆弱的,因为它可以使用 require,它可以从它做任何进程有权做的事情(例如下载和安装软件)。 vm2 是一个 npm 模块,可能会有所帮助,但它们并不能提供实际的安全保证。我建议您在沙箱中执行代码,并且只授予该沙箱有限的权限(例如不能访问文件系统或网络)。

【讨论】:

  • 非常感谢...现在,我打开https://localhost:3000/endpoint并输入function (request, response) { response.send("Hallo") },然后在另一个选项卡中打开https://localhost:3000/api/special,我希望看到Hallo,但我看不到它.我在router.get( "/api/special"...里面加了console.log(f.toString()),说明f没有更新。
  • 我的示例使用req.body,而您的示例使用req.body.value。你能验证你使用的那个是你传入的字符串吗?
  • 现在我也使用req.body,确实是我传入的任何内容。
  • 我能想到的唯一其他问题是put /endpoint 中更新的fget /api/special 中使用的f 不同。两条路线(和f)是否在同一个文件中声明?我更新了我的示例,以包含我在 Chrome、FF、IE11 和 Edge 中测试的整个示例文件。
  • 是的,路由和f 都在同一个文件中……我才意识到f = eval( "(" + req.body + ")" ); 不起作用,因为之后的所有命令都不会执行。看来它需要一些特殊的标题...
猜你喜欢
  • 2012-11-12
  • 2021-08-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多