webpack-dev-server: devServer proxy not working

Do you want to request a feature or report a bug? Bug

What is the current behavior? devServer proxy doesn’t proxy.

If the current behavior is a bug, please provide the steps to reproduce. Client server running at localhost:8080 and API server running at localhost:8000. I’ve tried several variations of what to proxy (api/*, /api/**, api/**, etc). Use the following proxy settings:

  devServer: {
    hot: true,
    contentBase: resolve(__dirname, 'dist'),
    publicPath: '/',
    proxy: {
      '/api/**': {
        target: 'http://localhost:8000',
        secure: false,
        changeOrigin: true,
      }
    },
  },

What is the expected behavior? Hitting /api/path should be proxied to http://localhost:8000/api/path but is instead hitting http://localhost:8080/api/path.

Please mention your webpack and Operating System version.

  • webpack @ 2.2.1
  • webpack-dev-server @ 2.3.0
  • macOS 10.12.3

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 6
  • Comments: 49 (4 by maintainers)

Commits related to this issue

Most upvoted comments

replace localhost with [::1]. like so: ‘http://[::1]:3000’

this works for me:

devServer: {
  proxy: {
    "*": "http://[::1]:8081"
    // "secure": false,
    // "changeOrigin": true
  }
},

one wildcard, or double, with ‘secure’ or ‘changeOrigin’ - doesnt matter. [::1] is the game changer. Good luck!

In my case, I had to rewrite the path:

proxy: {
   '/api/**': {
      target: 'http://localhost:9596/',
      pathRewrite: { '^/api': '' },
      secure: false,
      logLevel: 'debug'
   }
}

Hope this can help.

Make sure that your request url and port matches that which your webpack-dev-server is running on. So, if your api is located at http://localhost:5000, and your dev server is running on http://localhost:8080, make sure all of your requests are to http://localhost:8080. Its best to make your requests to localhost:8080/api (to avoid conflict with app routes) and use the path rewrite to remove the /api.

Example: Webpack devserver proxy config:

proxy: {
    '/api': {
        target: 'http://localhost:5000',
        pathRewrite: { '^/api': '' },
    },
}

Webpack dev server running on: http://localhost:8080 Desired API endpoint: http://localhost:5000/items

In your app, make the request to: http://localhost:8080/api/items.

This should work. It seems to me that all of the above issues stem from making the request to the API url and port rather than the webpack dev server url and port and using the proxy and path rewrite to direct the request to the API.

same issue on OSX

Same issue on OSX as well.

Having the same issue here, also OSX

For us setting the header Connection: keep-alive did the trick. Requests were handled by the backend server and a response was sent as well, nevertheless we saw the error ECONNRESET for some of the API requests before.

'api' : {
  target: SERVER_URL,
  secure: false,
  changeOrigin: true,
  headers: {
    Connection: 'keep-alive',
  },
}

Same issue on OSX.

The issue is 4+ years old. Though it is closed I am wondering why no-one references a documentation where it is (officially) described how it all works.

By the way, I do have the same problem as @gjunkie stated in the first post.
Is there anywhere a good explanation what to put where under what circumstances?

I see variants of webpack usage, path-rewrite, /api/** usage, secure: false, pathRewrite…you name you’ll find it but without proper documentation reference.

Well, I made it run on other projects so far, but it is sucky that it always consumes so much time to get it working…

How to set proxy buffer, i want to upload some files to backend

For Webpack 4 and OSX10, I had to add changeOrigin property to make it work.

{
    historyApiFallback: true,
    contentBase: './static',
    port: 9095,
    proxy: {
        '/api/**': {
            target: 'http://another-url',
            pathRewrite: {
                '^/api': '',
            },
            secure: false,
            changeOrigin: true,
            logLevel: 'debug',
        },
    },
};

I have the same problem as @gjunkie. Starting from v1.15.0 the http-proxy-middleware is installed as dependency and a ECONNRESET error is thrown each time I try to make a request to the backend.

Apparently, it is only happening in OS X environment because my colleagues at work are using Ubuntu and they can’t reproduce this problem.

@italoborges You saved my life:)

pathRewrite: {'^/api': ''}

@jellyfish-tom your solution did it for me with Mac OSX 10

replace localhost with [::1]. like so: ‘http://[::1]:3000’

this works for me:

devServer: {
  proxy: {
    "*": "http://[::1]:8081"
    // "secure": false,
    // "changeOrigin": true
  }
},

I faced similar issue, however my issue was: My UI ran on: localhost:9000 My API ran on localhost:3000 and endpoint /api/**

My proxy config:

devServer: {
    proxy: {
        '/api/**': {
            target:'http://localhost:3000'
        }
    }
}

My problem was - when I was making API calls from my React UI, i was pointing it to locahost:3000/api/** whereas I need to point it at the localhost:9000/api/** so that i can proxy it from the local domain to the remote domain.

I couldn’t get devServer proxy to work either (OS X 10). I’m running with a server.js which reads webpack.config.js and my workaround was a reverse proxy using http-proxy in server.js:

var httpProxy = require('http-proxy');
var apiProxy = httpProxy.createProxyServer();

// ... was here before
var app = express();
var compiler = webpack(config);

app.use(require('webpack-dev-middleware')(compiler, {
  publicPath: config.output.publicPath
}));

app.use(require('webpack-hot-middleware')(compiler));
// ... end of was here before

app.all("/api/*", function(req, res) {
    apiProxy.web(req, res, {target: 'http://localhost:3102'});
});

Reference: https://codeforgeek.com/2015/12/reverse-proxy-using-expressjs/

Solution for this stack: macOS 10.14.6, docker 20.10.0, docker-compose 1.27.4, webpack 4.38.0, preact-cli 3.0.3.

// Example of a webpack config for a preact application.
// preact.config.js

export default {
      
  webpack(config, env, helpers, options) {
    
    // "Gateway" is my Nginx service that routes API requests 
    // and static files inside my Docker network.

    let target = 'http://gateway'

    config.devServer.proxy = [
      {
        path: '/api/v1',
        target
      },
      {
        path: '/static',
        target
      }
    ]

  }

}
// Example of a client-side request.

fetch(`/api/v1/service-name/test`)
  .then((res) => res.json())
  .then((data) => {
    console.log(data)
  })
  .catch(err => {
    console.error(err)
  })
// Example of connecting a static file.
<img src='/static/images/test.jpg' />

I ran into the same issue and found

new CopyWebpackPlugin([
      {
        from: path.resolve(__dirname, '../static'),
        to: config.dev.assetsSubDirectory,
        ignore: ['.*']
      }
    ])

in webpack.dev.conf.js . Seems, it changes the way, proxyTable is handling the path to static?? I commented it out, restarted npm run dev and all is running fine again. Is there a better way to handle this than deleting the plugin?

BTW. This is my config for proxytable (now working again):

proxyTable: {
			'/static': {
				target: 'http://firedev.local:8888',
				changeOrigin: true,
				logLevel: 'debug'
			}
		},

Been scratching my head since Monday trying to figure this out! This ended up working for me:

proxy: {
	'**': {
		target: 'http://localhost:8080',
		secure: false
	}
}

I have webpack-dev-server running on port 3000, and Express running on port 8080. Requests to the API are made via http://localhost:3000/api/<whatever>

We’ve got a few workarounds posted for folks running into the issue. It seems that this might be slightly edge casey, however. If anyone would like to put together a Pull Request, we’d happily review it and revisit this issue.

This configuration is working for me on OSX (I sweated blood to make it work). I have the GNU Coreutils installed, by the way (don’t know if has something to do).

, proxy: [
          {
            path: /^\/styleguide(?!\/core-css\/build)/
          , target: 'http://localhost:8000'
          , bypass: function(req, res, _options) {
              return req.url.replace('styleguide', styleguideRoothPath + '/build');
            }
          }
        , {
            path: "**",
            target: "http://localhost:3000",
            secure: false,
            bypass: function(req, res, options) {
              if(req.url === '' || req.url === '/') {
                res.statusCode = 302;
                res.setHeader('Location', '/a/');
                return '/a/';
              }

              var frontend = new RegExp("^\/$^|\/a\/index\.html|^\/a\/|^\/a$|^\/styleguide");
              if (frontend.test(req.url)) return req.url;
            }
          }
        ]