Lukas
Lukas

Reputation: 531

Express not routing some jQuery requests

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

Answers (1)

Lukas
Lukas

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

Related Questions