Search code examples
javascriptreactjsproxycreate-react-app

Why is the proxy inside package.json not working in my React application?


I am currently trying to perform a simple fetch instruction in my React application, though, the actual url always ends up being that of the React application itself.

The React app is hosted at localhost:3000, and the server I am trying to connect to is at localhost:8080.

In the package.json I have a proxy field like so:

"proxy": "http://localhost:8080"

Then I have a fetch somewhere like so:

fetch('/', { /* stuff... */ })

But when I check in my browser it says a fetch request happened to http://localhost:3000; in another application, it used to be that if you had a proxy, this would just go to localhost:8080, but not this time.

I tried stuff like deleting the node_modules folder and package-lock.json, but that did not do anything (also did a npm install afterward). If I do this:

fetch('http://localhost:8080', { /* stuff... */ })

The url seems to be the correct one, though I get all sorts of random errors which I just do not understand:

Access to fetch at 'http://localhost:8080/' 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. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

I have never heard of CORS, perhaps this is new? So I have two questions really:

  1. How to get my React proxy to work?
  2. How do I get rid of this CORS stuff? I am running both servers myself so "access control checks" is a whole load of bogus...

Cheers!


Solution

  • For the proxy to handle a request, the endpoint you are calling shouldn't be handled by your React development server. For example, instead of fetch('/'), which is the endpoint that sends your React index.html file, your API should be at something like fetch('/api/').

    Like the doc says:

    To tell the development server to proxy any unknown requests to your API server in development, add a proxy field to your package.json, for example: "proxy": "http://localhost:8080".

    This way, when you fetch('/api/todos') in development, the development server will recognize that it’s not a static asset, and will proxy your request to http://localhost:8080/api/todos as a fallback. The development server will only attempt to send requests without text/html in its Accept header to the proxy.

    If it's still not working, you can switch to configuring the proxy manually, which is the second way to set up a proxy that Create React App talks about.

    For that, first, remove the proxy you have in package.json, keep it as it's the rule for the endpoint I talked about above, then:

    npm install http-proxy-middleware --save-dev
    

    And finally, create a src/setupProxy.js file:

    const { createProxyMiddleware } = require('http-proxy-middleware');
    
    module.exports = function(app) {
      app.use(
        '/api', // 👈🏽 your API endpoint goes here.
        createProxyMiddleware({
          target: 'http://localhost:8080', // 👈🏽 your API URL goes here.
          changeOrigin: true,
        })
      );
    };
    

    With that, you should be good to go. And about CORS, it's not new. You can read about it on mdn if you like.