[SOLVED] I can't get my cross-domain POST request to work

I am working on the voting app and trying to get the front-end and back-end to communicate with each other.

I am building the front-end with Angular 2 with systemJS, which is using localhost:3000
My backend runs on localhost:9000

I added this middleware to my backend:

app.use(function (req, res, next) {
  console.log('middleware working')
  res.setHeader('Access-Control-Allow-Origin', '*');
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
  res.setHeader('Access-Control-Allow-Headers', "Origin, X-Requested-With, Content-Type, Accept, x-auth");
  next();
});

Once I did that, I could get the login and create user functions to work. (POST /api/login and POST /api/users)

Now I am trying to create a survey (POST /api/surveys) and it’s not working. The main difference is that creating a survey requires authentification, so the POST request is sending a header: x-auth:token
I added x-auth to the Access-Control-Allow-Headers in the middleware. Still not working.

Here’s the front-end code doing the post request:

    saveSurvey(newSurvey: Survey, token):Observable<Survey>{
        let headers = new Headers({'Content-Type':'application/json', 'x-auth':token});
        let options = new RequestOptions({headers: headers});
        return this.http.post(apiUrl+'/surveys',JSON.stringify(newSurvey), options)
            .map((res:Response)=>res.json())
            .catch((error:any)=>Observable.throw(error.error || 'Server error'))
    }

I have included a console.log(token) and console.log(newSurvey) and both log the correct information.

and the backend code:

app.post('/api/surveys', authenticate, function(req,res){
  console.log('app.post surveys'); // not logging anything. There is also a console.log in the authenticate middleware and it's not logging either.
  var body = req.body;
  body._creator = req.user._id;
  var newSurvey = new Survey(body);
  console.log(newSurvey)
  newSurvey.save().then(function(survey){
    res.send(survey);
  }).catch(function(err){
    res.status(400).send(err)
  })
});

What am I missing??

Have you got this up on GitHub, or could you post the authenticate script?

The authenticate middleware:

var {User} = require ('./../models/user');

var authenticate = function(req,res,next) {
  console.log('authenticate')
  var token = req.header('x-auth');
  User.findByToken(token).then(function(user){
    if(!user){
      return Promise.reject('no user found');
    }
    req.user = user;
    req.token = token;
    next();
  }).catch(function(error){
    res.status(401).send(error);
  })

}

module.exports = {authenticate: authenticate};

I have used that middleware for other projects and it worked fine.

I tried and your code works for me.
What data are you sending?

It works in postman for me too. What doesn’t work is when I send the data from the form in the front-end.
The data looks like this:

{
'title':'title of survey',
'options':[{'text':'option 1','count':0},{'text':'option 2','count':0}]
}

So as I don’t know Angular, I wrote my own frontend.
I wasn’t getting any cors errors, only error I had was about not allowed header x-auth, which I solved by adding

res.setHeader('Access-Control-Allow-Headers', 'x-auth, content-type');

to other headers in backend server file.

I don’t have an answer, but I do know how to make debugging easier.

// user.service.js

UserService.prototype.createUser = function(newUser) {
//...
.catch(function(error) {
        return Rx_1.Observable.throw(error || 'Server error'); //change from error.error to just error
      });
// login.component.js
Login.prototype.onCreateUser = function(event, user, valid) {
//...
this.userService.createUser(newUser).subscribe(function(user) {
          _this.dashboard = true;
          _this.loggedIn = true;
        }, function(error) {
          console.log('there was an error: ', error); // Concatenate your message and the error object together
}

Now we’re talking

I might not get much more than this for you. I’m unfamiliar with your setup, and with this SystemJS in particular. It seems to be reverting my changes unpredictably. Hope this helps, though. It definitely appears to be a client side issue.

Also checkout Allow-Control-Allow-Origin Chrome extension.

Thanks everyone for your help!

I just fixed it. Turns out it was a mistake with my Angular 2 code. I forgot to add the .subscribe after the saveSurvey function.

It was supposed to look like this:

                this.surveyService.saveSurvey(newSurvey, this.token).subscribe(survey=>{
                    console.log('survey: '+survey)
                }, error =>{
                    console.log(error)
                })

I am finding that doing only front-end or doing only back-end is relatively easy, but the communication between the two is where I get my worst problems. A few weeks ago I was stuck for days on another POST request. Turns out I forgot the event.preventDefault() that time.

Hopefully some day I’ll run out of stupid mistakes to do and then I’ll be fine! :wink:

I totally get the difficulty of having a frontend speak to a backend!

My voting app uses a server rendered frontend, which feels like cheating when I compare it to yours!

I’m gonna have to learn this stuff a bit more I think :slight_smile: