This course has been updated! We now recommend you take the Build Progressive Web Apps (PWAs) from Scratch course.
Transcript from the "Fetch & CORS" Lesson
[00:00:00]
>> Steve Kinney: So there's this thing called CORS, and CORS is the first moment that aspiring front end engineers realize that this might not be for them, which is they get some stuff from a server, like their own server. They're yeah, I got I got data file server, this web programming is the best, and then there's, now I'm going to have it hit the Twitter API which is on a different origin, right?
[00:00:25] An origin is basically defined as, it is the same protocol, so HTTP, HTTPS? The same subdomain, and domain, and port, so different ports, or anything along those lines, if you are talking to your own server, thumbs-up. If you're talking to somebody else's server, right, they have to say they're okay, with this, it's kinda like going into your house, it's okay, to go into your house.
[00:00:51] Going to other people's houses when you haven't been invited is not very good, right, and generally speaking, frowned upon. And the same is true with CORS, right, cuz you could theoretically request sensitive data with Cookies and stuff along those lines, and you could do some not nice things.
[00:01:07] So the browser doesn't let you do them unless they have cleared this, right? But there's all sorts of things that you can request from other servers, who amongst us hasn't gotten the URL for a dank meme and dropped it into a message board? Did I just date myself there?
[00:01:24] Okay, so it's just me we can link to images on remote servers. We can go ahead cuz we're lazy just go ahead to the jQuery website, grab that CDN link and drop it into the page, and we've got jQuery, clearly this is not always the case, right? We were surprised when we couldn't hit the Twitter API from our client side app, because we were used to just going on W3Schools, grabbing some markup, and throwing it in our app, and it just working half the time, right?
[00:01:54] So this is new and different for us, so images are fine, right cuz there's no data in there for us to read and work with, it's an image it's a video, all of those things kind of work. So in fact we can theoretically and we'll talk about how to do that get stuff from other domains if they are what we're gonna call an opaque kind of data, right?
[00:02:15] But we can't see into them.
>> Mike: So just to be clear this concept has always existed, opaque responses. And one way you could see it is if you got an image from a server that didn't have CORS headers on this image, you could not then take that image and then write that to canvas and have your program analyse this thing that was shown to the user.
[00:02:42] So it's almost like the users are allowed to see it, but your code is not allowed to see what was shown to the user.
>> Steve Kinney: For safety reasons.
>> Mike: For safety reasons, and here is to reason why, cookies so by default, fetch aside, by default, with AJAX and requesting images and things like that, like cookies are sent along with each request.
[00:03:06] And so, if you were logged into my site and cookies are the means by which I authenticate and authorise people, now all I need to do is have an image of your user profile, or something like that, and I might be able to tell, are you an admin user, or are you a regular user?
[00:03:21] I could have some AJAX that would be sending requests out, to transfer funds from your bank account to another one. And the fact that you have a cookie for that domain, and that's the way that that authentication works, that can happen. Now those responses are opaque to us, we can't know for a fact whether it completed, but we can certainly do it.
[00:03:50] And that's why CORS headers, it is important if you're a front end developer to know what your doing here and don't set them up the way this example project is set up, which is a wildcard course header, it's extremely permissive, right? The consequence of this for a real app would be like I could send a link to Steve and trick him into clicking on it, and he would order three tons of diapers to be delivered to his house in two weeks.
[00:04:21] So definitely important to pay attention to and learn more about it but it is sort of been rethought and fetch and they got a second chance to define what are the defaults, what should we allow, and now like have reason in this world, and not only dangerous things.
[00:04:40]
>> Steve Kinney: Yep, it's a real problem for us at SendGrid, too cuz we have a product where they could upload an HTML file that is their email, right? An attack vector would be, hey, if we didn't sanitize all that stuff they could upload executable JavaScript, call up support that has advanced permission.
[00:04:56] Have that send AJAX requests with the cookie information and stuff, along those lines, right? So it's a very real problem, with XMLHttpRequest we were only getting things that were not opaque. So we never thought about opaque things in terms of these Asynchronous network request. They always exist to this Mike said, but now it's the first time that we can actually fetch that, one an unintentional pun.
[00:05:17] So now the time we can get those things as well, so here's an example of how that would work with an image.
>> Student: So for each fetch request now do we have to set course headers?
>> Steve Kinney: If it's your own, you do not, if it's something you expect to be opaque, you need to say that.
[00:05:35] Which we'll take a look at in one second. So, here I'm building a thing where I'm going to go get Mike's head shot from the Frontend Masters' website, as you do, I call it Wednesday.
>> Mike: Everybody does.
>> Steve Kinney: Everyone does, who amongst us was not doing that at lunch?
[00:05:50]
>> Mike: It's the retina headshot too.
>> Steve Kinney: Yeah, it's the retina one, I got it at 2x, cuz I'm not sacrificing quality here. So I'll go fetch this URL, and then when I get the response, I'm for some reason going to console log an image, because I was not feeling eventful for a thing that wasn't going to work anyway.
[00:06:06] So you could see that I'm apparently doing it from the dinosaur website, and the FrontendMasters website is like, excuse me, you don't have the keys to this house, please step outside. You cannot fetch this image, because we didn't set any of those, we didn't say, hey, take it opaque, we don't have the CORS permissions, so on and so forth.
[00:06:29] But if I went to the Nodejs webpage, I just put an image tag in there, and I set the source attribute to the same image, it would totally work. So why can't I do this in a fetch? I can, right, I just have to say that the mode is no-cors, right?
[00:06:44] And that will give me an opaque version, right? I couldn't request JSON like this, along those lines but things I will get a version that I cannot see into, right? We will say, that lost the slide in there. Yeah, the comment's right there, I'm just not looking, you can see when I say console.log(resource.type), it'll say opaque.
[00:07:05] Which means I can put it into an image tag, but I cannot read it or do anything with it. I can use it as if it was an image with a source attribute, right? If I were saying why can't I do that, I can, but that's what I can do, cool.
[00:07:20] And so for the most part, in a lot of our usage of fetch, we're gonna send a string as a URL, we can send this object with some options in it, we can also build a request ourself, right? So we can make a new request object with a string, and an object full of options, right?
[00:07:41] You're like, why wouldn't I just do that the way I was doing it before, noted. We can then take that request, and we can pass into the fetch, and it will work exactly the same way, right? So and this is the same example again with my no-cors in there, I can create the request, send it through, I'll get the opaque response.
[00:08:01] I put this slide back up because I want you to meditate for a second on the feeling you have in your heart of why. Why would I create a request object that has the same things that I would have passed into fetch? I'm not gonna answer that question for you just yet, I'm just gonna ask you to think about it for a second, there is this idea of a request object.
[00:08:22] It's not just we pass an a string, and we pass in an object full of options, but when we do that, especially what happens under the fetch hood, is it makes one of these request objects, and these request objects are a thing, they are a thing that will show back up, to kinda foreshadow how the story goes.
[00:08:40] Show back up later in our time together, to lend a helping hand. But right now, it's that kind of, the rule from storytelling don't feature a gun on the like mantle if it's not gonna get used to the end of the book. And if you do it better get used by the end of the book.
[00:08:56] This is our like foreshadowing for a friend that will return, when we're hanging out with pit of sharks of sharks that really just makes a whole bunch of movie metaphors together. Is after lunch, it's what you gotta do.
>> Student2: At least the sharks aren't jumping.
>> Steve Kinney: What's that?
[00:09:11]
>> Student2: So at least the sharks aren't jumping.
>> Steve Kinney: At least the sharks aren't jumping cuz jumping sharks are dangerous and they I got it [LAUGH] walked into it? Cool so here we can also create headers if we wanted to like set contact link, we can like append different things to the headers in our request when we get a response object, we can read headers.
[00:09:31] So there are things that we might want to do with this object, if this hurts your feelings, you can also pass it in as an object and it will kind of create the headers for you the same way. So we've talked a lot about making requests, and which raises the question of what about responses, right?
[00:09:48] Cuz ideally the request are only a means to the end we're only making the requests cuz we want the response, right? So we've kind of repeated repeatedly is that it works with more than JSON XML and we do again need to talk about what we're dealing with. In this case we'll take JSON, we have a bunch of other options, right?
[00:10:10] We saw blob, JSON is like please parse it as JSON, right? Text is, it's text, form data is kind of cool, form data works for both requests and responses, let's say you have a form on your page. You can actually say new form data and give it the DOM node that has the form and it will get you all the data and you can send it along to the server.
[00:10:32] If you got back to send anything back to the server you could theoretically pass it back into data that you could use. All right, quick word and this is again something that will appear later, is for a number of reasons, you can only read the data out of a request or response once, right?
[00:10:51] After that it's okay I don't really need to hold on to the same they've done the thing with it, I can let all this information go. Which most of the time is exactly what we want, some of the times you're like, hey actually I read it, I'm gonna need to do something else or I think I'm gonna need to do something else, we can clone it.
[00:11:09] We'll talk a little more about this later, but first what we're gonna do is we're going implement some fetch.