angular-cli server - how to proxy API requests to another server?

Solution 1:

UPDATE 2017

Better documentation is now available and you can use both JSON and JavaScript based configurations: angular-cli documentation proxy

sample https proxy configuration

{
  "/angular": {
     "target":  {
       "host": "github.com",
       "protocol": "https:",
       "port": 443
     },
     "secure": false,
     "changeOrigin": true,
     "logLevel": "info"
  }
}

To my knowledge with Angular 2.0 release setting up proxies using .ember-cli file is not recommended. official way is like below

  1. edit "start" of your package.json to look below

    "start": "ng serve --proxy-config proxy.conf.json",

  2. create a new file called proxy.conf.json in the root of the project and inside of that define your proxies like below

    {
      "/api": {
        "target": "http://api.yourdomai.com",
        "secure": false
      }
    }
    
  3. Important thing is that you use npm start instead of ng serve

Read more from here : Proxy Setup Angular 2 cli

Solution 2:

I'll explain what you need to know on the example below:

{
  "/folder/sub-folder/*": {
    "target": "http://localhost:1100",
    "secure": false,
    "pathRewrite": {
      "^/folder/sub-folder/": "/new-folder/"
    },
    "changeOrigin": true,
    "logLevel": "debug"
  }
}
  1. /folder/sub-folder/*: path says: When I see this path inside my angular app (the path can be stored anywhere) I want to do something with it. The * character indicates that everything that follows the sub-folder will be included. For instance, if you have multiple fonts inside /folder/sub-folder/, the * will pick up all of them

  2. "target": "http://localhost:1100" for the path above make target URL the host/source, therefore in the background we will have http://localhost:1100/folder/sub-folder/

  3. "pathRewrite": { "^/folder/sub-folder/": "/new-folder/" }, Now let's say that you want to test your app locally, the url http://localhost:1100/folder/sub-folder/ may contain an invalid path: /folder/sub-folder/. You want to change that path to a correct one which is http://localhost:1100/new-folder/, therefore the pathRewrite will become useful. It will exclude the path in the app(left side) and include the newly written one (right side)

  4. "secure": represents wether we are using http or https. If https is used in the target attribute then set secure attribute to true otherwise set it to false

  5. "changeOrigin": option is only necessary if your host target is not the current environment, for example: localhost. If you want to change the host to www.something.com which would be the target in the proxy then set the changeOrigin attribute to "true":

  6. "logLevel": attribute specifies wether the developer wants to display proxying on his terminal/cmd, hence he would use the "debug" value as shown in the image

In general, the proxy helps in developing the application locally. You set your file paths for production purpose and if you have all these files locally inside your project you may just use proxy to access them without changing the path dynamically in your app.

If it works, you should see something like this in your cmd/terminal.

enter image description here

Solution 3:

This was close to working for me. Also had to add:

"changeOrigin": true,
"pathRewrite": {"^/proxy" : ""}

Full proxy.conf.json shown below:

{
    "/proxy/*": {
        "target": "https://url.com",
        "secure": false,
        "changeOrigin": true,
        "logLevel": "debug",
        "pathRewrite": {
            "^/proxy": ""
        }
    }
}

Solution 4:

EDIT: THIS NO LONGER WORKS IN CURRENT ANGULAR-CLI

See answer from @imal hasaranga perera for up-to-date solution


The server in angular-cli comes from the ember-cli project. To configure the server, create an .ember-cli file in the project root. Add your JSON config in there:

{
   "proxy": "https://api.example.com"
}

Restart the server and it will proxy all requests there.

For example, I'm making relative requests in my code to /v1/foo/123, which is being picked up at https://api.example.com/v1/foo/123.

You can also use a flag when you start the server: ng serve --proxy https://api.example.com

Current for angular-cli version: 1.0.0-beta.0

Solution 5:

Here is another way of proxying when you need more flexibility:

You can use the 'router' option and some javascript code to rewrite the target URL dynamically. For this, you need to specify a javascript file instead of a json file as the --proxy-conf parameter in your 'start' script parameter list:

"start": "ng serve --proxy-config proxy.conf.js --base-href /"

As shown above, the --base-href parameter also needs to be set to / if you otherwise set the <base href="..."> to a path in your index.html. This setting will override that and it's necessary to make sure URLs in the http requests are correctly constructed.

Then you need the following or similar content in your proxy.conf.js (not json!):

const PROXY_CONFIG = {
    "/api/*": {
        target: https://www.mydefaulturl.com,
        router: function (req) {
            var target = 'https://www.myrewrittenurl.com'; // or some custom code
            return target;
        },
        changeOrigin: true,
        secure: false
    }
};

module.exports = PROXY_CONFIG;

Note that the router option can be used in two ways. One is when you assign an object containing key value pairs where the key is the requested host/path to match and the value is the rewritten target URL. The other way is when you assign a function with some custom code, which is what I'm demonstrating in my examples here. In the latter case I found that the target option still needs to be set to something in order for the router option to work. If you assign a custom function to the router option then the target option is not used so it could be just set to true. Otherwise, it needs to be the default target URL.

Webpack uses http-proxy-middleware so you'll find useful documentation there: https://github.com/chimurai/http-proxy-middleware/blob/master/README.md#http-proxy-middleware-options

The following example will get the developer name from a cookie to determine the target URL using a custom function as router:

const PROXY_CONFIG = {
    "/api/*": {
        target: true,
        router: function (req) {
            var devName = '';
            var rc = req.headers.cookie;
            rc && rc.split(';').forEach(function( cookie ) {
                var parts = cookie.split('=');
                if(parts.shift().trim() == 'dev') {
                    devName = decodeURI(parts.join('='));
                }
            });
            var target = 'https://www.'+ (devName ? devName + '.' : '' ) +'mycompany.com'; 
            //console.log(target);
            return target;
        },
        changeOrigin: true,
        secure: false
    }
};

module.exports = PROXY_CONFIG;

(The cookie is set for localhost and path '/' and with a long expiry using a browser plugin. If the cookie doesn't exist, the URL will point to the live site.)