'Express API works with curl but not in browser

enter image description here I followed this tutorial https://www.positronx.io/angular-8-mean-stack-tutorial-build-crud-angular-material/ to create a MEAN app

My express API works via curl and data successfully populates the mongo database. My angular front end also works in a live browser using nginx as the server. I am also able to proxy_pass to use express to serve the angular STATIC files directly.

When I try to POST data into a form from the browser I get an error saying ERR_CONNECTION_REFUSED. I have been stuck on this for a few days and not sure how I can resolve this. I suspect the issue is with my nginx file or /sites-available/default file, given that curl works in the command line.

My key files are:

/etc/nginx/sites-available/default:

server {
    listen 80 default_server;
    listen [::]:80 default_server;

    server_name _;

location / {
    proxy_pass http://localhost:3000;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection 'upgrade';
    proxy_set_header Host $host;
    proxy_cache_bypass $http_upgrade;
    }
}

app.js (for express):

let express = require('express'),
  path = require('path'),
  mongoose = require('mongoose'),
  cors = require('cors'),
  bodyParser = require('body-parser'),
  dataBaseConfig = require('./database/db');

// Connecting mongoDB
mongoose.Promise = global.Promise;
mongoose.connect(dataBaseConfig.db, {
  useNewUrlParser: true,
  useFindAndModify: false
}).then(() => {
    console.log('Database connected sucessfully ')
  },
  error => {
    console.log('Could not connected to database : ' + error)
  }
);

// Set up express js port
const studentRoute = require('./routes/student.route');

const app = express();
app.use(bodyParser.urlencoded({
  extended: false
}));

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

// Setting up static directory
 app.use(express.static('../dist/meanstack'));


// RESTful API root
app.use('/api', studentRoute);

// PORT
const port = process.env.PORT || 3000;

app.listen(port, () => {
  console.log('Connected to port ' + port);
})

// Find 404 and hand over to error handler
app.use((req, res, next) => {
  next(createError(404));
});

// Index Route
app.get('/', (req, res) => {
  res.send('invaild endpoint');
});

app.get('*', (req, res) => {
  res.sendFile('../dist/meanstack/index.html');
});

//error handler
 app.use(function (err, req, res, next) {
  console.error(err.message);
  if (!err.statusCode) err.statusCode = 500;
  res.status(err.statusCode).send(err.message);
 });

And the angular api.service file that connects the backend and front end:

import { Injectable } from '@angular/core';
import { Student } from './student';
import { Observable, throwError } from 'rxjs';
import { catchError, map } from 'rxjs/operators';
import { HttpClient, HttpHeaders, HttpErrorResponse } from '@angular/common/http';

@Injectable({
  providedIn: 'root'
})

export class ApiService {

  endpoint: string = 'http://localhost:3000/api';
  headers = new HttpHeaders().set('Content-Type', 'application/json');

  constructor(private http: HttpClient) { }

  // Add student
  AddStudent(data: Student): Observable<any> {
    let API_URL = `${this.endpoint}/add-student`;
    return this.http.post(API_URL, data)
      .pipe(
        catchError(this.errorMgmt)
      )
  }

  // Get all students
  GetStudents() {
    return this.http.get(`${this.endpoint}`);
  }

  // Get student
  GetStudent(id): Observable<any> {
    let API_URL = `${this.endpoint}/read-student/${id}`;
    return this.http.get(API_URL, { headers: this.headers })
      .pipe(
        map((res: Response) => {
          return res || {}
        }),
        catchError(this.errorMgmt)
      )
  }

  // Update student
  UpdateStudent(id, data): Observable<any> {
    let API_URL = `${this.endpoint}/update-student/${id}`;
    return this.http.put(API_URL, data, { headers: this.headers })
      .pipe(
        catchError(this.errorMgmt)
      )
  }

  // Delete student
  DeleteStudent(id): Observable<any> {
    var API_URL = `${this.endpoint}/delete-student/${id}`;
    return this.http.delete(API_URL)
      .pipe(
        catchError(this.errorMgmt)
      )
  }

  // Error handling 
  errorMgmt(error: HttpErrorResponse) {
    let errorMessage = '';
    if (error.error instanceof ErrorEvent) {
      // Get client-side error
      errorMessage = error.error.message;
    } else {
      // Get server-side error
      errorMessage = `Error Code: ${error.status}\nMessage: ${error.message}`;
    }
    console.log(errorMessage);
    return throwError(errorMessage);
  }

}

I am adding ./routes/student.route.js

const express = require('express');
const app = express();
const studentRoute = express.Router();

// Student model
let Student = require('../database/model/Student');

// Add Student
studentRoute.route('/add-student').post((req, res, next) => {
  Student.create(req.body, (error, data) => {
    if (error) {
      return next(error)
    } else {
      res.json(data)
    }
  })
});

// Get all student
studentRoute.route('/').get((req, res) => {
  Student.find((error, data) => {
    if (error) {
      return next(error)
    } else {
      res.json(data)
    }
  })
})

// Get single student
studentRoute.route('/read-student/:id').get((req, res) => {
  Student.findById(req.params.id, (error, data) => {
    if (error) {
      return next(error)
    } else {
      res.json(data)
    }
  })
})


// Update student
studentRoute.route('/update-student/:id').put((req, res, next) => {
  Student.findByIdAndUpdate(req.params.id, {
    $set: req.body
  }, (error, data) => {
    if (error) {
      return next(error);
      console.log(error)
    } else {
      res.json(data)
      console.log('Student successfully updated!')
    }
  })
})

// Delete student
studentRoute.route('/delete-student/:id').delete((req, res, next) => {
  Student.findByIdAndRemove(req.params.id, (error, data) => {
    if (error) {
      return next(error);
    } else {
      res.status(200).json({
        msg: data
      })
    }
  })
})

module.exports = studentRoute;

I welcome any tips as this is the final step before I am able to make my first MEAN app tutorial go live. Please let me know if you need any clarifications. Thank you.

EDIT 1: I have added the ./routes/student.route.js file. After more reading I am wondering if the issue might be cors related.

EDIT 2: I added a screengrab of curl output from the terminal

EDIT 3: I have tried nginx cors as described here https://enable-cors.org/server_nginx.html with and without proxy_pass to express and that has not resolved this issue either



Solution 1:[1]

This has now been solved. The issue was with the api.service file in angular

 endpoint: string = 'http://localhost:3000/api';

Here localhost:3000 should be replaced with the domain name

 endpoint: string = 'http://www.example.com/api';

Solution 2:[2]

In my case, I was running express server in port 3000 locally, was able to get response from the '/' endpoint with curl and not browser. Then I noticed that the route works perfectly fine in chrome browser. I had to clear edge browser data and it worked

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Zakoff
Solution 2 Rishi Rishi