
API Design in Node.js, v3 Router & Sub Routes
This course has been updated! We now recommend you take the API Design in Node.js, v4 course.
Transcript from the "Router & Sub Routes" Lesson
[00:00:00]
>> Scott Moss: And then for abstraction, which is what we're gonna be doing here, is that we can create sub routers. So everything up to this point, we've just been creating, everything on the router level. But because we have, we're gonna have many different resources for our REST API, we can create sub routers, which allows a different part of our API to have its own router, its own middleware stack.
[00:00:20] It's own everything and whether it's an opt in to inherit from a parent router or not. So it's, you can think of it as just a nested router. Or, if you think of routes as a tree, this is just a branch on that route, basically. It's just its own branch.
[00:00:35] It stills comes from the tree, but it's got its own branch, its own rules, its own everything. So Express allows you to do that very simple. So that allows you to, separate your code and abstract it out to where like it's pretty neat. And you can collocate code in certain places if you have a folder with all your different resources, which is exactly what we're gonna have.
[00:00:52] So it allows that to happen versus putting every single thing in one file, in one route where it can get pretty, I mean you might have a 500 line file full of routes, which is kinda scary. So this helps prevent that.
>> Scott Moss: So what that looks like is, using Express we can make a router.
[00:01:12] So we can just say, I'm gonna make a router, and to do that, you just use Express.Router with a capital R, and that makes a router. Now just how controllers and middleware are basically the same thing except for the intention. The router and the app are, when it comes to routing, they're basically the same thing.
[00:01:34] A router can't do things like, listen on a port and stuff like that. But as far as registering routes and verb combinations, the router can do the exact same thing as the app can. So just to show you, so if I come down here and I'm just gonna make some routes on the router.
[00:01:53] So I'm gonna take that router, I'm gonna say router dot, let me just clean this up a little bit.
>> Scott Moss: Go away. There we go. So I'm gonna say router.get, slash me. And I'm just gonna send back some json here.
>> Scott Moss: Or I'll also say, send. Cool. So I said router.get/me.
[00:02:29] Right now, the router's disconnected. All I did was make a router, and I registered a route on it. It won't actually do anything. I can't actually go to this route, because I have to register this router with the route router, which is our app. App is always a route router, so right now, it's just a leaf floating somewhere, but now, I need to attach it to the tree.
[00:02:48] So how do I do that? I need to register it with the app somehow, and the way you do that is, just like middleware, it treats it exactly the same way. It's called mounting, so now, I just need to mount this router on this app somewhere. And I can do that pretty easily just by saying, app.use which is saying, hey, I wanna use this middleware for everything.
[00:03:13] There's no route combination here, this is for every for every path, I wanna use this middleware. So I can do that. And I could just pass in a path here. So I'm gonna say app.use. I'll just say ('/api'). So if a request comes in for any verb that has /api on it, I'm gonna use this router that I created.
[00:03:35]
>> Scott Moss: So it's gonna delegate to that.
>> Scott Moss: So if I go here and I say /api/me and I run this, I'll get me hello.
>> Scott Moss: Which is exactly what's here. Because I went to /api, right? And just to test that, if I don't go to /api me, I just go to me, I get a 404 because there is no such thing as /me.
[00:04:07] There's only /api/me.
>> Scott Moss: Cool on that?
>> Scott Moss: Any questions on the subrouting? That's basically it, and like I said, a router has the same thing as app does, so if I wanted to register middleware on the router, I could do the same thing. I could do router.use here.
[00:04:32] I could do all of that, it's the exact same thing. Any questions on that?
>> Speaker 2: So why would you use router over app.get?
>> Scott Moss: The reason you would use router is if you just didn't wanna put everything in the same file, honestly. Or if you had, if some part of your API had its own set of rules that you wanted to isolate just for that part of the API, then you would make another router for it.
[00:04:56] For instance, let's say you had an API that serves static assets that also serves json, it served this proprietary machine learning thing. And the json one had a different authentication strategy than a machine learning one did, right? So if you added the authentication strategy as middleware to the route, it'll lock the whole API down.
[00:05:17] That's not what you want, you need different authentication strategies for different things. So you would make another router for this part of your API, for the json, and register it's authentication strategy on it's middleware and then the machine learning one would have it's authentication strategy on it's middleware, and they don't conflict with each other.
[00:05:34] So it's like I got separate rules for separate things, yes?
>> Speaker 2: And now, how can we, I'm just saying, if you have lots of pieces combining those routes, how can we, I mean, how can, from any point, can we look at the routes that are?
>> Scott Moss: In what file?
[00:05:47]
>> Speaker 2: [CROSSTALK], yeah.
>> Scott Moss: You can't, so you lose out on that, right?
>> Speaker 2: Really?
>> Scott Moss: Yeah, so if you have, right, if you take all these out, and you put them in different files, then, there's no way to look at all of them in one place. So you lose out on that.
[00:05:59]
>> Speaker 2: No, I'm saying if there's a big application. There's only one part and you wanna make sure you're not conflicting with anything. It's just like, okay, at this point, what kinda routes are there?
>> Scott Moss: I said you mean. There's no way a doing that either.
>> Speaker 2: At them.
[00:06:10] Yeah Like even debug?
>> Scott Moss: No, there's no way because as we saw, it's just whichever's first that is going to happen, right?
>> Scott Moss: So the only way you would run into a problem is if you started getting unexpected things like well, what is that, that's not what I expected.
[00:06:28] It's hard to debug because it'll just goes to the next one.
>> Speaker 2: It just goes through all those trees right?
>> Scott Moss: It just goes through the whole tree until it finds a match. The only time it'll error is if there is no match. You'll get a 404, like there's no match, I'm a 404 here.
[00:06:40] But yeah, if you got this crazy business logic and you eventually have something overriding, then yeah. I've never ever run into that problem.
>> Speaker 2: Yeah it shouldn't happen, but.
>> Scott Moss: The way you can avoid it is because eventually you have to tie the routers back to the application somewhere.
[00:06:57] You have to tie them back, right?
>> Speaker 2: There has to be some other point that actually has the information on it.
>> Scott Moss: Right, so like right here I have the app.use /api. That's the mount path. All I know is, I just don't do this again. I just can't use /api now.
[00:07:10] If I do /api and put another router here then I'm gonna have unexpected problems. So I know now I'm gonna have to put something different here. And then now it doesn't matter. If this router had /me and another router that I put here also had /me, they'll never conflict because they have different parent paths.
[00:07:25] They have /diff and /api. So this basically, where you mount it is kind of where you get rid of that problem.