1

I have a problem with my API. When I use fetch from ReactJS to send un json to NodeJS server, The server crashes...

fetch call :

 const jso = JSON.stringify({
        username: this.state.username,
        password: this.state.password
      })
      fetch("URL/authentication", {
        method: 'POST',
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json'
        },
        body: jso,
      }).then(res => res.json()).then((result) => {
        this.setState({
          answer: result.answer
        })

      }, (error) => {
        this.setState({isLoaded: true, error});

      })
  }

Here is the back-end side

var express = require('express');
var app = express();
var cors = require('cors');
var bodyParser = require('body-parser')
var mysql = require("mysql");

//Enabeling all Access-Control-Allow-Origin
app.use(cors());
app.options('*', cors())

var port = process.env.PORT || 5000

app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

//omitted mysql connections details

app.post('/authentication', (req, res) **=> {
    email = req.body.username,
    password = req.body.password,
    matching = "false"
    var dbpassword

    sql = "SELECT password FROM users WHERE email = ?";
    db.query(sql, email, (err, result, fields) => {
        if(err) {
            console.error('error query: ' + err.stack)
            return;
        }
        dbpassword = result[0].password;

         if(dbpassword === password){
        matching = "true";
        console.log(dbpassword + " : " + password);
        } 
        res.send({answer: matching});

    });
})

app.listen(port, function(){
    console.log("app running");
})

The thing is that this makes my server (hosted on Heroku) crash everytime I do a request from the front-end...

However, when I try to remove the header part from teh front end, the server doesn't crash but doesn't return anything...

After looking at the logs, I found that, when fetch has the header part with 'Content-Type': 'application/json', it sends an OPTIONS request before the post request...

My question : How can I make this to work? I tried a post request from postman and it works so I know that my server / algorithm is not the problem. Also, the server for the back-end is Heroku

etiennnr
  • 305
  • 5
  • 12
  • Well, if your server is crashing, that is indeed a problem on your server. First debug the server and see why it's crashing. NO request sent to your server should cause it to crash. Once you understand why it's crashing, you can fix it so it does not crash and then decide if that's also how you can just make your request work via the server fix. – jfriend00 Oct 03 '18 at 00:48
  • When you add custom headers to a request and you're making a CORS request from a browser, then the browser will issue an OPTIONS request to "pre-flight" the CORS request. It's the browser's way of asking the server if this request will be OK or not. You can easily handle that OPTIONS request on the server. It works fine in Postman because Postman isn't a browser and doesn't have CORS safety in it so Postman doesn't do that. The fast that it works with Postman is not necessarily an indication that your server has everything it needs to handle requests from a browser. – jfriend00 Oct 03 '18 at 00:49

2 Answers2

1

Because you are enabling CORS in the express server, you need to modify your fetch call.
Add the parameter mode: cors

fetch("URL/authentication", {
    method: 'POST',
    mode: 'cors', // defaults to same-origin
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      username: this.state.username,
      password: this.state.password
    })
  })

For more information check the Fetch API docs
Note that if you were running this on localhost it would work fine, but because it is being hosted elsewhere it's causing an error.

Joseph Lee
  • 11
  • 3
  • thanks for that but it wasn't actually the error. I just forgot to handle the case when I don't receive any paramater... Like with options... – etiennnr Oct 03 '18 at 03:13
0

I forgot to handle when my front-end doesn't send any request...

This is maybe not perfect but it's working :

app.post('/authentication', (req, res) => {
    email = req.body.username,
    password = req.body.password,
    matching = "false"
    var dbpassword

    if(email!=""){

        sql = "SELECT password FROM users WHERE email = ?";
        db.query(sql, email, (err, result, fields) => {
            if(err) {
                console.error('error query: ' + err.stack)
                return;
            }
            if(result.length > 0){
                dbpassword = result[0].password;

                if(dbpassword === password){
                matching = "true";
                console.log(dbpassword + " : " + password);
                } 
            }

            res.send(JSON.stringify({answer: matching}));
        });
    }

    else res.send(JSON.stringify({answer: matching}));
})
etiennnr
  • 305
  • 5
  • 12