Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add proxy to allow working with a back end on a different server/port #127

Merged
merged 3 commits into from
Mar 21, 2015

Conversation

stutrek
Copy link
Contributor

@stutrek stutrek commented Mar 10, 2015

I think the purpose of this PR got missed with my last one. I'm reopening because this is a feature that either makes or breaks the server for me and I'm sure many others. I've implemented this many times and seen it implemented even more. I also changed the configurations to be more flexible.

This adds an option to proxy a single path to an arbitrary server. This is different than the contentBase setting, which can proxy all requests or none. Unless I'm missing a configuration, this is something that is not possible with the server as it stands.

Here are some use cases that make this feature worthwhile:

  • Developing a front end that uses a server side API that runs in a different process or on a different computer.
  • Debugging a problem in production using a local build with production data.
  • Editing non-build files such as images in an app that uses an external service.
  • Developing and debugging using user-supplied or timely content, such as news.
  • Creating a test harness for integration tests or test HTML pages for widgets.
  • Creating a playground for developers to learn a client side interface to a service.
  • Being able to easily switch between dev branches, QA, and production services.

Without a built in proxy this must be done with nginx or a proxy above this server, which makes changing paths tedious and means you can't just clone and spin up another instance of your app.

@sokra
Copy link
Member

sokra commented Mar 12, 2015

Ok, we could remove the contentBase proxy than (in the next major version).
Could you add a deprecated warning when contentBase proxy is used?

@stutrek
Copy link
Contributor Author

stutrek commented Mar 12, 2015

Absolutely.

Should this documentation be updated too?
http://webpack.github.io/docs/webpack-dev-server.html#combining-with-an-existing-server

@stutrek
Copy link
Contributor Author

stutrek commented Mar 16, 2015

@sokra I added them, not sure if you want them styled in any specific way.

@chiefjester
Copy link

+1 here

} else if(/^(https?:)?\/\//.test(contentBase)) {
console.log('Using contentBase as a proxy is deprecated and will be removed in the next major version. Please use the proxy option instead.\n\nTo update remove the contentBase option from webpack.config.js and add this:');
console.log('proxy: {\n\t"*": "'+contentBase+'"\n}');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is wrong here. contentBase is not used as proxy. It's used to redirect requests, which is not deprecated.

@stutrek
Copy link
Contributor Author

stutrek commented Mar 20, 2015

@sokra I removed the warning for non-deprecated redirects

sokra added a commit that referenced this pull request Mar 21, 2015
Add proxy to allow working with a back end on a different server/port
@sokra sokra merged commit 755da19 into webpack:master Mar 21, 2015
@sokra
Copy link
Member

sokra commented Mar 21, 2015

Thanks

@geddski
Copy link

geddski commented Mar 28, 2015

@sakabako could you provide example of how to use this new option?

@MrOrz
Copy link
Contributor

MrOrz commented Mar 28, 2015

@geddski

The following two setup should work:

// webpack.config.js
devServer: {
  proxy: {
    '*': 'http://localhost:5000'
  }
}

and

// webpack.config.js
devServer: {
  proxy: {
    '*': {target: 'http://localhost:5000'}
  }
}

However, the deprecation warning for contentBase proxy is a bit confusing. The warning reads:

Using contentBase as a proxy is deprecated and will be removed in the next major version. Please use the proxy option instead.
To update remove the contentBase option from webpack.config.js and add this
proxy: {
    "*": [your current contentBase configuration]
}

So I put this in my config and the proxy does not work:

proxy: {
    "*": [{target: 'http://localhost:5000'}]
}

Since [ ] has special meaning in Javascript, I suggest using < > instead of [ ] when wrapping the placeholder text.

@SimenB
Copy link
Contributor

SimenB commented Mar 30, 2015

npm publish please 😄

@marclar
Copy link

marclar commented Apr 3, 2015

Haha -- hey, @sakabako! Just setting this up now :)

@jamon
Copy link

jamon commented Apr 5, 2015

I've added a pull request to make this support wildcards/regular expressions in the proxy configuration. See #148.

ex:

        proxy: [
            {
                path: /\/google(.*)/,
                target: "http://www.google.com/"
            }
        ],

Thanks,
Jamon

@KeKs0r
Copy link

KeKs0r commented Apr 7, 2015

Unfortunately I cant get this working with my contentBase setup. I know that contentBase will be deprecated, but with proxies it seems that I loose the capacity to serve static files. And if I set up both: contentbase & proxy, the proxy is never called.

Here my Setup:

    devServer = new webpackDevServer(webpack(webpackConfig),{
        contentBase: './build/',
        hot: true,
        watchDelay: 100,
        proxy: {
            "/api": "localhost:9091",
            //"/": {
            //    target: '/build/'
            //}
    },
        noInfo: true
    });

@jamon
Copy link

jamon commented Apr 7, 2015

@KeKs0r,

My solution will probably work for you, because you can selectively proxy subpaths with wildcards. You can test it by doing an npm install git+https://github.com/jamon/webpack-dev-server.git#installable. Your conf would look very similar to mine, above:

 devServer = new webpackDevServer(webpack(webpackConfig),{
        contentBase: './build/',
        hot: true,
        watchDelay: 100,
        proxy: [{
            /\/api(.*)/: "localhost:9091",

    }],
        noInfo: true
    });

@SimenB
Copy link
Contributor

SimenB commented Apr 7, 2015

Does anyone have a working solution for serving static files using webpack-dev-server, but rerouting all other request to a different server without using contentBase, as it's deprecated?

Just a quick note to @jamon, not contributing to the issue at hand at all 😆
npm is really good at resolving GitHub dependencies, so you can just go npm install jamon/webpack-dev-server#installable.

@stutrek
Copy link
Contributor Author

stutrek commented Apr 7, 2015

Using contentBase as a proxy is deprecated, using it to serve files or redirect is not.

@KeKs0r, I'm not sure if you're having trouble with the proxy or serving static files. Try '/api/*' instead, wildcards are handled by express.

@SimenB
Copy link
Contributor

SimenB commented Apr 7, 2015

@sakabako Ah, I misunderstood then. Thanks for the swift response!

@pvolok
Copy link

pvolok commented Apr 7, 2015

I think contentBase related middleware should be added before the one of proxy. This way it can serve static files if they exist and proxy all other requests to the backend.

Also there is no option for adding headers, which might be useful quite often. The backend can expect a Host header, for instance.

@jamon
Copy link

jamon commented Apr 7, 2015

For those interested, I've updated my related pull request to allow rewriting the request. This should solve your issue @pvolok.

Example:

utility for rewriting URLs

var rewriteUrl = function(replacePath) {
    return function(req, opt) {  // gets called with request and proxy object
        var queryIndex = req.url.indexOf('?');
        var query = queryIndex >= 0 ? req.url.substr(queryIndex) : "";
        req.url = req.path.replace(opt.path, replacePath) + query;
        console.log("rewriting ", req.originalUrl, req.url);
    };
};

config

        proxy: [
            {
                path: new RegExp("/api/example/1/(.*)"),
                rewrite: rewriteUrl("/$1"),
                target: "http://127.0.0.1:3000/"
            }
        ],

*note: fixed bug in example code above

@jordaaash
Copy link

Huge +1 for @jamon's patch, at least the RegExp support.

I was already able to use it to have koa serve my static assets while using React to render the page dynamically and have webpack-dev-server and react-hot-loader do HMR using this (partial) config:

config.devServer = {
    contentBase: config.output.path,
    filename:    'assets/scripts/application.js',
    host:        'localhost',
    hot:         true,
    inline:      true,
    // webpack-dev-server running on 3002
    port:        3002,
    progress:    true,
    publicPath:  config.output.publicPath,
    stats:       { colors: true },
    proxy:       [{
        // proxy all requests not containing ".hot-update.js"
        // regex is still crappy because JS doesn't have negative lookbehind
        path:    /^(?!.*\.hot-update\.js)(.*)$/, 
        // koa running on 3001 with koa-send and isomorphic react
        target:  'http://localhost:3001/'
    }]
};

@stevehu
Copy link

stevehu commented Jul 16, 2015

I have tried all above configurations and none of them works for me. All calls to the API through proxy have 404. Has anyone had a working github project to use api proxy? Thanks.

@SimenB
Copy link
Contributor

SimenB commented Jul 16, 2015

https://github.com/SimenB/webpack-fun/

That worked with an extremely simple express backend a couple months ago. Haven't tested since, but should still be good.

We have a complete working sample at work, I can send relevant parts tomorrow if you still need it.

EDIT: All we do is

new WebpackDevServer(compiler, {
    hot: true,
    inline: true,
    proxy: {
        '*': 'http://localhost:7021'
    },
    stats: { colors: gutil.colors.supportsColor }
}

With localhost being a Spring app running on weblogic. The url kan be staging or other enviros as well, proxying works fine. Using 1.10.1 for both webpack and webpack-dev-server.
compiler has no proxying in it.

The project is closed source, so I can't link to the complete config

@stevehu
Copy link

stevehu commented Jul 17, 2015

@SimenB Thanks for the quick reply and the working example. I tried your proxy settings before and it did work; however, all request goes to the API server including request for react javascript. I am using webpack.config.js and use npm start to start webpack-dev-server. I think the difference is you are using gulp to start webpack-dev-server. I will clone your repo and dig into the detail. What I want to do is the proxy all requests to /api/rs to my API server and everything else to the webpack-dev-server. I call the API from react with superagent.

@lauterry
Copy link

@stevehu Hi I have the same issue as you.

Have you found a solution ?

@stevehu
Copy link

stevehu commented Sep 28, 2015

@lauterry Yes. It works for me now. You can find a working example from my react shopping cart repo https://github.com/networknt/light/tree/master/efg

@williamwa
Copy link

@KeKs0r @SimenB @sakabako
to serve static files, you can use it like this:

var webpack = require('webpack');
var WebpackDevServer = require('webpack-dev-server');
var config = require('./webpack.config');

var path = require('path');
var express = require('express');

var app = new WebpackDevServer(webpack(config), {
  contentBase: config.output.path,
  publicPath: config.output.publicPath,
  hot: true,
  historyApiFallback: true,
});

app.use('/images/', express.static(path.join(__dirname, './images/')));

app.listen(3000, '0.0.0.0', function (err, result) {
  if (err) {
    console.log(err);
  }

  console.log('Listening at 0.0.0.0:3000');
});

@zuobuer
Copy link

zuobuer commented Jul 28, 2016

when I use Ajax to get data from remote API, the proxy do not work for me?
proxy: [{ path: /\/stackoverflow(.*)/, target: "http://www.stackoverflow.com/" }], $.get('/stackoverflow/', function(data) { //console.log(data); });
the result like this.
image
why the remote address is 127.0.0.1:80?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet