Search code examples
node.jsexpresshttp-deletehttp-put

PUT and DELETE methods not called in NodeJS Express Angular 2 app


I have this app with Express backend:

server.js:

var express = require('express');
var methodOverride = require('method-override')
var app = express();
var bodyParser = require('body-parser');
var cors = require('cors');
var mysql = require('mysql');
...
app.use(methodOverride('X-HTTP-Method-Override'))
app.use(bodyParser.json());
app.use(cors());
...
app.route('/api/lessons').get((req, res) => {
    con.query('SELECT * FROM lesson', (err, rows) => {
        if (err)
            res.send(JSON.stringify({ "status": 500, "error": err, "response": null }));
        else
            res.send(JSON.stringify({ "status": 200, "error": null, "response": rows }));
    });
});
...
app.route('/api/lessons/:lessonId').put(function (req, res) {
    console.log("Backend PUT");
    var lessonId = req.param('lessonId');
    con.query('UPDATE lesson SET title=?, body=?, level_id=? WHERE id=?', [req.body.title, req.body.body, req.body.level_id, lessonId], (err, rows) => {
        if (err)
            res.send(JSON.stringify({ "status": 500, "error": err, "response": null }));
        else
            res.send(JSON.stringify({ "status": 200, "error": null, "response": rows }));
    });
});
...
app.route('/api/lessons/:lessonId').delete((req, res) => {
    console.log("Backend DELETE");
    var lessonId = req.param('lessonId');
    con.query('DELETE FROM lesson WHERE id=?', [lessonId], (err, rows) => {
        if (err)
            res.send(JSON.stringify({ "status": 500, "error": err, "response": null }));
        else
            res.send(JSON.stringify({ "status": 200, "error": null, "response": rows }));
    });
});

Angular service:

import { Injectable } from '@angular/core';
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor, HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { Configuration } from '../../app.constants';

@Injectable()
export class LessonService {
  private restUrl: string;
  constructor(private http: HttpClient) {
    this.restUrl = 'http://localhost:8000/api/lessons/';
  }

  public getAll() {
    return this.http.get(this.restUrl);
  }

  public getOne(id: number) {
    return this.http.get(this.restUrl + id);
  }

  public getAllForLevel(id: number) {
    return this.http.get('http://localhost:8000/api/lessons-for-level/' + id);
  }
...
  public update(id: number, level: any) {
    console.log(this.restUrl+id);
    return this.http.put(this.restUrl + id, level);
  }

  public delete(id: number) {
    console.log("DELETE: " + this.restUrl + id);
    return this.http.delete(this.restUrl + id);
  }
...
}

All the GET methods are working correctly, but not the PUT or the DELETE method. With console.log's I concluded that the service methods update and delete are getting called from the frontend, but the REST endpoints (in server.js) are never called. There are no error messages at all.

What could be the problem?

Edits: Besides the PUT method, the DELETE is also not getting called. I've edited the title and the question. Also I've added console.logs in the update and delete methods so I can check what URL is being called, and it is http://localhost:8000/api/lessons/2 (for example), so it's correct. I've tried calling that URL via Postman both for PUT and DELETE and it works correctly, it changed or deleted the relevant entry in the DB. So as it looks to me, the only problem is the lack of communication between frontend and backend.


Solution

  • I've found the solution.

    tl;dr:
    I didn't put the .subscribe in the place where I call the update method.

    Long version:
    When I call various get methods from my service, I do it like this:

    this.lessonService.getAllForLevel(this.levelId).subscribe(data => this.lessons = data['response']);
    

    However, I thought that I can call my update method like this:

    this.lessonService.update(this.lessonId, this.lesson);
    

    ...because I thought there was nothing interesting that I should subscribe to.

    However, when I changed the call to this:

    this.lessonService.update(this.lessonId, this.lesson).subscribe(data => console.dir(data));
    

    ...it worked correctly (don't mind the console.dir part, I just wanted to put something in the subscribe part so it would work).