‫In this lecture we're gonna implement something
‫called CORS, which means cross-origin resource sharing.
‫And this is a fundamental feature in any API,
‫but I can only show you this now
‫that the application is actually already deployed.
‫Now what actually is cross-origin resource sharing,
‫and why do we need to implement it?
‫Well let's say we have our API
‫here at natours-jonas.herokuapp.com/api/v1,
‫and so on and so forth.
‫And then some other website, for example at example.com,
‫is trying to access our API.
‫So basically trying to call this URL here.
‫And this is then called a cross-origin request,
‫because herokuapp.com is a different domain
‫than example.com, and so therefore if example.com
‫is trying to access herokuapp.com,
‫it will be a cross-origin request, all right?
‫Now usually cross-origin requests are not allowed,
‫and will by default fail, unless we implement CORS,
‫so cross-origin resource sharing.
‫And since we want to make our API available to everyone,
‫we definitely need to implement that, all right?
‫Now let me actually show you how this would fail.
‫So let's grab this URL here,
‫and open in your tab and then inspect.
‫And so basically let's do an HTTP request to our API
‫here from the console, okay?
‫Because basically when we do it from here,
‫it will also be a cross-origin request.
‫So let's just say const x equals await,
‫and then let's use the fetch JavaScript function, all right?
‫So fetch is basically a function
‫that's a bit similar to the Axios library
‫that we used in our code,
‫but it's native JavaScript in the browser,
‫and so we can just use it here in the console.
‫So let's say that we want to do a request
‫to our tours API like this, all right?
‫So if we try this now, let's see what we get.
‫And indeed we get the error
‫that trying to access this path here
‫from this other origin has been blocked by the CORS policy.
‫And so that is exactly what I said before.
‫So that by default, a cross-origin request
‫will always be blocked.
‫Now by the way, this only applies to requests
‫made from the browser.
‫For example, using the fetch API here,
‫or something like the Axios library
‫that we used in our code.
‫And so that means that from the server,
‫we will always be able to make cross-origin requests
‫without any problems.
‫So there are no restrictions on the server,
‫but really only on the browser,
‫for security reasons basically.
‫Oh, and also in order to be considered cross-origin,
‫a request might come from a different domain.
‫So just as we saw in our first example here,
‫but also a different subdomain, a different protocol,
‫or even a different port is considered
‫a cross-origin request.
‫So for example, if we had API.natours.com for our API,
‫and would then do a request from natours.com,
‫that would then also be considered a cross-origin request,
‫and would fail, okay?
‫But again, since we want to allow other websites
‫to basically access our API,
‫let's now implement cross-origin resource sharing.
‫All right, and so we do that once more
‫by installing an NPM package.
‫So NPM install, and simply CORS.
‫Then here we require that package.
‫And once again, this CORS here
‫is a very simple middleware function
‫that we now need to use for our application, all right?
‫So let's do that here, and why not do it
‫right here at the top?
‫So let's say implement CORS.
‫And so app.use, and then call CORS,
‫which in turn will return a middleware function
‫which is then gonna add a couple of different headers
‫to our response.
‫And since all this middleware function here does
‫is to basically add some specific headers,
‫maybe you're thinking "Why we are using
‫"yet another NPM package?"
‫Well, let's just actually take a look
‫at the code of this package.
‫So GitHub CORS, so once more,
‫that's usually how I find documentation
‫or the source code itself for my packages.
‫And so let's go here into lib,
‫which usually means library.
‫And then all we really have here is this index.js.
‫And so you see that here is all the code,
‫and basically what you see here
‫is that it simply adds this header here
‫with the value of basically everything to the headers.
‫All right, so then you have a couple of other headers,
‫Access-Control-Allow-Methods, allow-credentials,
‫and that's for different cases.
‫All right, but so you see that it's really
‫just all about headers here.
‫So yeah, maybe we could just add these headers by ourselves,
‫but why would we actually do that?
‫I mean we could of course,
‫in order to fully understand really how it works,
‫but in Node.js and Express development,
‫in the real environment you usually
‫will not want to reinvent the wheel,
‫and instead, whenever you can,
‫use packages that other developers have written for us.
‫So really we just focus on making our application work,
‫instead of rewriting code that other developers
‫have already written for us, all right?
‫So we can take a look at all of this,
‫but as I mentioned, we can also just go ahead
‫and actually use this, all right?
‫Anyway, this is how we enable cross-origin resource sharing
‫for all incoming requests.
‫So basically for our entire API.
‫But let's say we only wanted to enable CORS
‫on a specific route.
‫So we could use that as well, so let's just copy this.
‫And so if we only wanted to enable CORS,
‫let's say on the tours, well,
‫we could simply add that here into this middleware stack.
‫All right, but again in this case
‫we really want to allow it everywhere.
‫So as we saw previously in the GitHub code,
‫what this does is to set
‫the Access-Control-Allow-Origin header to everything.
‫And so what this everything here means
‫is for all the requests no matter here they are coming from.
‫And so this is ideal for allowing everyone
‫to consume our API.
‫But now imagine the case
‫where we don't want to share our API,
‫but we want to be able to have the API on one domain,
‫or even one subdomain, and then have
‫our front-end application on a different domain.
‫For example, let's say, so as I mentioned before,
‫we had our API at API.natours.com,
‫but then our front-end app at natours.com.
‫And so in that case all we want it to do
‫is to allow access from this origin here, basically.
‫And so in that case we would use app.use,
‫and then CORS, and then pass in an object for the options
‫where we'd specify the origin
‫to let's say HTTPS://www.natours.com.
‫And so this is just an example
‫in case we had our front-end at natours.com, all right?
‫And so again, with this we would only allow
‫this URL basically, so this origin,
‫to create requests to API.natours.com.
‫And of course we could also allow other origins.
‫For example, only for some specific websites
‫that we want it to allow, okay?
‫But again, in this case we really want to allow everyone.
‫Okay, so this was the first part of enabling CORS,
‫but actually that's not all,
‫because right now this will only work
‫for so-called simple requests.
‫And simple requests are get and post requests.
‫On the other hand, we have so-called non-simple requests.
‫And these are put, patch and delete requests,
‫or also requests that send cookies
‫or use nonstandard headers.
‫And these non-simple requests,
‫they require a so-called preflight phase.
‫So whenever there is a non-simple request,
‫the browser will then automatically issue
‫the preflight phase, and this is how that works.
‫So before the real request actually happens,
‫and let's say a delete request,
‫the browser first does an options request
‫in order to figure out if the actual request
‫is safe to send.
‫And so what that means for us developers
‫is that on our server we need to actually respond
‫to that options request.
‫And options is really just another HTTP method,
‫so just like get, post or delete, all right?
‫So basically when we get one of these options requests
‫on our server, we then need to send back
‫the same Access-Control-Allow-Origin header.
‫And this way the browser will then know
‫that the actual request,
‫and in this case the delete request, is safe to perform,
‫and then executes the delete request itself, all right?
‫So let's do that and say app.options.
‫Okay, and so again this is very similar
‫to doing app.get for example, or .post, .delete, .patch,
‫and all these verbs that you already know.
‫So .options is not to set any options on our application,
‫it's really just another HTTP method that we can respond to.
‫And so again, in this case we need to respond to it
‫because the browser sends an option request
‫when there is a preflight phase.
‫So we need to define the route
‫for which we want to handle the options.
‫And once again, we will do this on all the routes, okay?
‫And then basically the handler,
‫which once more is the CORS middleware, all right?
‫And once more, we could of course only allow
‫these complex requests on just a specific route.
‫For example app.options,
‫and let's say only on api/v1/tours/:id,
‫like this, okay?
‫So let's say that someone does a delete or a patch request
‫for one of the tours, and only there
‫we allow a preflight phase.
‫And so basically only on this route here,
‫one of these complex requests can be done.
‫So in this case here where we only had this options route,
‫only the tours could be deleted or patched
‫from a cross-origin request, right?
‫And none of our other resources, all right?
‫But once more, let's allow all of them, okay?
‫But I will still just leave this here for you as an example.
‫Okay, anyway, that's all we really have to do
‫in order to enable CORS for our application.
‫And so let's now redeploy the application
‫by pushing it again to Heroku.
‫But before we do that, I actually want to change
‫something here in our package.json.
‫And that is this node engine here.
‫So sometimes it can create some problems
‫when we specify the version like this.
‫So basically allowing versions to install
‫that are greater than the version
‫that we're currently running.
‫And so what I want to do here
‫is to say that it should only install version 10,
‫and not a version after that.
‫So I do it by saying this caret symbol here,
‫and then version 10.
‫And so once more, that's using the semantic versioning,
‫and so just like here.
‫Which remember, means that NPM is allowed
‫to install any of these subversions or patch versions,
‫but not bump up to the next major version.
‫And so here what I'm doing is the same, okay?
‫So I'm currently running Node version 10 something,
‫and so you can confirm yours by typing node -v,
‫and so you see that I'm on 10.11 right now.
‫But probably when you're watching this course,
‫you're gonna be at least at version 12, maybe even 14 or 16,
‫depending on how long in the future you are, all right?
‫And don't worry of course,
‫everything that I show you here in the course
‫should still be working fine
‫for whatever Node version you're using.
‫So if you're using version 12,
‫then please go ahead and put the 12 right here, okay?
‫Anyway, let's now add all the modified files
‫to the staging area, so git add all.
‫And then commit them with a meaningful message,
‫so implemented CORS.
‫And then get push Heroku master.
‫And now that takes some time,
‫so I'll see you when that's done.
‫So the application is successfully deployed now,
‫let's just quickly reload here
‫just to see if it's still working, and indeed it is.
‫And so now to prove you that it works differently with CORS,
‫if we do this request here again
‫it should then actually work, right?
‫So let's try that, and here we go.
‫No error this time, let's check x here.
‫And indeed, it looks like there is something here.
‫So you see that actually the response is of type CORS,
‫we have our headers, well, I cannot really see them here.
‫That doesn't matter, here we also have
‫just a readable string,
‫but again that's not important at all.
‫What matters here is that now we are able
‫to perform cross-origin requests, so that's fantastic.
‫Now let me just also show you the actual headers
‫that the CORS package adds
‫by just doing some request here in Postman.
‫So in production, let's now send it.
‫And so here you see in the response headers
‫that we actually have this Access-Control-Allow-Origin
‫set to everything, okay, great.
‫And so this is how you actually implement
‫cross-origin resource sharing in your own application.