Mastering Form Handling in Go: A Comprehensive Guide

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] [Music] well hello guys and welcome back so today um we have a couple of things I would want to look at one would be talking a little bit about middle wearers how they work um as interceptors for requests and then of course we'll talk about um testing and then of course mocking as well because if you remember we're working with database and um we would want to write tests um um that would of course um not have to maybe write an actual entry into our database so more or less simulate the actual way the database could work but of course um just within our test environment of course if we would want to do um some form of integration test we we can actually write into a database that's of course a different topic Al together um but we would want to be able to break our codes into functional units so we can test all those individual units independently without having to manage the dependencies um with other components or other um logical units of our application so of course the first we're going to do more or less would be to start to refactor our code and then of course introduce middle Wares and after that we then move over to testing because I think we'll spend most of our time talking about about testing so without wasting so much of our time let's just jump in and start with our refactoring to introduce middle Wares so like I said initially we'll start by um with refactoring our mwes as you can see I already created um a new Branch so this is where everything we'll be doing in this video would be located so if you would want to check this out of course go to this branch and then you have every piece of code will be writing this tutorial anyways what I would like to do is to go in here so we had here a lot of helper functions one helping us to connect to our postgress um database and we also have this one here that we are using to connect to our um um Microsoft's SQL database so what I would want to do is would be to turn this actually to middleware so we have them um attached to certain apis only where we want them to be and so I'm just going to go ahead and start and start with this two I'll create a new file I can call this SQL um I think this is already okay because it would be within the package middleware of course and I'll would create another one for postest because I would like to see you how this works on package Middle where I would like to create one for config of course it will all be package middleware and maybe just also show you I would like to create one for Cores and I think that's mostly it if we cover this four I think you would you should have everything you need so for cuse I think it's pretty straightforward um I would just create a function here um I can call this course middle Weare so it should more or less all middle Wares in G always have the same signature more or L they return a g Handler Funk which would more or less which is actually similar to the handlers we've been defining all along so this would return a poter to come on Handler Funk one and this is what it should return so what I would like to do here is just create a string of allowed headers and I just wrote this down so this should be totally fine so these are some of the headers I would like to allow so content type length and the rest and now of course we need to return a Handler more or less so that's also pretty straightforward so it has to be a function that that takes in um a point a gen context and then of course um we should return this function basically that's really what we want to do and of course here is pretty straightforward so I would like to maybe add some headers so I can say context. writer. header and I would I would want to set a couple of headers and I can call this um this might be um of course this need to be to post so maybe to be pretty I think this should be return already we have here so um yeah of course um why also down here if everything goes we need to call um c. next of course that would be in reference to our Gene Contex but sure that should actually be inside of our function because outside here we don't know see that next like this of course we need to just return the Handler not a point to it so that's why we get this error anyways and but now I need to I would like to set a couple of headers here so I would first one would be assess control allow origin and this actually where you get to set your origin so for now I'm just going to put set this this to Local Host so again I need to set a couple more headers and here I would like to maybe allow credentials so ass say control allow credentials and I'll say this to true and of course set this as a string because the to should be string of string as you can see and I would like to come [Music] on I would like to set um this headers so assess control allow headers and now I will set my allowed headers and what else maybe allowed methods and that should already be fine header um header do sets and assess control allow methods and here we also pass a string so this string could contain a number of HTTP method so we could allow options it could of course allow allow get put patch maybe also head for example if we want to do some um monitoring to see if our our our server is up more or less but that's already fine and then maybe what we want to do of course is to handle options so if we have a pre flights of course we would want to handle this so if request do method if this is equal to options in this case we would like to um abot the request so here I can say abot with status with status and here I would use my HTTP status no content and of course return and that's more or less all we need for our course middleware that's I think that's already more than what we need so now we can go to um um our sqle middleware so what I can basically do actually is probably just copy all of this okay and then come back in here and then go start creating this I can call this SQL middleware like this and again it's going to return in hand fun like this so here we return a function that looks like this exactly and now I dump all of this inside of here and we would clean this part up soon but um that's also fine for now and but of course we don't really return this so what I would want to do is to set this inside the gene context so I is the set function this way and so I'm going to change this to c not um this this better for me this way and then I have to give it a name I can call it SQL client and of course pass the B so what it means is that if we pass this to any Middle where um this would of course provide us with the client and then we get to close um this connection when that's request terminates that's more or less what we do I think this pretty straightforward and of course for our post gra also do very similar to the other one so I call this post gra mware and I like the name to be explicit this way just so I don't mix things up so Handler fun again we return um Funk this way so it takes a point contest and we more or less return this our user and again we do the same here so see do sets no and we give it a name I can call it postgress client and I pass DB so I can get rid of this [Music] one and that's more or less what we we have to do actually so if you look in here if we look at one of the handlers say inside our users maybe create user and if I hover over this or more or less if I go to our API definitions for example which we should be able to find up here maybe going to O and then if I hover over here you would see like this more or less takes a string as our path and of course the Handler is this Handler Funk but the the the cool thing actually is not that it only takes just one but it can take an array so what it means is that I can actually just copy this for example and just maybe make copies of it and that should still be fine because it's fulfills this requirement here and that's why we write middlewares that have this um signature so that um when you visit this Endo it will process this it will handle these handlers in this manner so this would be handled first then this second and then this third and if anything should happen if there should be any error here you have the option to either propagate it down to the subsequent ones or it simply terminat so but of course you don't want to process the same thing three times that if for example if you try to log out or if you're trying to create an account then we create it three times that would not make sense anyways but in our case we can now replace this to our say our cause middleware so if you fulfill our cause requirements then the next thing might be to provide an off middleware where we handle like the user authentication and then in that order so that's really the cool thing about this but of course I'm going to get rid of this I don't confus someone um anyway so now we have our C midle Weare setup we have this setup and we have this setup now I would like also have config um middleware setup because I would really want to remove this logic from here so that our middle wees don't have to worry about fetching environment variables because again I need to have separation of constants here so I would like to move this logic completely into a different middleware that's probably just what we're going to do next so what I can quickly do is to come inside of our helpers and then maybe create a new function and I can call this config go of course we should not forget to provide the package package is helpers and in here I would like to Define um a struct that would match more or less our EMV file of course I don't want to open the EMV file because the credentials to my database as you can remember are in there um but the cool thing of course maybe I split this into two screens so we can see better um but if we take a look at let's say SQL database for example we see we have um the server user password port and all of this information so what I can quickly do more or less would be to come here and Define a struct I can call this com and maybe m config and now I provide all of this ACC SQL Server would be a string um s SQL user will still be a string SQL password will be a string and SQL ports with um let's make this int I'm not sure okay let's make it as int 64 we'll see how that works out for us and of course SQL database will be a string so this is more less going to represent for now all the environment variables we like to provide um to this application and now what we need to do is more or less to be able to read the values we have in our EMV file um and then somehow pass that into this struct and then have this struct again pass to any of our apis that need access to these environment variables that's really the plan here and to do this actually pretty straightforward um we need a library called Viper and this we can actually get from so I try to import it here um I importing this way so it's actually github.com SL spf13 and then Viper like this and now I need to define a function down here so I can call this load config so this is supposed to take a path to our environment variables and then of course then return two things to us so it should be able to when we provide the path it should be able to read um this um EMV file pass this into this struct and of course return this to us and because of that we would return two things one would be our our EMV config and of course an error if everything don't go as you expect that's really the plan and so this what we can now do more or less would be I'm just going to keep it as simple as possible but I need you to um understand what we are doing so CFG would be this or common so this should be our M config and now SQL Server we can use now use what we have over here actually so put this in here and save and of course we don't need this anymore because we are this within the same package so now we have SQL user I'm just going to copy this and put it in here because I'm lazy to type and again I'm going to update of course the string so I've not forgetting that SQL port and now of course I need to write a new yes okay I already have one already so I can say it as in oh is this ah okay so yeah I'm going to keep it simple so you're going to be in so I don't have don't want to do this actually that's totally fine and I put this to I don't know 136 for now and the last one of course will be SQL database and I put this one as well so I'm just going to copy this one user will be user password would be password um ports would be ports and of course database would be database and so if everything goes well so I would like to actually maybe H do one of two things so I don't want to save or I saved already but it's fine I'm going to have to import this again but that's totly fine so but what I would want to do is if we run our app in release mode for example then we didn't of course I would not it would not make sense for us to commit our EMV file into any public um code repository so in that case I would expect that we inject this somehow into our code maybe during The Bu phase so if we have this a pipeline with which we set this up then of course we have to inject this through the pipeline but if that's not the case if we running locally then we can have um we can have um um an a EMV file so what I can now do is I will try to say if get M I need to provide an variable here and I can call this app mode and I'm just going to set this to the bog and I'll say if this is intentionally set to release for example if this is set to release then this this what would be would do so more or less we know that we are let's say in our production environment and if that's the case of course we simply now return CFG and nail um but of course if that's not the case if we are running locally like we are doing right now now I can use the Viper that I tried to add before so that is a method called act config path like this and here I will provide the path um so if I over order this if my intelligence behaves itself um it's not okay I think we first need to of course go mode tidy because I don't think I have this of course so that's totally fine and now we should have it yes and if I hover over this now you can see we at the path for Viper to sarch this config file and then so if we have this what I will now want to do is of course um I need to tell it um more let break the file into two so there are two options of course so if you read over here more or less we can use it this way or we also have the option to say um via do set config name and we provide the name of the file so for example if we rename this to app. em V so we can give the name of the file as app or whatever and then and we need to of course set the extension using vi. set config type and now we can set this to EMV so in the end it's going to be app. EMV and that's um more or less what we can do and then we only now need to call this function vi. automatic EMV this one and now we we would need to of course um read in the config and then of course M on maral um what we've read into our struct and then return the struct that's basically what we have to do so now we say viper do read in config and of course this returns an error so we have to handle the error so we say if this error and this um error is not equal to new if this is the case what we like to do is simply return V config and we return the error and if that's not the case the next thing we want to do of course will now be to un maral and then we have to UNM maral into our config this way and of course this also returns an error which of course you would probably know already so we have to handle this error again like this um pretty straightforward I'm just going to copy this I don't want us to waste so much time so I'm just going to dump this here also because I'm lazy and if if everything goes as expected now we can I'll just return this guy and that's it that's more or less what we have to do so what it now means more or less is um that's over here we might actually need to get rid of this so we might actually need to get rid of this because what it means is that we now have the option of supplying this um supplying this middleware first before this so that way we would have this before we get our middleware sorry before we go to our SQ middleware and to use this more or less because we have access our um gen context so here I can say CFG for config and this would be from um what is the syntax I think this should be most get like this and and now we have to provide the name of um of this um so well maybe I think we've not actually even completed this one so we only just implemented this um this function here so now we can go over to the Middle where and implement this so I call this funk um config middleware again as usual it's going to return a Handler Funk Handler Funk like this and pretty straightforward we return um Funk this one thank you but how let just want to go with C that's totally fine for me and now I would need I I can call this maybe EMV and error because now I need to use the function we created so we called it um what was what did we call it so load config so I can say um so help pass a load config and now I will need I'm just going to point it to our current um directory so we need to point it to our current directory which is what we're doing here and remember we have to handle this error so now I can say if this error is not equal to nil I would want to do a couple of things um I would of course want to abort so we don't move on to the next um middleware and if we AB about I would like to return to the user some some human understandable error and that case I this would of course be my fault so I'm just going to time this as a intern inter server error um it should be an internal server error in my opinion and I need to provide additional information and I can say eror I I'm leaving this for you or leaving this to you rather to provide more human readable error so and in that case I return to the user but if everything goes well of course as before I need to set this into the Gen context and I can call this up EMV for example and then I pass my EMV like this pretty straightforward and now I can put this side by side so now we can actually get rid of this and now we say must get like this and the key of course would be this guy over here so we call it app EMV so must get if it doesn't get this is going to panic as it us to seen here so if you forget to put this before if forget to pass this middleware config middleware before this SQL middleware is going to panic that's just what's going to happen and of course we need to of course provide the type because go as you know is stat statically typed and so this should now come from help pass. EMV config like this and now I can just call this up EMV like this and so if we now have this in this format as you can already imagine we have access to um uh everything we need in here so of course this should actually be a pointer to this so let me just be sure um yes this should be and now what we can simply do is we come over here we say app EMV do SQL Server I think that was what was there okay up EMV that's user Square user now password password um up mv. supports and up EMV do SQL database like this so now we only need to have this here as you can see we don't need this Middle where doesn't really need to know about how anything about how to extract this um environment variables it should only just know how to use it you should be able to have access to it when he needs it that's really how it should be and so that way we have actually separated these two and of course you can already imagine so for our postgress middleware would of course need to provide all these variables as well to connect to it and you can already imagine all you would need to do would be more or less to ex extend um to extend not this why not this guy but this one to extend this to um I don't know whichever number of environment variables you would need to set your app and of course update the logic here mostly of course down here you wouldn't have shouldn't have any problem mashing that into your your your struct and then of course pass this before so what it means for example now is if we go to our let's say we go to our apis and we go to our apis and we have or for example so if we go to our login I think um for here we actually needed to um yes we needed to read to our database more or less um so what we can already just do to use this maybe we can actually starts with um um with these other ones so by default I'm assuming that all our end points should of course have the ca middleware so here I can already say um use and now as you can see again this function signature it takes an array of them and now here I can provide Middle where I would like to provide the config first and after the config I now provide course so by default all our end point would have this and now if we come back to earth for example um over here um here we can now provide this so now I can say uh middleware middle rare dot um SQL middleware like this and that way of course before this this guy would have already appended this two for us and then when we get here would also have access to this so that's really the point and I think actually with our current setup it also makes sense to have this in here and and of course if every of the end points within this would need to have this then it also makes sense that actually we come over here and then we say J do sorry use and then we'll put all of them here so I can just put this here once I'm for roll and now we don't need to put it here anymore so that's actually one way of doing it um yeah that's more or less it so now we can actually already start doing some cleanups um um more or less to remove or we don't need anymore and I think we we can easily skim through all of this so we have this already and now I can actually maybe come over here where we have this guy and I can now maybe we actually comment this out so just to see where this was actually used or where it's being used and I commment this all this way and I can go to the end points to the apis and now I see that this is actually being used here which is really nice so now what I need to do more or less is to just get rid of this one and now get it this way so who now C.M get and we call it um if I'm not mistaken I'll I'll take one more look just to be sure so SQL client and this should be of type pointer to gumd B so we'll come back here so SQL clients and this will be of type G DB like this and everything should now also be fine as before so now I can actually copy this because I know that's also the problem with all these other end points so we go to create we get rid of this I will put this one and we are good to go as simple as that we come in here we get rid of this again provide this one and we are good to go and then we come here as well exactly that's actually as you can see produc forward we don't need to repeat ourselves and we go to get we do the exact same thing and that's fine this one as well I think my PC is getting quite slow I have no idea why um now as you can see we have cleaned up everything and now actually we don't need this anymore because I can actually now go ahead and delete this it's no longer needed actually and I think that's mostly what we would want to cover as regards to Middle wear so again I think this is really pretty straightforward if you find anything confusing please just take your time pause the video go back go through it and TR to me once you grab the handang of it may walking with middle W and go and at least as it pertains to the gym framework is pretty straightforward [Music] oh
Info
Channel: Easy Dev For All
Views: 58
Rating: undefined out of 5
Keywords:
Id: YMfeigdyZnM
Channel Id: undefined
Length: 34min 12sec (2052 seconds)
Published: Sat Jun 22 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.