webpack dev server CORS issue
Asked Answered
S

5

81

I am using webpack-dev-server v1.10.1 to boost up my Redux project and I have the options below:

contentBase: `http://${config.HOST}:${config.PORT}`,
quiet: false,
noInfo: true,
hot: true,
inline: true,
lazy: false,
publicPath: configWebpack.output.publicPath,
headers: {"Access-Control-Allow-Origin": "*"},
stats: {colors: true}

In the JS, I am using request from superagent to generate a HTTP GET call

request
          .get(config.APIHost + apiUrl)
          .set('Accept', 'application/json')
          .withCredentials()
          .end(function (err, res) {
                if (!err && res.body) {
                    disptach(() => {
                        return {
                            type: actionType || GET_DATA,
                            payload: {
                                response: res.body
                            }
                        }
                    });
                }
          });

But I got the CORS error:

XMLHttpRequest cannot load http://localhost:8000/api/getContentByType?category=all. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:5050' is therefore not allowed access

Any suggestion to resolve this? Thanks a lot

Shieh answered 24/7, 2015 at 5:16 Comment(0)
C
108

Another way to work around it is to directly add the required CORS headers to the dev server:

devServer: {
  ...
  headers: {
    "Access-Control-Allow-Origin": "*",
    "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, PATCH, OPTIONS",
    "Access-Control-Allow-Headers": "X-Requested-With, content-type, Authorization"
  }
}

Doc links

Chairborne answered 25/6, 2017 at 16:38 Comment(6)
Any links to where you found this?Sundried
It's in the webpack docs: webpack.js.org/configuration/dev-server/#devserver-headers-Chairborne
Adding this doesn't work for me, nothing changes. Still I get error of missing access-control-allow-headers header.Aronoff
Usually it's enough to just put "Access-Control-Allow-Origin" there.Sula
If you also use a browser through some redirection (proxy, ssh redirect, …), use the devServer option sockPort: 'location', so the socket port will use the same as the location port, which is usually enough.Alcot
@Aronoff Try specifying the allowed hosts. Under headers: ..., add allowedHosts: ["localhost", ".host.com", "host2.com", "subdomain.host3.com"]. The .host.com entry is a wildcard for any subdomain on that domain. You can aslo use "auto", which you can read about here.Ultra
S
55

With webpack-dev-server 1.15.X you can use this configuration in your config file:

devServer: {
   contentBase: DIST_FOLDER,
   port: 8888,
   // Send API requests on localhost to API server get around CORS.
   proxy: {
      '/api': {
         target: {
            host: "0.0.0.0",
            protocol: 'http:',
            port: 8080
         },
         pathRewrite: {
            '^/api': ''
         }
      }
   }
},

With this example you will redirect all calls from http://0.0.0.0:8888/api/* to http://0.0.0.0:8080/* and CORS solved

Sisak answered 9/9, 2016 at 15:0 Comment(4)
This is not working for me. Still getting the exception saying Access to fetch at 'localhost:8080/api/auth' from origin 'localhost:9000' has been blocked by CORS policy: The 'Access-Control-Allow-Origin' header has a value 'localhost:7000'. I intentionaly added 'localhost:7000' in back end. Just to verify that if proxy is working on my front end, this setting will not restrict my api call.Ragout
It had been a bit different issue I believe, but apparently just setting port: 8080 was enough for me. I just wanted to enable 'hot reload' (while using Vue). Thank You anyway!Comintern
I like this solution, because as far as I can see this setup is closest to typical production setups, where e.g. an appropriate NGINX config would similarly unify the frontend + backend under the same origin.Truda
This worked for me. But! In my API, I also use the websockets. To allow websockets to be passed through proxy, add ws: true to '/api' node.Stadiometer
D
18

Had the same issue, but my api was on a https protocol (https://api....). Had to start the server with https and use https://localhost:8080

devServer: {
    https: true,
    headers: {
        "Access-Control-Allow-Origin": "*",
    },
    // ....
}
Dissected answered 18/7, 2019 at 9:53 Comment(1)
This is exactly what I was looking for! Thanks!!Justiciar
P
11

You're running your JavaScript from localhost:5050 but your API server is localhost:8000. This violates the same origin policy, so the browser disallows it.

You can either modify your API server so that CORS is enabled, or follow the instructions on the webpack-dev-server page under "Combining with an existing server" to combine asset serving with webpack-dev-server and your own API server.

Pettus answered 24/7, 2015 at 20:51 Comment(2)
The second link is now brokenVas
This is the official documentation. webpack.js.org/configuration/dev-server/#devserverproxySpoof
P
4

There are 2 solutions for this. first one is setting up proxy on the client side, second one is setting CORS on the server. CORS is server issue, server does not allow access from different source. Even using different ports is considered to be different source

First Solution

IN your backend code, you have to set this headers: this is example of in express node.js

app.use((req, res, next) => {
  res.setHeader("Access-Control-Allow-Origin", "*");
  res.setHeader(
    "Access-Control-Allow-Methods",
    "OPTIONS, GET, POST, PUT, PATCH, DELETE"
  );
  res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
  next();
});

Second Solution:

in webpack config.js, if you want to pass any variable, we export

module.exports=function(env){
return {}} 

instead of

module.exports={}

we inject this env through the script.

"dev-server": "webpack-dev-server --env.api='https://jsonplaceholder.typicode.com/users'",

now webpack has access to this env. in webpack.config.js

module.exports = function ({
  api = "https://jsonplaceholder.typicode.com/users",
}) {
  return {
    entry: { main: "./src/index.js" },
    output: {
      path: path.resolve(__dirname, "public"),
      filename: "[name]-bundle.js",
      publicPath: "/",
    },
    mode: "development",
    module: {
      rules: [
        {
          loader: "babel-loader",
          test: /\.js$/,
          exclude: [/node_modules/],
        },
        
        {
          // Load other files, images etc
          test: /\.(png|j?g|gif|ico)?$/,
          use: "url-loader",
        },
        {
          test: /\.s?css$/,
          use: ["style-loader", "css-loader", "sass-loader"],
        },
      ],
    },
    //Some JavaScript bundlers may wrap the application code with eval statements in development.
    //If you use Webpack, using the cheap-module-source-map setting in development to avoid this problem
    devtool: "cheap-module-eval-source-map",
    devServer: {
      contentBase: path.join(__dirname, "public"),
      historyApiFallback: true,
      proxy: {
        "/api": {
          changeOrigin: true,
          cookieDomainRewrite: "localhost",
          target: api,
          onProxyReq: (proxyReq) => {
            if (proxyReq.getHeader("origin")) {
              proxyReq.setHeader("origin", api);
            }
          },
        },
      },
    },
    
  };
};
Pasteurize answered 3/6, 2020 at 18:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.