When we first try to use a local server for our data in development, we get a rude error in the console and nothing works. What is that and why are we getting it? Well, even though both the server and the client will eventually be on the same domain in production, we're getting CORS (cross-origin resource sharing) errors in development. That's because we're running the server and the client on different ports. We can fix this by setting up the Angular CLI to proxy all requests to the API for us so they appear to be coming from the same origin.
Instructor: [0:00] I've added a simple Express server for the habits. It's over at logo host 3001/api/habits.
[0:10] We'd like to move our habits from the service here, just being hard-coded in the service, to actually going and getting them from the little Express server that I've got. Let's do that.
[0:23] I'm going to first go over to app.module.ts. Then in my imports array, I need to add HttpClientModule. Your editor may help you import this. If it doesn't, we're going to need to import HttpClientModule from angular/common/http.
[0:47] Now, over in the habits service, I'm going to go down into our constructor here. I'm going to type privatehttp. That's going to be of the type httpclient.
[1:00] Again, we can see if our editor will help us. We can import httpclient from angular/common/http. That's up at the top of our file now. Just move that up a line. Great.
[1:13] The next thing we need to do is replace our little return of our array here with an actual GET call. To do this, I can delete this and say return this.http.get. I can put in our URL, which is going to be http://localhost:3001/api/habits.
[1:36] You'll notice that it's giving me a red squiggle here and it's because we haven't specified a type. With the HTTP GET, what we can do is specify a type right after the operator name. I can add a type here and say habit array. When I save it, everything is good to go.
[1:54] Theoretically, this should work. Right? If I go over to the browser and go to the tab with localhost:4200 and refresh the page, you can see that everything's not OK. We're getting this error over here.
[2:08] The error is a cross-origin policy error. Meaning, that we're trying to hit localhost:3001 from localhost:4200 and the server is not set up to allow that kind of cross-origin request. We could fix that on the server side.
[2:26] Most of the time this comes up, it's because we're doing development on a local server, but that then, when we deploy, the production is going to be on the same domain. We won't have this problem anymore.
[2:37] This is a big hang-up when it comes to developing applications. Luckily, there's a way we can fix this by adding a proxy to our Angular application.
[2:46] Let's go back over to the code. The first thing we need to do is open the file explorer. In our source file, I'm going to create a new file.
[2:54] I'm going to call it proxy.conf.json. Inside of that file, I'm just going to add an object. The first thing we're going to do is specify the URL that we're going to reroute, basically, that we're going to proxy to.
[3:09] I'm going to say /api. Then I will define an object for that. We're going to give that a target of HTTP localhost 3001.
[3:20] That way, any URL that starts with /api will just be sent over to localhost 3001. Then lastly, we just need to give this a property called secure that's going to be false.
[3:33] Now we have our proxy config, but the Angular server doesn't know anything about it. We need to go into our angular.json. That's where we configure anything having to do with the COI. In our angular.json, we can scroll down into this architect section.
[3:50] Down where we get to serve, there should be an options object. If there's not, then you can go ahead and create it, but there should be one already. Inside of that, we can add an option called proxy config, and point to source/proxy.conf.json.
[4:09] Lastly, we just need to go over to our habit service. Instead of having localhost 3001 there, we're just going to have /api/habits. We need to restart the client and the server in order to make these changes take effect. I'm going to quit out of the client and the server and I'm going to run NPM start.
[4:31] In this example, I've got the NPM start command set to start up the server and also run the NG serve command. We'll wait for that to bundle real quick and we'll hop over to the browser. You can see that now we have our habits loading on the page.
[4:49] One thing that's interesting here is if I inspect the habits call here, you can see that we called localhost 4200/api/habits and yet when we look at the response, we get our habits back from the server. This is how the proxy worked, where it passed through the call to /api/habits to our Express server.
[5:14] Because we have that proxy, we no longer get those cross-origin request errors that we were getting before. This is a really handy trick to use when you're working in development on a server that you need to run locally on a different port but then in production will end up being on the same domain, so you don't want to have to go and swap up a bunch of URLs all the time in your services.
Hi Igor,
"I've added a simple Express server for the habits." What does this mean? How do I do this?
I moved the habits from just hard-coded in a service to a small Express server in order to demonstrate a CORS error. It’s not a step for you to have to repeat, it was just setup for this lesson since CORS errors happen when the client and API are not on the same server. You can see the code for the server here:
https://github.com/samjulien/egghead-angular/blob/master/server/server.js
Hope that helps!
Hello Sam,
Thanks for the quick response!
I did not get about which server you were talking about before. Now it works for me :)
Cheers!
"I've added a simple Express server for the habits."
What does this mean? How do I do this?