Search code examples
node.jsexpresscorsnetlify

How to stop CORS from blocking connections to my node netlify server?


I created a react client app that request images from a node.js server app (V23.4.0), also created by me. It works fine locally but when I upload the server to netlify, each request made is blocked by the CORS policy.

CORS response

I created simplified versions of both apps and start testing different solutions from this site.

App.jsx (client)

function App() {

    useEffect(() => {
        getServerResponse();
    });

    const getServerResponse = () => {
        axios.get("https://chambaserver.netlify.app/.netlify/functions/app:4000/test-response",
            {
                params: {
                    mytext: "Alexis response"
                }
            })
            .then(response => {
                if (response.status = 200) {
                    console.log(response.data);
                }
            })
            .catch((err) => {
                alert("GET ERROR: " + err);
            });
    }

    return (
        <div className="App" />
    );
}

app.js (server)

const express = require('express');
const serverless = require("serverless-http");
const cors = require("cors");
const app = express();
const router = express.Router();

app.use("/.chambaserver/functions/app", router);
module.exports.handler = serverless(app);

app.use(express.static(__dirname + '../..'));

//Local client site (App.jsx)
const corsOrigin = 'http://localhost:5173';

//Use CORS package
app.use(cors({
    origin: [corsOrigin],
    methods: ['GET', 'POST'],
    credentials: true
}));

app.get('/test-response', (req, res) => {
    let myText = req.query.mytext;
    console.log(myText);
    return res.send("This is your message: " + myText);
});

//Start in port 4000
const port = 4000;
app.listen(port, process.env.IP, function () {
    console.log(`Server is running on port ${port}`);
});

I already tried:

  1. Using cors npm package (as you can see in code). I tried write it with and without options (just "app.use(cors())"), but the answer is the same.
  2. Adding the CORS header in .toml file. It changes the message to an error 404: not found.
  3. Add options to the page, with the below code, but the result is the same (CORS block the connection)
app.options('/test-response', function (req, res) {
    res.setHeader("Access-Control-Allow-Origin", "*");
    res.setHeader('Access-Control-Allow-Methods', '*');
    res.setHeader("Access-Control-Allow-Headers", "*");
    res.end();

Can you tell me what I am doing wrong? By the way, I keep the server deployed in netlify, with solutions 1 and 3, so feel free to test making an axios call (the link is 'https://chambaserver.netlify.app/.netlify/functions/app:4000/test-response').


Solution

  • The request you're sending isn't being handled by anything so it returns a 404 without any of the necessary Access-Control-Allow-* headers.

    As per the Netlify docs, you need to configure internal redirects for Express to match requests to your configured routes.

    Eg, in netlify.toml

    [functions]
      external_node_modules = ["express"]
      node_bundler = "esbuild"
    [[redirects]]
      force = true
      from = "/api/*"
      status = 200
      to = "/.netlify/functions/api/:splat"
    

    Then configure your Express routes to match the /api prefix. This is most easily done using a Router though you can also simply include the prefix in your handler paths

    app.get('/api/test-response', (req, res) => {
      let myText = req.query.mytext;
      console.log(myText);
      return res.send("This is your message: " + myText);
    });
    

    Your client-side request would then use something like this

    axios.get("https://chambaserver.netlify.app/api/test-response", {
      params: {
        mytext: "Alexis response",
      },
    })
    

    Also, make sure you register the cors() middleware before any routes you want made available cross-origin.