0

I'm using Angular 7 to send a http request to an Express 4 backend code, but keep getting a 404 response in return. I think it might be an issue with the way I've listed the path for the http request, but not sure. This is the first time I'm attempting something like this. I have set up a proxy.conf.js file in Angular to allow from cross origin communication (angular runs on localhost:4200, express on localhost:8085). My Express code is saved under C:/ABC/myapp. Here's the relevant code:

Angular proxy.conf.js file:

{
  "/": {
    "target": "http://localhost:8085",
    "secure": false,
    "logLevel": "debug"
  }
}

Angular service code which sends the http request:

export class ContactUsService {
private url = '/contactus';
private result: any;
message: string;

addMessage(contactUsMessage: contactUsInterface): Observable<contactUsInterface> {
  return this.http.post<contactUsInterface>(this.url, contactUsMessage). (retry(3));
};

constructor(private http: HttpClient) {}
};

Express app.js code:

var bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');
var createError = require('http-errors');
var express = require('express');
var logger = require('morgan');
var mongoose = require('mongoose');
var path = require('path');
var winston = require('winston');
var contactUsRouter = require(path.join(__dirname, 'routes', 'contactUs'));
var app = express();

app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/contactus', contactUsRouter);

app.use(function(req, res, next) {
  next(createError(404));
});
app.use(function(err, req, res, next) {
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;

contactUs.js code (for contactUsRouter):

var express = require('express');
var router = express.Router();
var contactUsMessage = require('../models/contactUsMessage');

  router.route('/contactus')
    .get(function(req,res,next){
      res.send("Hello")
    })
    .put(function(req,res,next){
      res.send("Hello")
    });

module.exports = router;

When I reach the contactus page (url: localhost:4200/contactus) and execute the submit button for the form, I get the following errors: In the browser console: "HTTP404: NOT FOUND - The server has not found anything matching the requested URI (Uniform Resource Identifier). (XHR)POST - http://localhost:4200/contactus"

In the npm log: "POST /contactus 404 3.081 ms - 2128 Error: Failed to lookup view "error" in views directory "C:\ABC\myapp\views".

Any words of wisdom on what I'm doing incorrectly?

3
  • 1
    It seems that you have not defined the POST method in contactUs.js Commented May 7, 2019 at 19:46
  • ARe you able to hit the Api with a Rest tool like Postman ? Commented May 7, 2019 at 19:47
  • Currently you have a POST route exposed at /contactus/contactus. This is because the base route of /contactus is specified via app.use('/contactus', contactUsRouter);. Then you define the POST with /contactus again. Commented May 7, 2019 at 19:58

2 Answers 2

1

Currently you are exposing a route of POST /contactus/contactus because you are specifying a base route with the statement app.use('/contactus', contactUsRouter);, then adding/appending an additional/extra /contactus with the registration of the POST/PUT routes.

Try change the POST route to path to just '/':

var express = require('express');
var router = express.Router();
var contactUsMessage = require('../models/contactUsMessage');

  router.route('/')
    .get(function(req,res,next){
      res.send("Hello")
    })
    .post(function(req,res,next){
      res.send("Hello")
    });

module.exports = router;

Hopefully that helps!

Sign up to request clarification or add additional context in comments.

8 Comments

Oops, I meant to write "post" instead of "put". That seems to have resolved at least the error I inquired about. Now I get this error in the npm log: "GET /contactus 500". And the browser console gives this error: "HTTP500: SERVER ERROR - The server encountered an unexpected condition that prevented it from fulfilling the request. GET - localhost:4200/contactus". Also, does the router.route act upon the get request even though the angular app isn't making a get request? Node log shows: "[HPM] GET /contactus -> localhost:8085" when I first retrieve website.com/contactus.
Navigating to website.com/contactus, even without any HttpClient.get(), will trigger the express GET /contactus to trigger. As mentioned in another answer, it may be advisable to put API routes under some kind of base/prefix such as /api/ to avoid creating conflicts like this.
can you please elaborate on this point? How does using /api/ avoid such a conflict? And to do so, do I then have to change all the paths in angular app to include "/api/" so that the url passed to the http request is something like "/api/contactus"?
Yes, you would update all REST API routes in your express application to use the /api prefix and update all requests in Angular to use the /api prefix for any HttpClient requests as well. Usually you would add catch-all logic to express to load (sendFile()) your Angular's index.html anytime none of the API endpoints were not hit/matched.
Thanks. What is it about "/api" that avoids these types of conflicts? And I'm presuming this catch-all logic with sendFile() would be in the error handler in app.js or would I have to include it in every single router code in the express app?
|
1

Your proxy conf file is not working properly.

The requests are still trying to look for a POST method route /contactus in angular application running on port 4200 ((XHR)POST - http://localhost:4200/contactus) which does not exist and hence you are getting a 404.

Make sure you have followed the steps mentioned on official angular website - Add Proxy for backend server - angular.io

It will be advisable if you use proxy path /api instead of / . Something like this

{
  "/api": {
    "target": "http://localhost:8085",
    "secure": false
  }
}

Hope it helps

2 Comments

Actually, that's one thing I've struggled to understand. Why use "/api" in the proxy.conf file when there's no "/api" in the url?
The only purpose is from a perspective where you might want to send request to another backend server. If you have another backend server at port 8086 you might want to send some request to that server and some of them to port 8085. Having a /api kind of identifier might help to distinguish to handle such scenarios.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.