Search code examples
node.jsexpressherokunext.jsfetch-api

Apps (client/server) not working with cors when hosted on Heroku


I am facing an issue when running my apps on the Heroku server; though it was all working fine locally. I hope some expert or just an second pair of eyes will point something I may be missing.

One app is a server and this is the code:

const express = require('express'),
      server = express(),
      cors = require('cors');

server.use(cors({origin: "https://client-fox-67890fghij.herokuapp.com/"}));

server.get('/json-data', (req, res) => {
  res.status(200).send([
      {order:1,value:2},
      {order:10,value:29}
    ])
});

The other app is a client (Next.JS) and this is the code:

The app/page.tsx file:

import Receiver from './components/Receiver'

export default function Home() {
  return (
    <main className="flex min-h-screen flex-col items-center justify-between p-24">
      <div>
        <Receiver />
      </div>
    </main>
  )
}

The app/components/Receiver.tsx file:

'use client'

import {useState,useEffect} from "react"
import ListShow from './ListShow'

function Receiver() {
  const [data, setData] = useState([]);
  // const apiURL = 'http://localhost:8888/json-data'
  const apiURL = 'https://server-wolf-12345abcde.herokuapp.com/json-data'

  useEffect(() => {
    let ignore = false;

    async function fetchData() {
      const result = await fetch(apiURL);
      if (!ignore) setData(await result.json());
    }

    fetchData();
    return () => { ignore = true; }
  }, []);

  return <><ListShow dataList={data}/></>;
}


export default Receiver;

After uploading both apps and checking that the server side is responding as expected by pointing the web browser to:

https://server-wolf-12345abcde.herokuapp.com/json-data

When I then point the browser to:

https://client-fox-67890fghij.herokuapp.com/

I have this error in the Web Developer Tools Console in Firefox:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://server-wolf-12345abcde.herokuapp.com/json-data. (Reason: CORS header ‘Access-Control-Allow-Origin’ does not match ‘https://client-fox-67890fghij.herokuapp.com/’).
Uncaught (in promise) TypeError: NetworkError when attempting to fetch resource.

Locally the server ran on localhost:8888 and the client on localhost:3000.

Then in the server I was using:

server.use(cors({origin: "http://localhost:3000"}));

Why is it no longer working when the server and the client are hosted on Heroku ?


Solution

  • Is that the exact error message, or did you massage it a bit (e.g. to hide your actual Heroku domains)? No apps appear to be hosted at those URLs, and I wonder if this obscured the problem by subtly changing the domain in the error message.

    The documentation gives examples for the origin without a trailing slash:

    For example if you set it to "http://example.com" only requests from “http://example.com” will be allowed.

    When origin is a string, comparison is made using === which means it's not going to be very flexible on this point. Playing around in my browser, it looks like requests don't include a trailing slash in the Origin header.

    Try removing that slash:

    server.use(cors({origin: "https://client-fox-67890fghij.herokuapp.com"}));
    //                                                                   ^