API Design in Node.js, v4 Creating a Custom Middleware
Transcript from the "Creating a Custom Middleware" Lesson
>> So yeah, that's one middleware, we got some other middleware that we wanna use. So we're gonna say app.use. And we're gonna say express.json, like that. This one basically allows a client to send us JSON, basically. Without this, you would have to manually put together the bits yourself to make JSON work, and that would suck, so this does it for you.
[00:00:31] And the last one is express.urlencoded. And I think there's, An option here, extended true or something like that. So urlencoded allows a client to add things like a query string and parameters and it decodes and encodes that properly. Whereas if you don't do that, it kind of just treats everything like a string.
[00:01:05] So I don't know if you've ever seen a query string, right? So in a query string in a URL, you can have gogole.com, then the query string and then it's like, a equals that and then comma, thing equals some other thing, right? URL encoded will take all of this and put it in an object for you.
[00:01:28] So you can just do like query.a, query.thing, versus trying to get it yourself off the string which is annoying, all right, so. Cool, so we'll get those. And then now we're gonna make our own middleware. So let's just make one for fun. You can follow along and make one that I'm making or you can just make your own and have it do anything you want, cuz we're probably just gonna erase it anyway.
[00:01:58] It's not practical, but I want you to get into the feeling of making something. So I'm gonna say app.use here, and I'm just gonna make my middleware right inside of here like this. And I'm gonna say, request response, next, okay? What I'm gonna do is I'm going to augment the request object.
[00:02:16] So I'm gonna say, ooh, req.shhhh secret, Equals doggy, okay? So I'm adding something to the request object, and then I'm saying, yeah, next, I'm going next, right? So any single request that's registered after this middleware was registered will now have access to req.shhhh secret. So I should be able to go into, I'm gonna go all the way into my router.
[00:02:53] I'm gonna go into the slash product one and instead of hello, I'm gonna send back req.shhhh secret, like that. Cuz this should have access to it, because this came after me registering my middleware, so I should have it. Let's see, so I'm gonna stop my server, start it again.
[00:03:17] Go back here, run this code and there you go, I get back doggy. My middleware augmented the request object, it attached some new information to it. And because the handler that I was logging that information was registered after the middleware, it benefited from this middleware happening first. So if I were to put a log in this middleware and then put a log in the handler, you would see that the middleware would log first cuz it was written first.
[00:03:51] Or it was attached to the app first, not written first, but yeah, it was registered first. So yeah, you can make your middleware do whatever you want. And just to show an example of how a middleware can stop the execution of something, instead of doing that, I can just not say next and I can just be like, you know what?
[00:04:15] No, I'm just gonna stop you right now. Status is 401 res.send nope, I can just do that. I don't even need this secret thing anymore because it's not even useful. And now it doesn't matter what request I make, it's always gonna 401 and say no, no matter what URL I put it in, it's always gonna happen.
[00:04:38] So I can go here, and it literally doesn't matter. I can run this and it's gonna say, 401 unauthorized nope. I believe, I can even put anything here and it would say the same thing, right. It doesn't matter because it's always doing it, I never call next, I never move on to the next thing.
[00:04:59] And because this is registered before any other route is registered, none of the routes even get considered because I'm immediately ending the response or the request right here in this middleware. And this middleware is registered globally at the top. So it's pretty powerful stuff, you can do some pretty powerful stuff in middleware.
[00:05:21] I obviously, don't wanna do that so I'm gonna get rid of that, and I'm gonna get rid of that, just go back to message yeah, question?
>> What would happen if next was in app.get right before the console.log?
>> If next was in app.get before the console.log, if you put next here and you said next here, what's gonna happen is there's nothing next for this to go.
[00:05:54] There's nowhere left because now we took what was a handler, which you can think of a handler as like a middleware, it's like the last middleware, it's like that's the end of the road. There's nothing after this, it's like let's follow the stack. Someone makes a request, this gets executed, this gets executed, this gets executed.
[00:06:13] Then it's like okay, what route did you call? You did a get request to slash. Okay, cool, now I'm gonna execute this and then you immediately call next. What's next? There's nothing else left, we don't have any other middleware, we don't have any other route that matches this, nothing would happen.
[00:06:30] You would actually get a hanging server most likely or an error from Express. So yeah, by saying next you are telling Express that this is a middleware, when in fact, this function thinks it's a handler because of how it's behaving. So yeah, you probably wouldn't get the result that you thought.
[00:06:47] Yeah, and then the other thing I want to talk about with the middleware is that you can add as many middleware as you want, you can just comma separate them. You can literally add as many as you want, either by doing it this way or just dropping in a whole array of middleware, all right, you can just drop a whole array.
[00:07:05] Either way, it works the same. The only other thing is that if you need your middleware to take options, kind of like URL encoded right here takes option and how Morgan takes options, you just make your middleware a function that returns a function, right. So you would make custom logger is a function that returns a function, right, and this function has rec, response, next and then you can do your log, I'm gonna cancel that log.
[00:07:39] Hello, from, and then I can have an option you pass in here like message, and I can say hello from message. And then I can call next. All right, so now I have a custom logger. And when I come down here I can say app.use(custom logger), it's a function that returns a function and it takes in a message.
[00:08:04] Or I can say hello from custom logger like that, and that's how you have your middleware take in an argument, you would just do that, it's just a function that returns another function.
>> Can we chain middleware in a nested form?
>> You can chain middleware if you want to but the recommended approach is to compose middleware, either manually putting just them in an array, or there's literally plugins called compose middleware that I used to use.
[00:08:45] I haven't used them in a while, [INAUDIBLE] compose. Compose middleware. Yeah, so you can compose them kinda like this, which again, just puts them in an array anyway, so you could just do it yourself. Cool, any other questions about middleware? Okay, this is also where you would do something like cors.
[00:09:17] So if you wanted to use cors, you can just npm install cors save. And then you can import cors from cors, and at the top of your app, you can say app.use(cors). So what is cors? Cross origin research sharing, basically, it's a thing, browsers are super sketch. They're terrified that they should allow you to talk to other resources.
[00:09:53] So cors is just a configuration that you can put on your server that will tell a browser who or what can access this API. And by default this means everybody can access this API. Doesn't mean you're gonna get access, you've still got to be authenticated but as far as you as a client, you can be authenticated here.
[00:10:12] But you can block on IP levels and some different requests, you can block on all types of stuff. This just means everything and everyone can at least try to get access to this. So cors is a middleware. So when you think of how do I change configuration to my server?
[00:10:28] It's middleware.