Reputation: 531
I have an annoying problem. I am trying to build a simple website. That website uses an api i build using nodejs and express. While developing the API, i constantly checked functionality with Postman. Everything worked and still works fine (using Postman).
Now I started working on my Website. The first GETs and POSTs worked ok. (I tried some lightweight ajax libs, none worked, only jQuery seems to work for me)
Now I am trying to update a item using the PUT Verb. Again updating works fine using postman. But trying to use jQuery doesn't trigger the right route in express. To check that, I added a simple console.log if express used the last middleware which is also returning a 404 statuscode
and one console.log in the function that handles the PUT. Everytime I use jQuery to update an element it goes to 404. If I use Postman I see the message from the PUT function.
My APIController (NodeJS with Express):
let express = require('express');
//let path = require('path');
let bodyParser = require('body-parser');
let mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/test', { useMongoClient: true });
require('./Models/InitModels');
let app = express();
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true}));
let routes = require('./Routes/APIRoutes');
routes(app);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
res.status(404);
console.log("Returning 404 to request");
});
app.set('port', 2017);
app.listen(2017);
console.log("Starting API Controller");
API Routes (only Karte is important here):
module.exports = function(app) {
let benutzer = require('../Controller/BenutzerController');
let gruppe = require('../Controller/GruppenController');
let zugriffslog = require('../Controller/ZugriffsLogController');
let karten = require('../Controller/KartenController');
let zugriffszeit = require('../Controller/ZugriffsZeitenController');
app.route('/karten')
.put(karten.put)
.post(karten.post)
.delete(karten.delete);
And then the KartenController:
exports.post = (req, res) => {
if (req.body.search) {
Karte.find(req.body.search)
.populate('benutzer').populate('gruppen')
.exec((err, karten) => {
res.json(karten)
});
} else if(req.body.karte) {
if (this.createdKarte !== null) {
res.json({"error": {"code": 110}}); // card needs to be scanned
} else {
let newKarte = new Karte(req.body.karte);
newKarte.save();
//this.createdKartenDatum = new Date();
res.json(newKarte);
// Add Karte To User
//Benutzer.findOneAndUpdate({_id: newKarte.benutzer}, {$push: {karten: newKarte._id}});
//Benutzer.findOneAndUpdate({_id: newKarte.benutzer}, {$pull: {karten: newKarten._id}});
this.kartenCreateDatum = new Date();
this.createdKarte = newKarte;
this.kartenScannPending = true;
// Abort after some time
setTimeout(scannTimeExpired, timeTillCreationExpires);
}
} else if(req.body.status) {
if (this.kartenScannPending) {
res.json({"status": {"code": 300}}); // waiting for card to be scanned
} else if (this.kartenScannFehler !== null) {
res.json(this.kartenScannFehler); // fehler aufgetreten
this.kartenScannFehler = null; // aufräumen
} else if (this.kartenScannErfolgreich) {
res.json({"status": {"code": 500, "date": this.kartenCreateDatum}}); // karte gescanned
this.kartenScannErfolgreich = false;
} else {
res.json({"status": {"code": 404}}); // no card needs to be scanned
}
} else {
res.json({ "error": "U SUCK" });
}
};
exports.put = (req, res) => {
console.log("Trying to put a Card)");
if (req.body.karte) {
if (req.body.karte.name && req.body.karte._id) {
Karte.findOneAndUpdate({_id: req.body.karte._id}, {$set: req.body.karte}, {new: true},(err, karte) => res.json(karte));
} else {
res.json({"error": {"code": 120}});
}
} else {
res.json({"error": {"code": 120}});
}
};
My Javascript looks like this:
$.ajax({
type: "POST",
context: this,
url: "http://localhost:2017/karten",
data: {
search: {
benutzer: {
_id: this.benutzer._id
}
}
},
async: true,
success: function (data) {
console.log(data);
},
dataType: "json"
});
// Zugriffszeiten abfragen
$.ajax({
type: "PUT",
context: this,
url: "http://localhost:2017/karten",
data: {
karte: {
_id: this.karte._id,
name: "PLS WORK !!!"
}
},
async: true,
success: function (data) {
console.log(data);
},
dataType: "json"
});
The result:
First one:
is working and giving me an array of two cards
Second one:
getting me an ERR::EMPTY_RESPONSE (because of the 404) and the nodejs console outputs "Returning 404 to request"
Trying the same with Postman, everything works and the cards get updated
I realy hope somone can help me with that, as I am working on this quite a long time now and cant seem to see my mistake.
Thanks for reading everything :)
Upvotes: 1
Views: 157
Reputation: 531
Thanks to jfriend00, I found the solution to the problem. I didnt respont to the options-request properly. I had to add some lines of code to my APIController:
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
// The routes wont fire on that options-request, so it sends a 404 response and thus the ajax request times out
//intercepts OPTIONS method
if ('OPTIONS' === req.method) {
//respond with 200
console.log("Received options request");
res.send(200);
}
else {
//move on
next();
}
});
Now everything works as expected.
Upvotes: 1