0

I am trying to do a crud with the mean stack, question that I do not understand because it does not add a task to me.

My app.js

const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const mongoose = require('mongoose');

const server = express();

// connect mongodb
mongoose.connect('mongodb://localhost:27017/myDb', { useNewUrlParser: true, useUnifiedTopology: true }).
    then(() => { console.log('DB is connected') },
        err => { console.log('Can not connect to the database' + err) });

// routes
const taskRoutes = require('./routes/task');

server.use((req, res, next) => {
    res.header("Access-Control-Allow-Origin", "http://localhost:3000");
    res.header("Access-Control-Allow-Credentials", "true");
    res.header(
        "Access-Control-Allow-Headers",
        "Origin, X-Requested-With, Content-Type, Accept"
    );
    res.header("Access-Control-Allow-Methods", "HEAD, GET, POST, OPTIONS, PUT, DELETE");
    next();
});


server.use('/task', taskRoutes);
server.get('/', (req, res) => {
    res.send("New Tasks");
});

server.use(bodyParser.json());
server.use(cors);


// server initialization
server.listen(3000, () => {
    console.log("________________________________________________________");
    console.log("||-->          Server running on port 3000         <--||");
    console.log("TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT");
});

My model:

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const Task = new Schema({
    name: {
        type: String
    },
}, {
    collection: 'task'
});

module.exports = mongoose.model('Task', Task);

My Route:

const server = require('express').Router();

const Task = require('../models/Task');

// add task
server.post('/add', (req, res) => {
    let task = new Task(req.body);
    task.create()
        .then(todo => {
            res.status(200).json({ 'status': 'success', 'mssg': 'task added successfully' });
        })
        .catch(err => {
            res.status(409).send({ 'status': 'failure', 'mssg': 'unable to save to database' });
        });
});

// get tasks
server.get('/', (req, res) => {
    Task.find((err, tasks) => {
        if (err) {
            res.status(400).send({ 'status': 'failure', 'mssg': 'Something went wrong' });
        }
        else {
            res.status(200).json({ 'status': 'success', 'tasks': tasks });
        }
    });
});

// edit task
server.get('/edit/:id', (req, res) => {
    let id = req.params.id;
    Task.findById(id, (err, task) => {
        if (err) {
            res.status(400).send({ 'status': 'failure', 'mssg': 'Something went wrong' });
        }
        else {
            res.status(200).json({ 'status': 'success', 'task': task });
        }
    });
});

// update task
server.put('/update/:id', (req, res) => {
    Task.findById(req.params.id, (err, task) => {
        if (!task) {
            res.status(400).send({ 'status': 'failure', 'mssg': 'Unable to find data' });
        } else {
            task.name = req.body.name;

            task.update().then(work => {
                res.status(200).json({ 'status': 'success', 'mssg': 'Update complete' });
            })
        }
    });
});

// delete task
server.delete('/delete/:id', (req, res) => {
    Task.destroy({ _id: req.params.id }, (err,) => {
        if (err) {
            res.status(400).send({ 'status': 'failure', 'mssg': 'Something went wrong' });
        }
        else {
            res.status(200).json({ 'status': 'success', 'mssg': 'Delete successfully' });
        }
    });
});

module.exports = server;

My add.component.ts

import { Component, OnInit } from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { TaskService } from '../task.service';

@Component({
  selector: 'app-add',
  templateUrl: './add.component.html',
  styleUrls: ['./add.component.css'],
})
export class AddComponent implements OnInit {
  response: any = {};
  angForm: FormGroup;
  constructor(private fb: FormBuilder, private tas: TaskService) {
    this.angForm = this.fb.group({
      name: ['', Validators.required],
    });
  }

  ngOnInit() {}

  addTask() {
    this.tas.addTask(this.angForm.value).subscribe((res) => {
      this.response = res;
      if (this.response.status == 'success') {
        this.tas.alert('Task added successfully!', 'success');
        this.angForm.reset();
      } else {
        this.tas.alert('Error saving task!', 'error');
      }
    });
  }
}

My add.component.html

<div class="card">
  <div class="card-body">
    <form [formGroup]="angForm" novalidate>
      <div class="form-group">
        <label class="col-md-4 title-add">Title</label>
        <input type="text" class="form-control" formControlName="name" #name />
      </div>
      <div *ngIf="angForm.controls['name'].invalid && angForm.controls['name'].touched" class="alert alert-danger">
        <div *ngIf="angForm.controls['name'].errors.required">
          Title is required.
        </div>
      </div>
      <div class="form-group">
        <button type="submit" (click)="addTask()" [disabled]="angForm.pristine || angForm.invalid"
          class="btn btn-primary">Add Task</button>
      </div>
    </form>
  </div>
</div>

When I click on the "add task" button of the add.component.html component, I get the following in browser console:

Access to XMLHttpRequest at 'http://localhost:3000/task/add' from origin 'http://localhost:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The 'Access-Control-Allow-Origin' header has a value 'http://localhost:3000' that is not equal to the supplied origin.
zone-evergreen.js:2845 POST http://localhost:3000/task/add net::ERR_FAILED
scheduleTask @ zone-evergreen.js:2845
scheduleTask @ zone-evergreen.js:385
onScheduleTask @ zone-evergreen.js:272
scheduleTask @ zone-evergreen.js:378
scheduleTask @ zone-evergreen.js:210
scheduleMacroTask @ zone-evergreen.js:233
scheduleMacroTaskWithCurrentZone @ zone-evergreen.js:1134
(anonymous) @ zone-evergreen.js:2878
proto.<computed> @ zone-evergreen.js:1449
(anonymous) @ http.js:1776
_trySubscribe @ Observable.js:42
subscribe @ Observable.js:28
innerSubscribe @ innerSubscribe.js:67
_innerSub @ mergeMap.js:57
_tryNext @ mergeMap.js:51
_next @ mergeMap.js:34
next @ Subscriber.js:49
(anonymous) @ subscribeToArray.js:3
_trySubscribe @ Observable.js:42
subscribe @ Observable.js:28
call @ mergeMap.js:19
subscribe @ Observable.js:23
call @ filter.js:13
subscribe @ Observable.js:23
call @ map.js:16
subscribe @ Observable.js:23
addTask @ add.component.ts:22
AddComponent_Template_button_click_10_listener @ add.component.html:14
executeListenerWithErrorHandling @ core.js:15214
wrapListenerIn_markDirtyAndPreventDefault @ core.js:15249
(anonymous) @ platform-browser.js:582
invokeTask @ zone-evergreen.js:399
onInvokeTask @ core.js:27474
invokeTask @ zone-evergreen.js:398
runTask @ zone-evergreen.js:167
invokeTask @ zone-evergreen.js:480
invokeTask @ zone-evergreen.js:1621
globalZoneAwareCallback @ zone-evergreen.js:1647
Show 8 more frames
core.js:4352 ERROR HttpErrorResponse {headers: HttpHeaders, status: 0, statusText: "Unknown Error", url: "http://localhost:3000/task/add", ok: false, …}

Thanks and sorry that the post became long.

R. Richards
  • 24,603
  • 10
  • 64
  • 64
  • Does this answer your question? [Receiving a CORS error when to my react app using fetch function](https://stackoverflow.com/questions/61899340/receiving-a-cors-error-when-to-my-react-app-using-fetch-function) – eol Oct 07 '20 at 12:23
  • Thanks for your comment, I have tried the same thing but it still does not work and the cors error persists. – Marcelo Del Valle Oct 07 '20 at 21:57

1 Answers1

0

Your cors-header setup is wrong. As your frontend is running on port 4200, you need to allow this origin. So instead of port localhost:3000, use:

res.header("Access-Control-Allow-Origin", "http://localhost:4200");

Also you need to fix your middleware setup and initialize the parsers before the request-handlers, as req.body will be undefined in the request handler with your current code:

server.use(bodyParser.json());
server.use(cors);

server.use((req, res, next) => {
  res.header("Access-Control-Allow-Origin", "http://localhost:3000");
  res.header("Access-Control-Allow-Credentials", "true");
  res.header(
    "Access-Control-Allow-Headers",
    "Origin, X-Requested-With, Content-Type, Accept"
  );
  res.header("Access-Control-Allow-Methods", "HEAD, GET, POST, OPTIONS, PUT, DELETE");
  next();
});


server.use('/task', taskRoutes);
server.get('/', (req, res) => {
    res.send("New Tasks");
});
eol
  • 23,236
  • 5
  • 46
  • 64
  • I get this error: HttpErrorResponse {headers: HttpHeaders, status: 500, statusText: "Internal Server Error", url: "http://localhost:3000/task/add", ok: false, …} POST http://localhost:3000/task/add 500 (Internal Server Error) – Marcelo Del Valle Oct 08 '20 at 21:07
  • This means that the cors issue is solved now and is actually a different issue. You need to fix your middleware setup as you need to access `req.body` inside your handler. I've updated my answer. – eol Oct 09 '20 at 05:44