 Using Express middleware functions. Let's take a look at what middleware functions are in Express. There are a couple of types of middleware functions. One of these is the application level. Here it has the router, have an error handling, built-in, and third-party. So there are many types of third-party middleware functions. You can actually download and install and use it, and then load in your app at the application or the router level. There are three built-in functions in Express. These are the static JSON and URL encoded. And for application, router, and error handling, you have the ability to create your own custom functions to handle any of these middleware. So let's take a look at the anatomy of a middleware function. So middleware functions are typically just callback functions that act on one of the HTTP methods or on a route if applicable. So they can execute any code, make changes to the request and the response objects. They can also end the request-response cycle by issuing the .ender command. Or they can call the next middleware in the stack if, for example, this function does not end the cycle. And usually you want to do that. So let's take a look at an example of how middleware functions work. So middleware functions have access to the request object, the response object, and the next function in the application's request-response cycle. Now if the current middleware function does not end the request-response cycle, it must call the next function to pass control to the next middleware function. Otherwise the request will be left hanging. And you always want to avoid that from happening by terminating the request-response cycle like you see here. That's really important. Now these two functions can be combined together forming what's called a sub-stack. And this is a very common feature used in node applications, especially in error handling. I quite often enthralled the program and in other express application as well. So let's take a look at the application-level middleware. So these are functions that are bound to an instance of the app object by using the app.use and app.method functions, such as get, put, pose, and so on. So this first example here shows an application-level middleware that is bound... I'm set again. The first example here shows an application-level middleware that is not bounded to any path and it will execute for each request. The second example here is mounted on the course-slash-id path and it will execute only if the matching path is triggered. And the third one you see here uses the get method and a middleware sub-stack that handles a get request to the course-id path. As you can see, the first one did not end the cycle, so you must pass that to the next function to end the cycle there. That's really important. The next one is the router-level middleware. This one works exactly or almost the same way as the app-level middleware using the use and the HTTP methods as well, except it is bound to the instance of express.router and not the express app. So the code is very similar. The only difference is just we switch from app to router. That's all. So you might have a question like, why do you use router-level middleware if it's identical to the application-level middleware? And that's a great question. So there are two group reasons why. One is if you remember when we instantiated the express application, we used the express constructor to create the HTTP server that listens to requests, right? So we can also instantiate a router object using the router constructor. However, only the app listener, app object can listen to requests and the router does not and cannot do that. So the router can act very similar to the app object but only responds to requests that is sent by the app or the object that listens to requests. The second reason is because it's primarily for code restructuring. So when your app gets really large, it's always better to combine related features into their own folders or modules so that they don't clutter up the main application. And by doing it this way, it will not only help you manage your project more easily but also help you troubleshoot and debug your code tremendously. So this is a very good feature. We'll actually do this in our app in the next couple of videos. And so here is the error handling middleware. They are defined in the same way as the other middleware functions except there are four arguments instead of three. So specifically with the signature of the ER for error, request, response, and next. Now you define error handling middleware usually at the end after the app that use or the routes call as you see here. The application level, router level, and error handling middleware functions are three common types that you use quite often in your app's express application. So now that you know how middleware functions work, in the next video we'll create a template, a data model, and a controller to display a list of service providers using these middleware functions.