Alex Ironside
Alex Ironside

Reputation: 5039

Cross-Origin Request Blocked erroring out after adding application/json

I'm trying to send some data to Node using React. Here's my React code:

sendMail(e) {
    e.preventDefault();
    // fetch('/https://uczsieapp-mailer.herokuapp.com/', {
    var name = document.getElementById('name').value;
    var contactReason = document.getElementById('contactReason').value;
    var email = document.getElementById('email').value;
    var additionalInfo = document.getElementById('additionalInfo').value;
    var body = {
        name: name,
        contactReason: contactReason,
        email: email,
        additionalInfo: additionalInfo,
    };
    body = JSON.stringify(body);
    console.log(body);
    fetch('http://localhost:4000/', {
        method: 'POST',
        headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/json',
        },
        content: body,
    }).then(r => console.log(r)).catch(e => console.log(e));
}

Here's my Node code:

var cors = require('cors');
var app = express();
app.use(cors());
var a = '=';
router.post('/', (req, res, next) => {
        console.log('mailing');
        console.log(a);
        a += '=';
        var nodemailer = require('nodemailer');

        var transporter = nodemailer.createTransport({
            host: "smtp.gmail.com", // hostname
            auth: {
                user: '[email protected]',
                pass: 'testgmail'
            }
        });
        console.log(req.body.content);
        let mailOptions = {
            from: `${req.body.name} ${req.body.email}`, // sender address
            to: '[email protected]', // list of receivers
            subject: 'Email from UczSieApp contact form', // Subject line
            text: 'Hello world ', // plaintext body
            html: `
                    <h4>Imie: ${req.body.name}</h4>
                    <h4>Email: ${req.body.email}</h4>
                    <h4>Powod kontaktu: ${req.body.contactReason}</h4>
                    <p>Wiadomosc: ${req.body.additionalInfo}</p>
                    `
        };

        // send mail with defined transport object
        transporter.sendMail(mailOptions, function (error, info) {
            if (error) {
                return console.log(error);
            }

            console.log('Message sent: ' + info.response);
        });
    }
);

So as you can see I'm using the cors module, which is supposed to handle all the cors issues.

But that's not enough. When I get rid of the headers property passed to fetch(), the call is being done, but no data is being sent. When I add the headers, I get the fun

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:4000/. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).

error again.

How can I get around it and what am I missing?

I used this answer when writing my code: https://stackoverflow.com/a/42965820/7055769

Upvotes: 3

Views: 2533

Answers (3)

Alex Ironside
Alex Ironside

Reputation: 5039

Ok there were numerous reasons this didn't work. I'm leaving this answer for the future developers to ease their pain.

This is the method that worked on the client side:

$.ajax({
    type: "POST",
    url: 'http://localhost:4000/',
    data: body,
    success: data=>{console.log(data)},
    dataType: 'json',
});

Here's my whole server side code:

var express = require('express');
var router = express.Router();
var cors = require('cors');
var app = express();

app.use(cors());
app.options('*', cors());

var a = '=';
router.post('/', (req, res, next) => {
        console.log('mailing');
        console.log(a);
        a += '=';
        var nodemailer = require('nodemailer');

        var transporter = nodemailer.createTransport({
            host: "smtp.gmail.com", // hostname
            auth: {
                user: '[email protected]',
                pass: 'testgmail'
            }
        });
        console.log(req.body);
        let mailOptions = {
            from: `${req.body.name} ${req.body.email}`, // sender address
            to: '[email protected]', // list of receivers
            subject: 'Email from UczSieApp contact form', // Subject line
            text: 'Hello world ', // plaintext body
            html: `
                        <h4>Imie: ${req.body.name}</h4>
                        <h4>Email: ${req.body.email}</h4>
                        <h4>Powod kontaktu: ${req.body.contactReason}</h4>
                        <p>Wiadomosc: ${req.body.additionalInfo}</p>
                        `
        };

        // send mail with defined transport object
        transporter.sendMail(mailOptions, function (error, info) {
            if (error) {
                return console.log(error);
            }

            console.log('Message sent: ' + info.response);
        });
    }
);
module.exports = router;

So in my case I had to add these:

app.use(cors());
app.options('*', cors());

No idea why, but it just breaks without the app.options('*', cors()); parameter. If someone knows a better answer to this, and/or sees any security flaws please leave a comment and let me know. Thank you everybody once more for all the help!

Upvotes: 1

Joel Wembo
Joel Wembo

Reputation: 870

You mind trying this as follow, this should solve the problem :

app.use(function (req, res, next) {
    //set headers to allow cross origin requestt
    res.header("Access-Control-Allow-Origin", "*");
    res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS');
    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    next();
}); 

Upvotes: 1

Jeeva
Jeeva

Reputation: 1590

It turns out that CORS only allows some specific content types.

The only allowed values for the Content-Type header are:

  1. application/x-www-form-urlencoded
  2. multipart/form-data
  3. text/plain

The origin parameter specifies a URI that may access the resource. The browser must enforce this. For requests without credentials, the server may specify "*" as a wildcard, thereby allowing any origin to access the resource.

https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS

fetch('http://localhost:4000/', {
    method: 'POST',
    mode: 'cors',
    headers: {
        'Access-Control-Allow-Origin': '*',
        'Accept': 'application/json',
        'Content-Type': 'application/json',
    },
    content: body,
}).then(response => response.json()).then(r => console.log(r)).catch(e => console.log(e));

Upvotes: 4

Related Questions