node.js - Angular 到 Node + Express.js http.post() 停止:状态 204 无内容。疑似 CORS 预检选项
问题描述
我正在使用客户端 ionic 和服务器端 node.js + express.js。目前在我的本地计算机上进行测试。
我可以通过邮递员发出 POST 请求,但是我无法通过 ionic 发出请求。
研究
我花了将近1天的时间来调查这个。但我找不到解决这个问题的方法。此外,客户端和服务器端都没有错误,因此我很难对此进行调查。
据我所见,我怀疑错误来自 PREFLIGHT OPTIONS 设置。我应该将它设置在我的节点 + 快递中的某个地方。我正在使用 cors 插件https://www.npmjs.com/package/cors并使用设置来允许 PREFLIGHT OPTIONS,但它仍然无法正常工作。
我的客户端代码(离子)
postAPI() {
return new Promise ((resolve,reject)=>{
this.http.post("http://localhost:8080/api/status/", {
"body" : "This is the body post"
}, httpOptions).subscribe((val) => {
console.log("POST call successful value returned in body", val);
resolve();
}, error => {
console.log("POST call in error", error);
reject();
}, () => {
console.log("The POST observable is now completed.");
})
})
}
我的服务器端代码(Node + Express)
在这里,我使用 CORS OPTIONS 设置来允许所有 OPTIONS 请求。我在 server.js 中设置它,而路由本身在 status.js 中。
服务器.js
const express = require('express'); // call express
const app = express(); // define our app using express
var cors = require('cors'); // setup CORS so can be called by ionic local app
const port = process.env.PORT || 8080; // set our port
// ALLOW CORS
app.use(cors());
// SET CORS for PREFLIGHT OPTIONS
app.options('*', cors());
// Libraries
const bodyParser = require('body-parser');
const admin = require('firebase-admin');
const serviceAccount = require('./serviceAccountKey.json');
// Json
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
// Firebase Configs
//firebase admin sdk for Firestore
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://menuu-sm-dev.firebaseio.com"
});
var afs = admin.firestore();
var db = afs;
app.set("afs", afs);
var db = admin.firestore();
const settings = {timestampsInSnapshots: true};
db.settings(settings);
app.set("db", db);
// ROUTES
app.use('/api',require('./routers/api/api'));
app.use('/',require('./routers/home'));
// START
app.listen(port);
console.log('Server is served on port ' + port);
api.js
// SETUP
const express = require('express'),
router = express.Router();
const url = require("url");
const path = require("path");
///const sanitizer = require("sanitize")();
// ROUTES (/api/)
router.use('/user',require('./user'));
router.use('/status',require('./status'));
router.use('/timeline',require('./timeline'));
router.use('/photo',require('./photo'));
router.use('/like',require('./like'));
router.use('/comment',require('./comment'));
router.use('/checkin',require('./checkin'));
router.use('/promotion',require('./promotion'));
// OTHERS
module.exports = router;
状态.js
// SETUP
const express = require('express'),
router = express.Router();
const url = require("url");
const path = require("path");
const Timeline = require("../../models/Timeline");
const Post = require("../../models/Post");
///const sanitizer = require("sanitize")();
// ROUTES
// ===============================================================
// /status/
var statusRoute = router.route('');
// Create
statusRoute.post((req, res) => {
let query = url.parse(req.url,true).query;
let userKey = query.userkey;
let statusKey = query.statuskey; // ga dipake
let reqBody = req.body;
let db = req.app.get('db');
// ! remember to do sanitizing here later on
if (typeof userKey != 'undefined'){
// Create New Status
let newStatusRef = db.collection('status/'+userKey+'/status').doc();
newStatusRef.set(reqBody);
// Fan-Out
let docId = newStatusRef.id; // get pushed id
//let docId = "1";
// Insert request body to models
var post = new Post();
var timeline = new Timeline();
Object.entries(reqBody).forEach( ([key, value]) => {
timeline.set(key,value);
post.set(key,value);
}
);
// Specify operations to be done
var batch = db.batch();
let newPostRef = db.collection('posts/'+userKey+'/posts').doc(docId);
batch.set(newPostRef, post.data);
console.log("b" + batch);
// Timeline & Commit
getFollowers(userKey, db)
.catch((error) => {
console.error("Error writing document: ", error)
})
.then((followers) => {
// ATTENTION!!
// if followers > 9, batch write supposedly wont work because max limit of batch write is 10
if (followers.length!=0){
followers.forEach((f) => {
let newTimelineRef = db.collection('timeline/'+String(f)+'/timeline').doc(docId);
console.log(typeof batch);
console.log("a" + batch);
batch.set(newTimelineRef, timeline.data);
});
}
// Commit changes
batch.commit()
.then(() => {
console.log("POST Request");
res.json({"Action":"CREATE","Status":"Successful", "User key":userKey, "Post Key": docId, "followers":followers});
})
.catch((error) => {
console.error("Error writing document: ", error)
})
});
}
});
你能帮我找出这个问题的原因吗?谢谢!
解决方案
将 app.use('cors') 替换为以下代码:
app.use((req, res, next) => {
res.header("Access-Control-Allow-Origin", '*');
res.header(
"Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept, Authorization"
);
if (req.method === 'OPTIONS') {
res.header('Access-Control-Allow-Methods', 'PUT, POST, PATCH, DELETE, GET');
return res.status(200).json({});
}
next();
});
推荐阅读
- php - PHP HTML 联系表单中的验证码验证
- javascript - 为什么节点中产生的子进程甚至在执行之前就触发关闭事件?
- c++ - 在现代 C++ 中获取参数的最有效方法是什么?
- python - 如何通过运行 python 脚本在 Opencart 中添加产品?
- java - Java 8 in Action Streams 明确说明
- mysql - MySQL中生成列后面的表达式
- google-cast - 如何隐藏或更改下一个队列项目的倒计时外观?
- electron - 无法在 Windows 10 上使用 ffi 运行电子重建 (src\ffi.cc(228): error C2065: 'Handle': undeclared identifier)
- html - 根据组件值在角度组件之间画线的最佳做法是什么?
- excel - 如何在 VBA 中将 If 语句变成 For 循环