This course has been updated! We now recommend you take the API Design in Node.js, v4 course.
Transcript from the "Exercise: Middleware" Lesson
[00:00:00]
>> Scott Moss: So we've got Lesson 4 here. So one thing is we've got some global middleware that we need to set up. Remember we're reusing that request.body, right? I was like that's gonna be a test on some middleware later on. Yeah, by default, Express knows nothing about JSON. It has no clue, it doesn't have any way of how to handling it.
[00:00:15] But there's some special middleware we can use that does allow us to parse JSON, parse URLs. Do all that stuff for us so we're gonna use that middleware cuz we don't want to do it ourselves. And we want that to happen on every single request in our app because our whole app is gonna be responding to in JSON so we're gonna set that up globally.
[00:00:31] We can also set up login globally like hey, I want to cuz right now when I start this server. And I make a request to it. I don't know if somebody made a request but I'm not logging that request anywhere. It would be pretty great to be able to log every single request that came in.
[00:00:49] That'd be really nice to have that. That's a API 101. Some logging for your request. So we want to see that and that also needs to be global. So if we look inside of this middleware file.
>> Scott Moss: Here you can see there's a function called set up global middleware.
[00:01:06] And it takes in the app. What we want to do here is we want to set up some middleware to do some logging. That's optional but the one we absolutely have to do is set up JSON parsing. And we're gonna use this body parser. So we're gonna go get body parser.
[00:01:23]
>> Scott Moss: There's this thing in here called JSON, we need bodyParser.json. And then we also need URL encoded. So we need both of those, and if we just take an example of how to use it. This is why we chose express, because this thing works for express, almost everything works for express/connect as you see right here.
[00:01:48] Express/connect because express is based off of connect, but basically we need to set up both of these middlewares. We need to set up bodyParser URL encoded, extended ,this but true. Then we also need to set up bodyParser.json. We need both of those middleware on our app. So knowing this right here.
[00:02:06] Looking at this. We need to do that in here,
>> Scott Moss: On our app. So and how do we set up something? What's the method that we use on the app or the router? That we can mount anything on.
>> Speaker 2: Use?
>> Scott Moss: Use, exactly. So use, use, and set up that bodyParser for JSON, and URL encoded.
[00:02:30] And then what we also have here is some authentication. So we're not gonna walk through building custom authentication, but it's already done. We're gonna attach it to our routes, though. So I already have that done, you can go look in modules/off and there's a whole bunch of stuff in here with JSON web tokens, some crazy stuff.
[00:02:51] And we're gonna go walk through it when we get done on what's going on. But it's heavily commented and it tells you exactly what's happening here. But this is also middleware and we're gonna set this middleware up to protect our API. So you can't access /api without being authenticated.
[00:03:05] So that's what this is gonna do. So we need to set this up as well, and the middleware for this, we need to use the decodeToken function from this file. So decodeToken is exactly, it sounds like it's gonna decode the JSON web token. And we wanna do that on every single route to /api.
[00:03:26] So think in your app where there's a place where we can set up some function that runs for every other function for /api. Then you wanna place decodeToken in there, just like that. You have to invoke it, cuz it's a function that returns a function. Every other middleware doesn't return a function.
[00:03:43] This one returns a function so we got to invoke it just like that. That's a side of auth. And then you have this custom error handler that does absolutely nothing. And like you said we need to set this up to handle any error that's passed into next. Eventually, when you pass an error to next it just bubbles up.
[00:04:03] No matter where you pass it in, it's gona go to it's router, do you have an error handler? Nope. Do you have an error handler? Nope. Do you have an error handler? Nope. Okay, I'm just gonna blow up right here. Stop. This is gonna check every single level until it gets to the route app.
[00:04:14] So we should set up a error handler for api, and the syntax for that is express passes in the errors in the first argument. That's how it knows, if this is the error handler, it checks the arity or the signature of your functions. if it detects that there's an error here, it's like okay, this is the error handler, that's how it does it.
[00:04:30] So all you do is register this, using the same .use method. And then inside of it, you can do whatever you want. I would say, probably log the error so you can see what it is on the server. And then send back a status of 500 or whatever you wanna send back.
[00:04:43] But normally, what you would do is, you would throw custom error messages, and then inside this function, you'd be, if it's this error, send back this status code. If it's this error, send back this message. If it's this error, call this service. That's what you would do in here.
[00:04:59] You could do anything, async, you could do whatever you want. But we're just throwing generic errors. We don't really care. But that's what you do in production. You would check the metadata on this error right here to determine what you need to do next. But ultimately, no matter what you do you have to send a response otherwise it's gonna hang.
[00:05:14] So this has to send a response some way or another. So I bring up the test or the challenge.
>> Scott Moss: And you're gonna set up global app middleware. You're gonna add the router based middleware, which is the error handling. And then you're gonna set up auth middleware where needed.
[00:05:38] So global middleware, the error handling.
>> Scott Moss: And then set up the auth middleware. If you don't get to auth middleware that's totally fine, you don't have to set it up but I think it's a good exercise. So it is-
>> Speaker 3: What can you define where needed?
>> Scott Moss: Where do you think it's needed?
[00:05:59] It'll work the same no matter where you put it.
>> Speaker 3: User create. [INAUDIBLE] it depends on [INAUDIBLE] right?
>> Scott Moss: Yeah, so I would say for now just protect the whole /api.
>> Speaker 3: Okay.
>> Scott Moss: Obviously, if you actually had your sign up ability protected by authentication nobody could ever sing up, right?
[00:06:18] So I would say, just assume that that create method is not for signing up. And it's like your an admin creating users, or something like that, not for sign up. That's a whole another route that I think is already in the app. Let me check. Yeah, there's a sign in, sign out flow already in there that's completely separated out.
[00:06:33] But yeah, that's something you don't wanna do. So you gotta be careful where you put these middleware because anything that belongs to that mount will be affected by that middleware. So, if you accidentally put authentication on your sign up flow, nobody would ever be able to sign up because they need to be authenticated to sign up.
[00:06:50] So that would suck. So I would say just lock down the whole API route, set up that error handling, the function is already there inside of modules errorHandling, there it is. And then you also need to, inside the middleware file here, you need to just attach the body parsers, that's it.
[00:07:12]
>> Scott Moss: So you'll know this works when it doesn't break. [LAUGH] And you can actually send JSON. So if you do a post, you can do some logging in the controllers, and you can find out, let me see where erectile body. If you logged erectile body, and it's exactly where you said, then it totally works.
[00:07:28] And you can test that the authentication works is because, I don't want to show it, but if you put the authentication in there, you'll just get an error back immediately, you're not authenticated. It'll immediately say you're not autenticated. It won't even execute your controller, it'll just break.