-1

When using the following code:

SERVER:

const cors = require('cors')
const mongoose = require('mongoose');
const Pet = mongoose.model('pets');

const corsOptions = {
origin: 'http://localhost:3000'}

app.get(`/api/pets`, cors(corsOptions), async (req, res) => {
    let pets = await Pet.find();
    return res.status(200).send(pets);
});

app.post(`/api/pets`, cors(corsOptions), async (req, res) => {
    let pet = await Pet.create(req.body);
    return res.status(201).send({
        error: false,
        pet
    })
})

CLIENT:

import axios from 'axios';

export default {
    getAll: async () => {
        let res = await axios.get(`http://localhost:5000/api/pets`);
        return res.data || [];
    },
    post: async (name, birthdate, decription) => {
    let res = await axios.post(`http://localhost:5000/api/pets`, {
        name: name,
        birthdate: birthdate,
        description: decription
    });
        return res;
    },
    ...
}

The client is able to access the .get route just fine, but when it tries to .post I get the following error:

"Access to XMLHttpRequest at 'http://localhost:5000/api/test' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource."

Picture of headers

However, this will allow the .post route to work just fine:

SERVER:

const cors = require('cors')
...

const corsOptions = {
origin: 'http://localhost:3000'}

app.use(cors(corsOptions));

app.get(`/api/pets`, async (req, res) => {
    ...
});

app.post(`/api/pets`, async (req, res) => {
    ...
})

What is the difference between the two approaches, and why does using "app.use(...)" allow the .post route to work but not the other?

Jefumaru
  • 1
  • 2
  • 1
    Chances are there is something in your POST request that is triggering a pre-flight request (an OPTIONS request) which you do not have a handler for. If you want us to help you with that, we would need to see exactly what the POST request is including content-type and custom headers. – jfriend00 Nov 21 '20 at 19:06
  • I've edited the post to include exactly what I have, and I've also added what's on the client side as well. "Pet" is a mongoose model – Jefumaru Nov 21 '20 at 20:02
  • Is there any specific reason you want to have CORS only on some URL but not others? – slebetman Nov 21 '20 at 20:08
  • Because I only want it to accept requests from that URL. I'm hoping to deploy this one day and I want at least some security on it – Jefumaru Nov 21 '20 at 20:11
  • We need to see the ENTIRE code for sending the request from the client OR the actual POST request (including all headers). As I said above, I suspect you have something in the POST request that triggers CORS preflight which you don't have a handler for. But, seeing just a shell of the code and no actual view of the request itself means we can't tell for sure. Certain content types or certain header on the request can trigger the preflight. FYI, if you look at the network tab in the Chrome debugger, you can see EXACTLY what is happening. We are all flying blind right now. – jfriend00 Nov 21 '20 at 20:14
  • I edited the post to add a picture of the headers I see from the network tab in the Chrome debugger. I've also added the rest of the post code from the client – Jefumaru Nov 21 '20 at 20:36

1 Answers1

0

You have to explicitly allow method post in your allowed http methods.

So your cors options should be something like:

const corsOptions = {
  "origin": "http://localhost:3000",
  "methods": "GET,POST", //here explicitly allowing http post method
  "preflightContinue": false,
  "optionsSuccessStatus": 204}

Here is the documentation for cors lib, you can just check more options.

Danizavtz
  • 3,166
  • 4
  • 24
  • 25