RESTful and HTTP APIs in Pyramid Transcripts
Lecture: Enabling cross-domain requests with CORS
0:01 Here we are back in our actual server side service code.
0:04 And our goal is to add cors support, that is cross-origin scripting support
0:09 so we could come in here, and actually on every single one of these requests
0:15 set the various cors headers that are required, that is not a good idea.
0:20 We're not going to do that, it's totally not maintainable,
0:22 it's not centralized, things like that.
0:24 There are also third party packages,
0:27 other packages that add core support to Pyramid
0:30 but you'll see that really we just have to add a couple of headers in the right location
0:35 and globally or actually however we want to choose to support it,
0:40 we would support and enable cors, so I'm just going to show you
0:43 the raw way to do it, if you want to grab some other package and that does it as well,
0:46 that's fine, but I don't really think that it's necessary.
0:49 So we're going to come down here
0:52 and we're going to write another function here called allow cors,
0:58 we're going to need the config in order to do this
1:01 so we create this will function, and just like all the mains
1:04 I prefer to have this stuff below main, there we go.
1:09 So what we're going to do is we're going to write a function
1:12 that's going to leverage what are called events in Pyramid,
1:15 and these are basically filters that run before and after various requests.
1:20 So what we're going to do is we're going to hook
1:23 every single request that comes into our site
1:25 and we're going to write a little function that for any request that comes in
1:29 we're going to add the proper headers that allows cors,
1:32 and then let the rest of the app run and it wouldn't even know
1:35 that we've done this trick to add cors to it.
1:38 So in order for this to work, we're going to need to do a couple of things-
1:43 we're going to start by coming over here,
1:45 we're going to write a function that goes to the config and says add a subscriber
1:50 and it's going to subscribe to the new request event,
1:54 so we can notice this is from pyramid.events.NewRequest
1:57 we'll import that at the top, well what is this function?
2:00 This is a function that is going to get called every time a new request comes in,
2:04 so you are going to have to follow me a little bit down the rabbit hole here
2:09 but it's pretty easy once you see it; so here's what that function looks like,
2:13 we want to come in and say add cors headers into this response right,
2:17 so we're going to process that request and as part of the response
2:20 we're going to add these headers, we can do that at the very end
2:23 and it's got to come with the event, the reason we care about the event
2:27 is this has things like the request and response objects on it,
2:30 so this function here will run at the beginning of the request,
2:35 and so what we're going to do is use this function to say
2:38 call one more function that we don't have yet,
2:41 call one more function after our various API calls,
2:45 or view calls if I have already processed it, and at the end add in those headers.
2:49 So we have one more function here that we're going to write,
2:52 and I'm just going to copy this over,
2:54 because you don't want to mess up the headers.
2:56 So here, we are going to say cors headers given a request and a response,
3:00 it doesn't really matter here but the request is we're going to go to the response
3:03 and we're going to update the headers, allow control origin star
3:06 allow control methods and so on, so these are the various things
3:10 and you can of course tune them to the security that you are after,
3:14 but how does this function get called, well, remember,
3:19 the function on line 18 runs at the beginning
3:22 and the goal is to get line 19 to run at the end
3:24 so when I come here I want to say go to the event request
3:27 hey request, when you are done and you're generating the response
3:32 run the function that adds the headers.
3:35 So that probably looks a little g narly, a little intense,
3:38 but here's the thing, you write this code and you never ever think about it again,
3:42 so let's just add a little print here I'll say print adding headers,
3:47 if we run this again, if we just click on it, you can see we got three adding headers
3:52 one of them from our straight request,
3:58 you know calling back into this service, maybe even images.
4:02 So it looks like that's working, let's do one more thing,
4:05 let's go back here and do another request;
4:07 now notice, our headers went from 4 to 9,
4:12 and there you can see all of the headers that allow cors are now added back in here.
4:16 So be very careful, these controls are in here for a reason,
4:24 to reach back to your site and grab some private data
4:26 using a logged in cookie of your user
4:29 that maybe also visited that site, things like that,
4:31 but if your goal is to write just a pure service endpoint
4:36 that anybody can call, then you need to enable cors.
4:39 It looks like those are coming back, now let's go and clear this out,
4:43 let's go and try our other client, this one here;
4:47 so we can come back to this, and run this again,
4:50 and now we had one that had it open right, so if I click this, let's erase that
4:55 do this again, abc oh look at that- 404 not found,
5:00 well why is it not found- it's not found because there's no car with id abc,
5:05 this is super cool, so now let's go and, remember, this list is out of date,
5:10 because I restarted the server, so let's refresh,
5:13 and let's try to get this Opel Signum here with id that ends in f f.
5:20 So when I come over here and paste it, you've got to be very careful
5:23 I got a quote on the end, so if we hit go, it shows the id,
5:29 I am going to get rid of that little alert, that part is working- success,
5:32 see that, success, right, you have an error here but that's just leftover.
5:36 All right, so things are looking great, this is fine,
5:38 let's say if e.error, remember we added that in
5:45 get alert, error contacting service, like so;
5:53 otherwise, we'll just say a generic fail, who knows what happened here,
5:58 like site is down, network is off, something like that.
6:02 So that's the fail, but over here that's done one, this is the success
6:06 so the results remember, we're getting an individual car
6:10 so the results are going to actually be the car,
6:13 so let's say populate data, and we'll pass the car which is the results here,
6:18 I put that in the wrong spot, let's put it where it belongs, all right there
6:22 so when it's done, we're going to populate the car with the results
6:27 and this is when it runs successfully, if it fails, well then we get something over here.
6:31 Ok so the final thing to do is to just populate the results,
6:34 and let's go ahead and write that, let's go over here, grab that and drop that in.
6:40 So no,we don't want to switch languages to whatever that is,
6:43 so we're going to come over here and we want to use jquery again,
6:46 and we're going to go grab all these,
6:49 so we want to basically do like this at the beginning of every one of these
6:52 and then drop off the end, put something there to set the value,
6:57 down here at this part, we want to say .text is going to be car.name, okay,
7:03 in this case it's name, in this case it's price.
7:17 so we can access the values with dot notation there.
7:21 Okay, so, notice we are going to the car detail section
7:25 and we're fading it out in case it was already shown
7:27 and then we're fading it in,
7:30 by default it's not shown initially until you load a car into it,
7:34 so doing a get when things are done successfully, we're going to call this
7:38 otherwise there's some error handling, let's go and try this
7:42 so here we refresh that, click and I got to get rid of this,
7:46 but look at that, there it is, success, we've done it!
7:50 All right, that's pretty cool, so notice there's no errors in the console
7:53 that's really pretty sleek, and the last thing is there's some alert somewhere
7:57 that I still have that I want to get rid of.
8:00 So let's refresh this, get it again, notice we've got this one,
8:03 let's go get a different one, this one's going to be the Astra, find little vehicle
8:07 okay, so let's go check out the Astra,
8:09 this should go to the server, download it as it starts,
8:12 it's going to fade out this part and then when the fade out is done,
8:16 it's going to populate it and fade it in,
8:18 so it should fade away and come in with the Opel Astra, and not the Signum.
8:22 Ta- da, and there it is, okay so what have we learned here?
8:26 We've learned, well jquery still works and makes life pretty easy, right,
8:30 so we come over here and we order the document,
8:33 and we say give me the form, somebody tries to submit it,
8:36 instead we're going to use ajax to do that and tell it don't actually submit the form,
8:39 we can go over here and we do a little bit of grabbing the car id value out
8:43 and use that to build the url that is basically our api
8:48 our schema that we want to talk to here,
8:50 and we use $.get because we're trying to do a get
8:53 we could just as easily do a post and post the data, but we're not there yet;
8:56 if it's done successfully, we populate the results,
8:59 otherwise there's error handling, remember we return like a 404,
9:02 and we put this error, let's try something else,
9:05 like let's change 1 to a 2 and see what we get- fail, okay.
9:08 So if we try to get one where the idea is wrong, we just get a 404,
9:13 but of course, if we get the one that is right, it fades in and everything is good.
9:22 the one thing that maybe was unexpected,
9:26 depending on how much you've done this,
9:28 is we actually had to go over to pyramid and we had to add this cors operation
9:33 or cors configuration on the server side, we had to go to every request
9:38 and say for this request, we would like to add the cors headers,
9:43 now of course, this thing here was the request
9:46 you could look at the request that's coming in and say
9:49 well, only if its /api/something do you want to actually add the cors headers,
9:59 we just wanted to be able to get to /api/whatever right,
10:03 so you could be more discriminating, more careful
10:06 than just throwing it on every single request,
10:08 but we don't really have a use case for excluding it
10:11 so I'm going to put it everywhere, and you guys can adapt this to your situation.