我正在尝试使用node(w / npm)和express为web艺术类创建一个webapp。我们的想法是让网站的主体都是一种颜色,但是任何人都可以在Twilio号码上为网站发送十六进制代码/ CSS颜色,并且网站的颜色会立即变为该颜色值。
基本上它是如何工作的是服务器从http://example.com/message的Twilio接收POST请求,其中包含文本消息的正文。它将它写入〜/ app / .data / color.tmp中的临时文件,客户端使用jQuery .get()调用http://example.com/color来访问该文件,该文件返回
所以这就是问题所在:我得到了一个应用于glitch.me的应用程序版本,所以我知道这个代码可以工作,但是我在使用它在我的域上工作时遇到了很多麻烦。我安装了应用程序并可以使用npm启动它,它成功地向我显示了HTML页面,但Chrome devtools显示脚本在尝试访问/着色时正在接收403。此外,我的网站的新文本不会更改/.data/color.tmp中的颜色值。我认为这可能是一个权限问题,但我检查了它们,看起来很好。
这是index.html页面上的服务器文件和脚本:
应用/ server.js
var express = require('express');
var bodyParser = require('body-parser');
var fs = require('fs');
var app = express();
app.use(bodyParser.urlencoded({extended: false}));
var dataPath = '.data/color.tmp';
// set a new color (saves posted color to disk)
app.post("/message", function (request, response) {
var dataStr = JSON.stringify(request.body.Body);
fs.writeFile(dataPath, dataStr);
response.end();
});
// get the saved color (reading from disk)
app.get("/color", function (request, response) {
var dataStr = fs.readFileSync(dataPath).toString();
response.send(JSON.parse(dataStr));
});
app.get("/", function (request, response) {
response.sendFile(__dirname + '/views/index.html');
});
var listener = app.listen(process.env.PORT, function () {
console.log('listening on port ' + listener.address().port);
});
应用/视图/ index.html中
<script>
// checks server for color value and sets background
function checkForColorChange() {
$.get('/color', function getColorComplete(data) {
document.body.style.backgroundColor = data;
console.log(data);
})
}
// Poll the server at 2000ms interval
setInterval(checkForColorChange, 2000);
checkForColorChange();
</script>
无论如何,我觉得我必须错过一些非常明显的东西,如果它在Glitch上如此容易,而且不会在我的网站上,但我已经被困了几天而且没有取得任何进展!任何帮助都会非常感激。如果有什么不清楚,请告诉我。
答案 0 :(得分:1)
(有关工作示例,请参阅下面的更新)
您的代码几乎没有问题:
path.join
来加入路径您现在遇到的主要问题很可能是文件权限。好消息是,您不需要任何文件访问权限,因此无论如何使用文件都不是最佳选择。你需要的只是将颜色存储在一个变量中,如果你不需要它,它会在服务器重启之间持续存在 - 即使你这样做,我也会使用一个简单的数据库。
例如:
// some initial value:
var color = '#ffffff';
app.post("/message", function (request, response) {
var color = request.body.Body;
response.end();
});
// get the saved color (reading from disk)
app.get("/color", function (request, response) {
response.send(color);
});
app.get("/", function (request, response) {
response.sendFile(__dirname + '/views/index.html');
});
var listener = app.listen(process.env.PORT, function () {
console.log('listening on port ' + listener.address().port);
});
这是我将使用的第一个更改 - 不依赖于文件系统,权限,竞争条件等。
您的代码遇到的另一个问题是在请求处理程序中使用阻塞函数。除了事件循环的第一个刻度之外,你不应该使用任何阻塞函数(名称中带有“Sync”的函数)。
我要做的另一项改进是使用WebSocket或Socket.io而不是定期轮询数据。这很容易编码。请参阅此答案以获取示例:
这样做的一个好处是,所有学生都会立即同时改变颜色,而不是在2秒内的随机时刻。
我写了一个我上面描述的例子。
POST端点略有不同 - 它使用/color
路由和color=#abcdef
而不是/message
和Body=...
,但您可以根据需要轻松更改 - 请参阅下文。
服务器代码 - server.js:
// requires removed for brevity
const app = express();
const server = http.Server(app);
const io = socket(server);
let color = '#ffffff';
app.use(bodyParser.urlencoded({ extended: false }));
app.use('/', express.static(path.join(__dirname, 'html')));
io.on('connection', (s) => {
console.log('Socket.io client connected');
s.emit('color', color);
});
app.post('/color', (req, res) => {
color = req.body.color;
console.log('Changing color to', color);
io.emit('color', color);
res.send({ color });
});
server.listen(3338, () => console.log('Listening on 3338'));
HTML页面 - index.html:
<!doctype html>
<html lang=en>
<head>
<meta charset=utf-8>
<meta name=viewport content="width=device-width, initial-scale=1">
<title>Node Live Color</title>
<link href="/style.css" rel=stylesheet>
</head>
<body>
<h1>Node Live Color</h1>
<script src="/socket.io/socket.io.js"></script>
<script src="/script.js"></script>
</body>
</html>
样式表 - style.css:
body {
transition: background-color 2s ease;
background-color: #fff;
}
客户端JavaScript - script.js:
var s = io();
s.on('color', function (color) {
document.body.style.backgroundColor = color;
});
特别有趣的是客户端代码有多简单。
对于您的原始端点,请在server.js中使用它:
app.post('/message', (req, res) => {
color = req.body.Body;
console.log('Changing color to', color);
io.emit('color', color);
res.end();
});
GitHub上提供了完整示例:
我在本地和Heroku上测试过它。您可以单击此按钮将其部署在Heroku上并自行测试:
享受。
答案 1 :(得分:0)
我认为,问题出在var dataStr = fs.readFileSync(dataPath).toString();
。请按以下方式更改dataPath
:
var dataPath = __dirname + '/data/color.tmp';
并确保该文件具有读取/写入权限。