137

With the angular-cli ng serve local dev server, it's serving all the static files from my project directory.

How can I proxy my AJAX calls to a different server?

Florian F
  • 1,300
  • 1
  • 12
  • 28
elwyn
  • 10,360
  • 11
  • 42
  • 52

13 Answers13

222

UPDATE 2022

The officially recommended approach is now the one documented here

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

glenatron
  • 11,018
  • 13
  • 64
  • 112
Imal Hasaranga Perera
  • 9,683
  • 3
  • 51
  • 41
  • 1
    How do you do with "unsafe" credentials. Using node I can set the process.env.NODE_TLS_REJECT_UNAUTHORIZED to 0 and will by pass that security, but I don't know how to do it with the proxy.config.json. This is all development stack, I don' t mind if it feels insecure – nicowernli Oct 31 '16 at 09:41
  • 1
    having "secure":false should do, it should be a boolean not a string... i spent countless time by keeping it "false" – Imal Hasaranga Perera Oct 31 '16 at 09:55
  • This works for me but the with the proxy ends up being something like `/api/api/person` any idea why is this happening? – ocespedes Mar 23 '17 at 21:57
  • can you share the proxy.conf.json of yours so I can have a look ? – Imal Hasaranga Perera Mar 24 '17 at 05:48
  • 2
    where is the documentation for proxy.conf.json? – heldt May 18 '17 at 06:46
  • This works for me sometimes. But not always with current angular-cli version: 1.0.2. Problem is it connects to server and gets JSON responds. Then in chrome network console if we check, along with JSN data, it adds extra string. `{"name":"something","id":"12sde"}Error occured while trying to proxy to: localhost:4200/api/v1/login`. Any idea why it's happening? And not always. Detailed question here - http://stackoverflow.com/questions/44006326/angular-connects-to-proxy-server-and-gets-response-but-then-shows-error-occure?noredirect=1#comment75070129_44006326 – iCode May 18 '17 at 16:53
  • Here is the documentation: https://github.com/angular/angular-cli/wiki/stories-proxy – JuanPablo Jul 10 '17 at 21:57
  • There are many other ways yout can do this, please refer to documentation https://github.com/angular/angular-cli/blob/master/docs/documentation/stories/proxy.md – Imal Hasaranga Perera Jul 14 '17 at 07:12
  • there is a stray comma "logLevel": "info", should be "logLevel": "info" (without the comma) – rjdkolb Aug 13 '17 at 14:51
  • It's possible to make it work in productive environment using node express? – leoxs Aug 19 '17 at 02:17
  • @imalhasarangaperera can I use an IP from a different network for the proxy target? – fariba.j Jul 11 '18 at 11:11
  • yes that is basic idea here, so as the ip address and the port is accessible from your local computer proxy should work fine – Imal Hasaranga Perera Jul 11 '18 at 11:22
  • Is there a way to add a single context that proxies all requests? It's annoying to have to add every single route that goes to the backend server. – Justin Aug 08 '19 at 17:56
  • I would be grateful if someone could point to any documentation stating that the `target` key accepts an Object and not a String value. Angular and Webpack docs only show String as an accepted value. – ktsangop Sep 10 '19 at 11:50
  • I've done the same thing but when I do ```ng build --prod```, it is not working probably because proxy.conf doesn't gets added in dist folder. So what to do while production build – Avishek Jul 22 '20 at 14:04
  • @Avishek this is not for production at all! you should not even try to get this to work in production. in production environment make sure that you have set up a server-level reverse proxy – Imal Hasaranga Perera Jul 27 '20 at 06:17
  • @imalhasarangaperera how proxy will work for production environment? please guide me. what step I should follow to make it work on production? – Asif Jun 10 '21 at 06:59
  • @imalhasarangaperera how to setup reverse proxy? – Asif Jun 10 '21 at 07:00
  • Guys this is not for production! this is a quick way you can forward your requests to the dev or staging based on the config.. you need to have set up reverse proxies within the actual server which the code is going to deploy – Imal Hasaranga Perera Jun 11 '21 at 07:57
  • This is now in the official Angular documentation: https://angular.io/guide/build#proxying-to-a-backend-server. Follow the official tutorial so we can do `ng serve` without extra parameters – Vũ Ngô Nov 19 '21 at 12:49
94

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

EugenSunic
  • 13,162
  • 13
  • 64
  • 86
  • 1
    Thanks, this is the right answer for the current version of Angular. The "changeOrigin" option is only necessary if your target is not *localhost*, though. Also you need to load the proxy config file by running with the flag, *ng serve --proxy-config proxy.conf.json* Apparently ignores the flag inside package.json (as in the previous examples). – Andrew Dec 22 '17 at 01:52
  • 1
    this worked for me, except the star character is no longer supported. – Ant Kutschera Mar 12 '23 at 19:00
40

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": ""
        }
    }
}
Marcos Dimitrio
  • 6,651
  • 5
  • 38
  • 62
Tony Scialo
  • 5,457
  • 11
  • 35
  • 52
  • this should be chosen answer for external API reference locally. This pathRewrite was what resolves an issue when referencing external EP, replacing reference with target. – chris_r Jun 11 '21 at 15:36
27

Currently, as of Angular 12, the official approach is like this:

Create a file called proxy.conf.json in the /src folder of your project and use it to define your proxies:

    {
      "/api": {
        "target": "http://api.yourdomai.com",
        "secure": false
      }
    }

Change your angular.json file to include the proxy when you run it:

...
"architect": {
  "serve": {
    "builder": "@angular-devkit/build-angular:dev-server",
    "options": {
      "browserTarget": "your-application-name:build",
      "proxyConfig": "src/proxy.conf.json"
    },
...

Note that you can set this per configuration, so if you only wanted the proxy configured in your development environment (often in production you would use your HTTP server to manage the proxying) you could configure it like this:

...
"architect": {
  "serve": {
    "builder": "@angular-devkit/build-angular:dev-server",
    "production": {
      "browserTarget": "your-application-name:build",
    },
    "development": {
      "browserTarget": "your-application-name:build",
      "proxyConfig": "src/proxy.conf.json"
    },
...

Now when you run ng serve it will proxy requests correctly.

The full documentation is here : Building and serving Angular- proxying to a backend server

glenatron
  • 11,018
  • 13
  • 64
  • 112
14

EDIT: THIS NO LONGER WORKS IN CURRENT ANGULAR-CLI

See other answers 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

elwyn
  • 10,360
  • 11
  • 42
  • 52
  • 1
    Thanks for your answer @elwyn. Is it possible to proxy only urls matching some pattern, like '/api/v1/'? – Marian Zagoruiko May 15 '16 at 09:28
  • I'm not sure - I haven't had a need to do that. The webserver is just vanilla `ember-cli` under the hood (for now, anyway), so maybe look into their docs? This person seems to have an example of custom proxies running: http://stackoverflow.com/q/30267849/227622 – elwyn May 16 '16 at 05:34
  • Did that yesterday. As you said, it's just vanilla ember-cli. So I've created an ember application, generated a proxy there (there is no such generator available in angular-cli yet) and copied in to my angular app. Works good. Thanks. – Marian Zagoruiko May 16 '16 at 11:58
10

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.)

Zoltan M
  • 121
  • 1
  • 3
10

In case if someone is looking for multiple context entries to the same target or TypeScript based configuration.

proxy.conf.ts

const proxyConfig = [
  {
    context: ['/api/v1', '/api/v2],
    target: 'https://example.com',
    secure: true,
    changeOrigin: true
  },
  {
    context: ['**'], // Rest of other API call
    target: 'http://somethingelse.com',
    secure: false,
    changeOrigin: true
  }
];

module.exports = proxyConfig;

ng serve --proxy-config=./proxy.conf.ts -o

prabhatojha
  • 1,925
  • 17
  • 30
7

Step 1:Go to Your root folder Create proxy.conf.json

{
  "/auth/*": {
    "target": "http://localhost:8000",
    "secure": false,
    "logLevel": "debug",
    "changeOrigin": true
  }
}

Step 2:Go to package.json find "scripts" under that find "start"

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

Step 3:now add /auth/ in your http

 return this.http
      .post('/auth/register/', { "username": 'simolee12', "email": 'xyz@gmail.com', "password": 'Anything@Anything' });
  }

Step 4:Final Step in Terminal run npm start

yash sanghavi
  • 368
  • 3
  • 5
6
  1. add in proxy.conf.json, all request to /api will be redirect to htt://targetIP:targetPort/api.
{
  "/api": {
    "target": "http://targetIP:targetPort",
    "secure": false,
    "pathRewrite": {"^/api" : targeturl/api},
    "changeOrigin": true,
    "logLevel": "debug"
  }
}
  1. in package.json, make "start": "ng serve --proxy-config proxy.conf.json"

  2. in code let url = "/api/clnsIt/dev/78"; this url will be translated to http://targetIP:targetPort/api/clnsIt/dev/78.

  3. You can also force rewrite by filling the pathRewrite. This is the link for details cmd/NPM console will log something like "Rewriting path from "/api/..." to "http://targeturl:targetPort/api/..", while browser console will log "http://loclahost/api"

Feng Zhang
  • 1,698
  • 1
  • 17
  • 20
5

It's important to note that the proxy path will be appended to whatever you configured as your target. So a configuration like this:

{
  "/api": {
    "target": "http://myhost.com/api,
    ...
  }
}

and a request like http://localhost:4200/api will result in a call to http://myhost.com/api/api. I think the intent here is to not have two different paths between development and production environment. All you need to do is using /api as your base URL.

So the correct way would be to simply use the part that comes before the api path, in this case just the host address:

{
  "/api": {
    "target": "http://myhost.com",
    ...
  }
}
codemusings
  • 117
  • 1
  • 5
4

We can find the proxy documentation for Angular-CLI over here:

https://github.com/angular/angular-cli/blob/master/docs/documentation/stories/proxy.md

After setting up a file called proxy.conf.json in your root folder, edit your package.json to include the proxy config on ng start. After adding "start": "ng serve --proxy-config proxy.conf.json" to your scripts, run npm start and not ng serve, because that will ignore the flag setup in your package.json.

current version of angular-cli: 1.1.0

Luuk Schoenmakers
  • 1,814
  • 1
  • 8
  • 5
3

Cors-origin issue screenshot

Cors issue has been faced in my application. refer above screenshot. After adding proxy config issue has been resolved. my application url: localhost:4200 and requesting api url:"http://www.datasciencetoolkit.org/maps/api/geocode/json?sensor=false&address="

Api side no-cors permission allowed. And also I'm not able to change cors-issue in server side and I had to change only in angular(client side).

Steps to resolve:

  1. create proxy.conf.json file inside src folder.
   {
      "/maps/*": {
        "target": "http://www.datasciencetoolkit.org",
        "secure": false,
        "logLevel": "debug",
        "changeOrigin": true
      }
    }
  1. In Api request
this.http
      .get<GeoCode>('maps/api/geocode/json?sensor=false&address=' + cityName)
      .pipe(
        tap(cityResponse => this.responseCache.set(cityName, cityResponse))
      );

Note: We have skip hostname name url in Api request, it will auto add while giving request. whenever changing proxy.conf.js we have to restart ng-serve, then only changes will update.

  1. Config proxy in angular.json
"serve": {
          "builder": "@angular-devkit/build-angular:dev-server",
          "options": {
            "browserTarget": "TestProject:build",
            "proxyConfig": "src/proxy.conf.json"
          },
          "configurations": {
            "production": {
              "browserTarget": "TestProject:build:production"
            }
          }
        },

After finishing these step restart ng-serve Proxy working correctly as expect refer here

> WARNING in
> D:\angular\Divya_Actian_Assignment\src\environments\environment.prod.ts
> is part of the TypeScript compilation but it's unused. Add only entry
> points to the 'files' or 'include' properties in your tsconfig.
> ** Angular Live Development Server is listening on localhost:4200, open your browser on http://localhost:4200/ ** : Compiled
> successfully. [HPM] GET
> /maps/api/geocode/json?sensor=false&address=chennai ->
> http://www.datasciencetoolkit.org
dineshk033
  • 31
  • 1
2

Here is another working example (@angular/cli 1.0.4):

proxy.conf.json :

{
  "/api/*" : {
    "target": "http://localhost:8181",
    "secure": false,
    "logLevel": "debug"
  },
  "/login.html" : {
    "target": "http://localhost:8181/login.html",
    "secure": false,
    "logLevel": "debug"
  }
}

run with :

ng serve --proxy-config proxy.conf.json
Patrice
  • 1,404
  • 1
  • 14
  • 27