Middleware, Setting Up Custom Logging And CORS - FastAPI Beyond CRUD (Part 17)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
what's up everyone and welcome back to the series in this video we going to be looking at middleware we've so far been able to look at things like defend injection error handling and other Concepts in first but I thought before we conclude the series uh let us look at the concept of middleware so middleware are basically functions that sit in between our requests and our responses by this I mean functions that we can Define to modify how we are going to handle a request before passing it to the route Handler and how we can pass a response or how we can handle a response before actually returning it to the client now I've created a simple diagram right here I am not the best at making these diagrams but I think this will kind of give you an idea about how middleware work so just like you see right here middleware sit in between the server or the route handling functions and then the client who is going to make a request to our server so when you have your middleware this can be able to do a variety of things you can check for authentication you can be able to modify headers in your request or your response before actually sending them to wherever they going to be handled so for example here when a client makes a request to our server the middleware will get the request perform actions on that request and then send the request to the request Handler function that happens the same way for the response when you're making a response from the server you're going to pass it via the middleware that will go ahead and perform actions on that response and then after you'll be able to return that response now this is a very nice way in which you can go ahead and modify some of the ways fast API works you can go ahead and do things like logging in fact we're going to be looking at a loging example in our video you can customize exceptions we can customize error handling and perform authorization and so much more and you can also be able to use third party asgi middleware just like I'll show you in the video so to start we're going to create a simple middleware that's going to be responsible for allowing us to modify how fast API logs our logs so for example whenever I make a request to our server we get a log inside our terminal that shows the path through which we made that request and some other details about that specific request we're going to modify it and we're going to make it look little bit more detailed in our video so to start I'm going to go ahead and first of all show you some of the changes that I've done to the application so remember in our error handling video went ahead and made all the errors to be registered within our dpy in our source folder I went ahead and modify this to create the register all errors function that is going to go ahead and perform all those actions in a function that has the app instance which is our first API instance so once we Define this function it takes in an app instance which is a first API instance we then go ahead and call that function to run all our exception handlers just like you see right here with our app instance that we created for our application so we're going to do the same thing for middleware so what I'm going to do is to go within our source folder right here I'm going to start by creating a new file so this is actually going to be a new file and I'm going to call this new file middleware P so inside that middleware P we are going to first of all Begin by Import in the first API class so I'll say from first API we are going to go ahead and import first API and once you imported fast API now we're going to create a function that's going to take in an app instance so I'm just going to come right here and create this function so this is going to be our register so we simply going to call this our register middleware function and this will also take in our app instance so this will be our first API app instance so we can pass this for now and what we need to do at first is to go within our errors piy we are going to need to you actually need to go within in it and then import that function so I'm going to do that by saying from middleware we are going to go ahead and import our register middleware function and once we've been able to do that now we shall come right down after registering our errors we are going to go and register our error or register our middleware and what we shall provide is going to be the app instance so now the skips are done any py clean and the only thing that we have is only those lines of code that are going to register our routers so those are the ones that are going to be the most in this file so right after we've done that let us go ahead and create a simple loging middleware so if we went back to rest for right here and try to make a request to an endpoint we now see that our token is invalid but one thing we can notice is that first API is going to log that request within our console so as verification is is expired so that token is expired but for now we can only handle that and return a 41 and authorized error so we see that first API is going ahead and logging this request in the console and also showing us the response that is being returned what if you wanted to customize is to make it in a way that is custom or changed in a way that is more detailed and we may actually include things like the time it took for that request to happen so that's where middleware can be used so to begin we are going to go ahead and create that middleware so A middleware is simply a function and for us to create a custom middleware in fast API we can go ahead and use our app instance to create a decorator that shall use to decorate a function then whatever code that will be within that function will be our middleware so for example if we enter ahead and say at app middleware so this is the middleware operator it's going to take the type of middleware that you want to create now you can create one for HTTP so that will be our HTTP middleware you can create that that specific to let's say our web sockets and so on but for our case since we are dealing with an HTTP server we can just go ahead and say that this is going to be our HTTP middleware and once you've been able to do that then we can go ahead and Define the function that's going to be run within our middleware so to Define an async function I'll say async Def and for our case we shall say custom loging or shall just simply CR right here and say that this is going to be our custom logging so this custom logging middleware is going to take in two things so every middleware function is going to take in the request for which you want to pass that middleware so in this case we are going to provide the request object now this request object is going to be of type request I have to go ahead and import that as well so I'll say from first API we are going to go ahead and import actually you need to we need to enter the request module so that's going to be within first API request we shall go ahead and import request once we've been able to achieve that thing we are now going to go ahead and provide that type in here and then after doing that we shall have to provide call next so there are two things to observe here the request parameter is going to be that request that you want to pass to the middleware before we pass it on to the route Handler and then the call next is going to be either another middleware that's going to be registered on our app as well as any path Handler or route Handler that we've defined if you go within our route. P for let's say our authentication we have a simple route for signing up so whenever we use a midw onto this specific route we may be able to go ahead and first of all get the response on our sign up but before it reaches this function to handle that specific request it will pass through the middleware get processed and then hit the route Handler so I hope you understand that so when you go back right here the call next is going to be that specific route Handler or any other middleware that will be needed to process that specific request so to move on we are going to start by first of all getting the current time so to do that we're going to be making use of our time module so I'll say import time and once I've imported time I'm going to go ahead and keep track of the current time so to do that you can create a variable called the start time and that start time in this case is going to be time do time so this is going to create an object that's going to be standing for the current time and once we able to do that then we can go ahead and first of all get our response so to get our response all we need to do is to go ahead and call this call next function with the current request as an argument so basically what that does is to go ahead and set up our response object so to do that we shall say that our response is going to be equal to a wait and for our case you can go ahead and say uh this is going to be our call next so so that's going to also be an async function then what we shall do is to go ahead and provide the current request so once that is done we can now calculate the processing time for this request so normally when we are done processing the request with our middleware all we do is to go ahead and return our response so I'll say return response and once I've been able to do that then we're going to go ahead and process everything we need to do before the request is done or before the request is handled in in here and then we shall also have to handle everything that is going to be done before the response is returned under here so for example let's say we wanted to go ahead and say that this is what is going to happen before the request or before the request is actually passed on to our R Handler so in this case we can say a print before and then we can do the same thing right here and say print after so this is going to show us where the request is beginning and where the response is being returned so for our case we can print the start time and then we can go ahead and also get the end time or we can actually get the time at which the time for which the request has been processed so to do that I'll come right here and say that we're going to have a processing time being equal to time time which is going to be the current time after the response has been created minus the start time so once we have that then we can say uh print processed after and then we can provide the process time so once we've been able to do that and our middleware has been registered onto our app we can now now finally go ahead and make this of our middleware so if we pull up our server our server is running so let's try to make a simple request so I'll send the same request now we shall see that this is now going to print that this request has been processed after this time but we can also notice that it's going to print that the time before the request was processed is going to be this and then after the request was processed we can get the processing time which is going to be after this amount of seconds so this is basically how that middleware will work it will go ahead and get the request process it before returning a response return the response and then process the response before it returned to the client so now that we've been able to understand that let us go ahead and modify our loging so to modify our loging the first thing we shall do is to go ahead and first of all disable first AP initial loging or uon initial loging that we using right here so we're going to go ahead and and make so we're going to begin by first of all modifying the way first API is logging our responses so to do that we are going to be making use of the loging module so we shall go ahead and import that I'll say import loging dot so this is going to be our loging and the first thing we shall have to do is to get the logger that we using to log and that is going to be Aon loger so to get the loger we are going to be making use of logging get logger so all we need to do is to go ahead and provide the name of the loger that we're using in here so for our case it's going to be uvon do access so that's going to be the one to log all these requests and the details about those requests and responses so if you want to disable it all we have to do is to just come right here and say loger do disabled and then we can set that to false or actually it's going to be true since we are disabling it so once that is done whenever we try to make a request so let's try to make a request right here when we go back to our terminal we shall see that no information is being printed about the response that is being returned and that is what we want so want to go ahead and set up our custom loger that's going to log information about the request as it has happened and we shall have the request URL the method that's being used to make the request as well as the process time for that request so what you're going to do is to first of all create the message that you want to go ahead and log so to do that I'll come right here and say message so our message is going to be an F string and for our we want to go ahead and get the request time so all those can be accessed within the request object right here here so you can go ahead and say request dot in this case we can get the path so we can say uh we can actually begin with the method so we can say request do method and then space then we want to go ahead and we can say request method Dash then we provide the path so we can say request do URL dot so we can get all the components of the URL right here so for I is going to be the path and then after providing the path so this is going to be g/ let's say books and then we can go ahead and provide the time that this request has been completed so for our case I think this needs to be done right here or let's calculate the processing time right down here actually I'll just move the message down because we need to go ahead and return this uh before we return the response so I'll come right here provide the message so this is where we're going to provide a time so we can say completed after and for our case you can go ahead and provide the processing time so we going to go ahead and provide the processing time and since we want this to be in seconds we shall just provide the S just like that so for messages we are going to get rid of these Sprint statements and then we can simply go ahead and provide uh L loging for that so we can just come right here and all we shall do is to just go ahead and print our message and this is going to be what we shall print within our terminal so if we try to make any more request to our endpoint within our rest forx here we shall now go to our loger and then we shall see that this is going to be a get request to/ a// books SL that ID and then we shall see that that request has been completed in that amount of sequence so it's just that we have errors right here so let's go ahead and try to get right credentials for this so that we actually do not get those errors so if we go to where we get a token pair we can send a request we get our new access token and when we get this new access token we can now pass it in our authorization header just like you see right here and that will be so we have something wrong let's see what is wrong if I go our terminal right here we can see that n is not defined I forgot to remove this so I'll go ahead and get rid of that and when I get rid of that we now see that the book is not found but what is most important is going to be this log that we have here so when you get the book we see that get books V1 books and then the ID is completed under that now we can also get the status code or the response status code so to do that we can simply go ahead and modify our message to return our response status code but simply going back to our mid py and then we can go ahead and provide the response status code by simply coming in here so we can just come right here and say response Dot and for our case we shall provide the status code so when we save and try to make a request again shall now go within our logs and now we shall see that get that is going to return the 44 status code and that will be completed in that amount of seconds so by just using our middleware we've been able to set up custom loging for our app so right I've done here is to also go ahead and add the client who made that specific request so we can get the details about the client via request. client. host and then we can also get the port via request. client. port and now to go ahead and log the IP address of the client that made the request and we shall also be able to get the method the path the response status code and then we can also see the amount of time it it took to complete that request so what I'm going to do is to go ahead and disable SQL Alchemy Echo since we do not need it at this point so what I'll do is to go within our DB Main and what I'll begin doing is to first of all remove the echo attribute so that we only see our logs so when I save and head over back to our loging when we try to make any requests uh this time we only going to be getting our loging so if we try to make any more requests we shall now see that our loging is the one that's going to be done and this is how we're going to be using our loging from now and on so let us look at another example of using middleware so in set up a simple middleware that's going to check our authorization header and just in case a request is sent without authorization header uh we shall be able to get or raise an error so this is something that is an alternative to what we did in the series where we use dependency injection to achieve this thing so just in case you don't want to go ahead and this dependency injection for your authorization you can also use your middleware and set up authorization middleware that will be responsible for helping you check if users have provided credentials and if those credentials are valid so what I'm going to do is to head over back to my mwarep and I'm going to create the second middleware now this is going to be the authorization middleware so shall say app. middleware so in this case shall say app. middleware this is going to be a HTTP middleware and then we're going to Define this as our authorization and this will take in our request object and call next so request is going to be of type request and call next is going to be also provided so I forgot the def so I'll go ahead and provide that and now we're going to write the code that's going to handle our requests one thing we need to keep in mind is that when you set up middleware this middleware is going to be registered app instance and therefore it's going to work on all in points that we shall have within our application just like we saw for the loging middleware right here so if want to go ahead and make that specific middleware that's going to check every request and check if the user has an authorization header we shall go ahead and first of all check if the authorization header is really found in the request headers so do that we can do something like if authorization is in the request headers so we can access those via request. headers then uh since we are checking for the opposite of this we can go ahead and do something like if not authorization in request. header that means a user is not authenticated then we can return an error showing them that they are not authenticated but one thing is we cannot Trace exceptions and return them as responses within our middleware so we have to go ahead and return turn ajon response and that's something that is important to note when using middleware you cannot trace an HTTP exception inside middleware it will be raised as an exception but it will not be returned as a response and that is very important to understand if you want to return some kind of response all you have to do is to go ahead and return it inside the response right here so to do that to do that we have to go ahead and create a response object and then return it in in case we hit this error or in case we encounter this error so I'm going to go ahead and import the Json response class that's going to allow us to do exactly that so I'll say from first APA I think I've done a m right here so this is going to be from first APA do responses we are going to go ahead and access the Json response class and once we have that we are now going to go ahead and return so this is going to be return Json response and for our case we are going to provide our content now for this time we can come and provide the message so the message can be something like uh or let's say not authenticated so let's just say not authenticated and we can also give them a way to resolve that by providing a resolution message also so we can say resolution and we can simply tell them to provide the right credentials so we can say please provide the rate credentials to proceed so when we save this is going to be added onto our headers or it's actually going to be added to our request so that when we make a request we check if the authorization header is present in the request headers of that request and then if not we return the Json response so to finish this we have to go ahead and create our response object this is going to be good here await call next and our call next function is going to take in our request object so let's go ahead and return our response so that going to return our response and when you try to make a request again without our authorization header of course we shall see that going to be what will happen so when you go back right here and let's say we delete our authorization header when you try to make this request you shall see that our middleware is going to allow us to return this specific response to show that the user is not authenticated now we can also go ahead and return the right status code for this case our status code is going to be the one for not authorized so you can say status I think I have to go ahead and import that status HTTP 41 so let me go ahead and import the status from first API so this going to be our status and then can go ahead and say 41 unauthorized so when you make that request of course we shall see that we are not authenticated and therefore we need to provide the right credentials for us to proceed with that specific request so that has been a very simple example of how we can achieve authorized or authentication using our middleware but this is a simple example I think I'm going to just go ahead and remove it so that we only keep our loging right here so now that we've been able to do that let us also look at how we can this custom middleware with first API so first API is a framework that is built on top of the asynchronous Gateway interface and therefore in any middleware that can be used with asgi can be able to work with f API first API allows us to achieve that by using The midare Decorator actually it's a method that's found on the app instance so when you go back to our midare right here and let's say we have some middleware that is Created from another package that is compliant with asgi we can go ahead and register it onto our app inance and it will be able to work for example let's say I wanted to add cores or cross orig resource sharing to allow resources be accessed from another domain from our server we can go ahead and use the inbuilt course middleware that's formed within first here so let's go ahead and set up course for our app to do that I going to go in here and first import that class I'll say from first API do middleware so inser here is where you can find middleware for Cores middleware for giz middleware that can help for HTTP redirect middle for and middleware for gzip wsj trusted hosts and so on and we're going to look at how to use some of these middle so for our case we can just come right here and say middleware course we can import the co middleware and once we imported the co middleware to set it up all we have to do is to go down here and call our app. add so this actually going to be our app in our case then we can add middleware and this will take in our middleware class so our middleware class is going to be the course middleware and once we've been able to do that then we can provide the keyword arguments or arguments that that m t in let's go to the new line and provide those so what we need in this case is to go ahead and provide let's say allow hosts so when you go back in here we see that this is going to take in a a bunch of arguments allowed origins in this case are going to be those domains which will be allowed to access resources from our domain allowed methods will be the methods that will be allowed to be performed from other domains allowed headers headers that to be sent to the request when basically performing an action on our domain so these are things we need to go ahead and set up if you go within our middleware all we have to do is to go ahead and provide those so we need to copy some of the stuff that we have right here and then I'll bring it in here but then I'll give it the values so instead of having these typings or this type annotations all I can do is to go ahead and remove them and then we can go ahead and set this up so so here we can say allow credentials equals to true or false whatever we may feel is needed so we can say allow credential is equals to True allow headers you can allow all headers by saying uh star then you can allow all methods by also saying star so every method can be allowed to be used on our domain and then allow Origins we can also go ahead and set up start to say that want to allow all Origins to be able to make request to our API without getting core issues cause issues so right after doing that this is just enough for us to go ahead and use our custom middleware we can also use the trusted host middleware so for example can go to fir so this going to be first API do middleware dot trusted middleware or trusted host so we can go ahead and import The Trusted host so the trusted host middleware can also be added here here so this is how we set up the allowed hosts for our app the host on which our app may be accessed so in in this case we can go ahead and say app. add middleware and then we can simply go ahead and set up the trusted trusted host middleware so this is going to take in a lot of things just like you saw for the cuse but we need to set up the allowed hosts so the allowed hosts is going to be the list of domains on which our app can be accessed so can go ahead and set that up by saying allowed hosts and this is going to be our allowed host so in case you have a domain you can just go ahead and provide it here by basically saying example.com blah blah bl.com that's where I going to go ahead and set it up here so that's just how you set up a custom midare and this can be any asgi middleware that you want to use within your app so you can just go ahead and import it then and simply import that class and then use the ad middleware method to go ahead and register it can provide it agum just like you see right here in this video we been able to look at how we can use fast apis middleware we've also looked at how we can create our own custom middleware and we've created a simple example where we went ahead and modified first apis loging so that we can be able to provide more details with our loging we've also going ahead and looked at how we can use other modified custom middlewares that are compliant with asgi so that we can use them with our first API application if you've enjoyed this video I request you leave a like and please share this video with whoever it may be helpful too also do not forget to click the Subscribe button my goal is to reach 10,000 subscribers this year if you've enjoyed this video and like to support my channel financi please join the channel become a member of my patreon and also buy me a coffee in the link down in the description I hope to see you in the next video where we're going to be looking at API testing and documentation thank you for watching guys and I hope to see you in the next one bye
Info
Channel: Ssali Jonathan
Views: 487
Rating: undefined out of 5
Keywords:
Id: 7ndnHhxcL-Q
Channel Id: undefined
Length: 32min 53sec (1973 seconds)
Published: Fri Jul 05 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.