So route handlers can be a useful feature.
Another feature that can be useful is middleware,
and that is a feature
that does actually not use the app folder.
Instead, you set up middleware
by going to your route project folder,
and then there next to the package.json file and so on
you add a file named middleware.js.
And again, that is a reserved file name.
The position also is important,
it should be in the root project folder.
In there, you should export a function called middleware,
and that function name is also important,
and that will now get a request object
passed in automatically by NextJS,
just as the route handler did.
And you then have to return a Next response,
which is something that must be imported from next/server.
And this next response thing here has various
methods you can call.
You can also instantiate it
to create a new response from scratch,
but you get some utility methods like next,
which simply forwards the incoming request
to its actual destination.
And that also kind of describes what the purpose
of this middleware function is, as does its name.
It is a function that's not really meant to block
or handle an incoming request, though you could do that,
but instead it's typically meant
to take a look at some incoming request,
maybe change it a bit, maybe block it,
for example, to implement authentication
and maybe redirect to another page
if a user is not authenticated, for example,
which you could do with help of the built-in redirect method
on this next response.
But you often also just might want to let the request
go on to its original destination,
maybe after evaluating or changing it.
So here again, we can lock that request
to see what's inside, because here in this application,
we don't really need that middleware feature,
but it is another feature that is related to routing,
which is why I wanted to introduce you to it here,
because middleware does allow you to set up code
that will run on every request that's sent to
any page or any route anywhere in your entire website
so that you can inspect that request block
or redirect the request or do whatever you want to do.
So here with that setup,
if I save that and I open up that terminal
where my server side code runs
and I clear it and restart that development server
so that we start with a clear output again.
If I load the news page, for example,
you see a request object was locked here,
but in there you actually see that it was not
for the news page,
but instead for the fav icon.
Well, that's just the case
because when I visit this news page,
actually multiple requests are sent
and the fav icon request is one of them.
But there also would be a request for every single image
that's shown on the screen
because that also is loaded from our server
and that also is done through a separate request.
And if you would scroll all the way up in your output,
you would also find the request for the news page somewhere.
Here it is in my case.
And that shows you how that middleware function works.
It really runs this code for every request
so that you can do with it whatever you want to do.
Now, you can also export a config object,
and this must be a variable
or constant called config, which must be an object.
And in there you can set up a matcher property,
which must be called matcher,
and that would allow you to filter the kind of requests
that trigger the middleware.
For example, if I filter for /news here like this,
and I then reload this page
and I take another look at my server log thereafter,
you would see that now there is this request
for the news page, but I don't see the request for this icon
or for all those images.
So you could set up some filters here.
And this does not just allow you to filter
for a single page,
but you can also filter for other pages
by setting up a more complex matcher.
And you can find all the details about this
matcher configuration in the official documentation,
and you find a link to that attached so that you can learn
how you could set up this matcher, for example,
by passing an array
and using placeholders to match multiple routes
and not just a single route.
So that's something you can do.
And in general,
this middleware feature is a feature you can use
to handle different requests differently,
to inspect all kinds of requests
and potentially to also redirect requests
depending on what you need to do in your application.
Here we don't really need that feature,
but it's still important to know about it.