Building Microservices with Go: 5. Gorilla framework for RESTful services

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] hello and welcome back and I'm unmuting my mic this time and we spent the last sort of couple of weeks looking at micro-services and we've been looking at kind of the basics so we've looked at how do we kind of build micro services with the gold standard library and then starting to kind of refactor that up a little bit create some nice restful patterns and start looking arrests I think one of the things that I find when I'm dealing with a ghost standard library is I end up creating a lot of really what feels like boilerplate code I mean stuff like you know like this let's just have a look at this handler over here that we created last week so we've where so like we have this serve HTTP method and we've got method get' in here and it's got to do this and then get products and it's going to do that and you know it just feels kind of really really really untidy and especially when you start adding other methods and then you start sort of parsing out the the the kind of IDs from query strings and and things like that so let's just imagine my branch from last week all right so what we're gonna do this week is we're going to take all of this code and we're going to refactor it again but this time what I want to do is I want to look at something called the guerilla web toolkit so the nice thing about the the guerilla web toolkit is that it it has it as a number of different sort of capabilities but some of the things that I really like is this much package so I'll put the link up there for the kind of the previous session where we started looking at mugs and of course go back through the playlists if you haven't seen all that stuff but I think one of the key things about the the serve MUX that's built in to go it's quite good and it's quite powerful but there's some bits missing now the gorilla web framework has got a much more refined MUX rudin we can do things like this we can define placeholders to be able to extract categories or something from our restful URIs I can also define things like an ID I can specify what the format is using a regex so here this regex is saying that the ID is going to consist of numbers between 0 and 9 and it's going to be one or more of those and it'll put that into an ID variable so I don't have to kind of go through all of that kind of hassle myself where I'm doing all of this extraction and then I'm validating this and validating that this is wasteful code some of the other things that I really like with this framework is that it can handle middlewares as well so not only can we kind of get rid of a lot of the boilerplate around the air your eyes and the methods but we can add middleware and one of the kind of the key things that we we had around our kind of our previous example is that we ended up doing this validation around the product and we kept doing that like in a number of different places we had out on the post and we had it on the put so we're extracting we're validating and then we're returning in error but we're not actually validating we should be but we can actually extract all of this out into middle Wareham and we're gonna see that in this this episode we're going to refactor all of that out but goriller in it's gonna be sweet love it I covered this in the last session gorilla was literally the first framework that I ever used and got that but for me is a kind of a pretty big deal the fact that I've been using this for a long time now Nellie I don't know how many years like six at minimum but a long time and it still stands so let's dig let's have a play and let's see what we can do is you ready all right let's go okay so we we have this this code how are we going to refactor this out so the first thing that we we want to do is we we probably want to like replace this serve marks but we're going to replace this serve monks and we're going to replace it in two with the the Rooter but one thing we do need to do is we need to kind of refactor these as well so let's start with a serf MUX let's just get rid of get rid of this the default one so I'm not using the default one I'm using the MUX new Rooter so this is in the the gorilla MUX package you can see that's imported there so github.com slash gorilla I'll put the links in the description I really recommend you check this out so then what we're going to do is we can now actually register more more detailed handlers on on our route erm we can we can do things with with paths so one of the things that I want to be able to do is I'm I'm gonna I'm gonna call this product and you know products on its own is just going to be the get handler so if I add that I can add my my product Handler and I can also add a method so I can kind of specify at this level that I only want to be able to handle the product on there which is really nice now I think actually there's a there's a nicer way to do it and what a sub ruder has the the capability of doing sorry a Trudeau has got the concept of a sub brooders and by defining these sub rubezh we can kind of define a sub root for a little bit more flexible with adding middleware to various different routes and stuff so let's go through and let's set out that ruling pan so I'm gonna call my get ruder and that's gonna be my MUX ruder it's going to be methods and I'll look show you that in just a second get dot sub Ruby what so let's have a look at that that there in the documentation so we have a Rooter and on a Rooter you can add these routes and you can add methods so methods register a new route with a matcher for HTTP methods so what this means is that I can define as a sub I can basically create a route which is only applicable to let's say get and then I can register my handle as onto that now what I can also do with with this is route can be converted into a Subaru and I just scroll back to the API documentation which is in here somewhere I'm sure it is we will see there we go that a sub route that creates a sub rubric for the route all right this I'll be honest with you is probably making no sense whatsoever so let me put something together in code and I'll explain so what I've done here as I've I've got my Rooter this is my root looter rudra de the root root and I want to kind of start filtering this now I want to I only want to Han send get requests to a particular HTTP handler so what I can do is I can use the methods method on the Rooter and what this is doing is this gives me a route which is filtered specifically for the HTTP verb get then if I use the sub Rooter method on the root it converts it into a Rooter the same as SM and and once it's a Rooter I can do things like add my handle on there so I can do things like this right get ruder dot handle funk and I'll be honest with you I didn't expect go to be probably working here because did I mention but go tooling isn't as terrible as broken right now okay so I'm gonna handle my function right so which function do I want to pass well what I want to do is I really want to just go directly to my my get function which I've defined here on my my handler so in my in my handler when I was setting this up last week I ended up putting all of this stuff in to serve HTTP to be able to kind of handle this subroutine to be able to extract all of the IDS and all of that I'm gonna do my absolute favorite thing with code I'm just gonna delete all of that garbage and it's gone because we don't need any more what I'm going to do though is I'm just gonna convert this get products to a public because now I rather than having to roll all of that code myself I can just do it really really nicely here so let's um let's just check that out let's just make sure everything's working so go run bingo okay that's looking good and let me kill localhost 1990 and there we are okay so we've we've got we've got our product listing exactly as we had it last week so now let's add the the other methods into there so what I want to do is I want to create a Rooter for put requests so I'm going to call this a put route it and this is going to be again exactly the same thing so I'm trading that filter it should it be verb put I could actually even use the just in case I spelled get a foot wrong I mean it's I mean it's probable I mean some my buddy Eric probably would agree that that's not passed me put my sub brooder cream up Pat Reuter let's handle a function okay now we defined in our book ruder that we were going to have this this identifier so let's add that identifier in here because we're going to put and where we're just kind of going to pull the ID out of the string so I can define a variable for gorilla MUX and I'm going to call that variable ID and I'm going to use a regex so naught 2 9 and more than one or more okay so you see the curly brackets here this is how I define a regex which will be X manically extracted out of the URI by the gorilla Rooter and then I just define the the regex because it's gonna just define the split by using this colon here and then I can add my pH dot put Rooter which I've again just need to do a little refactoring so I'll wipe all this one update that's fine update products so now I'm just making that public because I don't have that that kind of root serve HTTP method anymore all of that's being read fact that out and it's gone in the bin and we're gonna just kind of look at this and you can see that well update products originally took an ID now again we we don't need to to kind of have that ID in there so what guerrilla does is guerrilla when you define those variables inside of your your your your eyes it's going to extract them out into a collection called MUX VARs so I can do VARs equals MUX dotting bars okay and you pass it the request so with MUX top bars VARs now will have an ID so to get the the ID for my collection I can just do bars and it's just a map ID like that so now I can do print line get product let's stick the ID in there so this now is really really clean right I mean really really simple we're not pausing any of that we don't need to worry that we're making mistakes by by kind of pausing any of these things out we're just defining these placeholders inside of our MUX URI it's very nice and very clean and we can you can see that in action too so again let's just run what are we complaining about okay so cannot use ID type string as type int in nog of update product fair enough it comes we have an ID there well we are pretty sure that that is going to be an ID because the the regex I mean if it's not an integer the regex is going to fail but let's let's just cast it anyway so we're just gonna do good coding practice so string STR comm dot a - I convert and into an integer but does that actually return me an error I don't know what we'll see as much one returns two values it does so again we're just gonna check that error if error is not equal to me now which it pretty much never will be but I'm gonna check it anyway good defensive coding HTTP dot r RW unable to convert ID HTTP go laters yes it's a bad request so just standard standard stuff there nothing special and what are we got no products on 61 so 61 okay because we've already defined error all right so we're running so let's do our put request so we're gonna do X put we're going to do we know update the first one we ascertained last week that I couldn't spell anything other than T so I'm going to update my latte to T so I'm just gonna rename it let's just name teeth oh gosh contact that mind and we run that unable to Marshall Jason probably so look what do we got blah blah blah blah alright very good so we've we've handled the put of our product we've we've updated that so if we we get our product again we can see now that's T so that's working as it was last week so just kind of quickly recapping there we've we've deleted a huge amount of code we've deleted about 20 lines of code we've introduced this new router and we're now kind of doing the filtering of the put requests and the get requests we're doing it on this at this level here by creating these sub rulers for for every HTTP verb I can do exactly the same thing so let's do the same for our post a new post ruder SM dot methods HTTP dot method post sub ruder and then do post for a dart handle funk you know if you want to you could you could absolutely bark be sort of creating separate handlers or for each of these I'm just using functions and I'm I'm just using handle func it um I don't think it kind of really matters I think the kind of the key thing around what you choose here is things like testability readability there's not a great deal of code here for it to be too much to be handled by a single file or the need to have a separate handle ever whatever you want to roll with you can do all right add product so again we've got exactly the same thing let's just give that a very quick test go run okay so this time I'm going to do a post and now I should have three items in here you see I've got my latte I got my espresso and now I have my I don't have my tea why don't I have my tea well let's have a look at what miraculous typing mistake I've made here then did I actually say that and rerun it oh gosh just pressing buttons everywhere post read and or post product okay so all that should be fine now I'm doing something stupid here and I will be damned if I can find out what it is well I can tell you exactly what it is I don't have that path registered for a start so there we go but it proves that my room is working you got to look it on the bright side right but let's quickly just look at get that products and now we've got three as we would expect all right cool everybody makes mistakes including lots of them so this this is cool we we've done a nice little bit of refactoring here we've now got I think some much much cleaner code it's very very specific we know exactly what's going on I this but if you remember as well last week we were kind of saying well you know we're we're kind of we've got this we're extracting the the product every time and I'll be honest with you we should be validating this object as well which we're not we will look at validation like we'll probably look at validation next week and I'll show you a great tool for doing object validation but how do we do that like let's avoid that duplicate code so there's a couple of things we could do one thing that we could do is that we we could put this into a function and that would work or we could use middleware and and I want to show you middleware because the the kind of the middleware sits outside it's it's actually a nice excuse just to show you how it works so let's take a look at the docs little wire all right the use function so the use function in the guerilla toolkit allows you to apply middle-way so what is middleware well middleware is just an HTTP handler and what you can do is use this middle wet pattern and you can kind of chain multiple handlers together so like a classic example for using middleware is doing things like cause you want to be able to just validate requests just using the the course for JavaScript access or you want to do authentication middlewares are kind of a really nice really nice example of where you can kind of do this sort of stuff and I'm scrolling around it this is just way too big on my screen Reuter Reuter use and and it's really really easy so there is this middleware function and let's have a look at what that looks like what it looks like to be able to define middle way so first things first let's look at the signature for middleware function so middleware function is here and just it's a very very simple signature so which is returns an HTTP handler so as an example of that like let's have a look at how we we could implement our own middleware so we're gonna do it in our products and again we could extract this out we can have it in a a completely separate thing if we want to but I think this is fine for now the size of the code that we've got so P products and it is going to be let's call it middle middleware product road of validation and the type of this is going to be the HTTP handler so this is gonna be the next handler that we're going to get and we need to return an HTTP HTTP handler so we're just gonna do return HTTP dot handler funk and we're gonna just do RW it should be phonce writer it's like standard pattern that's an interface it is not a reference but request is a reference so we we define our our middle way which is really straightforward what we're kind of gonna end up something which is gonna look like is this it's you know it's really really really really simple let's dig in alright so the the thing that we we want to be able to do is we want to validate that that request so we can take our our product and we can deserialize its okie and Prada is gonna be our product and we're gonna create a new one of those so it's data dog well actually we can just copy this really really really simple is he the best way to refactor so we're just saying that we're gonna just decode this product from Jason if we can't we're gonna return and that means that the the chain will stop dead we're not going to be calling any more elements in in this in this handler chain however if we succeed what we want to do is put that product somewhere so that we can use it later on so the place that we're going to put it is on to the request because the request has a context so I can define my my new context CTX and it's just going to be a request dot context and I can do with value if this would just autocomplete that would be asking too much first no big deal so context the the way that you kind of use a context in and go the HTTP context is then you you need to define a key you can use strings as keys but the kind of the preferred approach is to use types of scree so I can just quickly define it key something call it key product and it's just a type struct then what I can do my contacts with value I can use my key key product and we can specify our value so that adds the that will create me a new context from the context it's already on the request so the next thing I can do is just kind of create a copy of that request but I'm gonna call the upstream wave so that's just going to be our dock with context whoops context and then I'm going to call next next dot serve HTTP because it's a next as a handler and I'm going to specify my response writer and my request and that's that's all I need to all I need to define there so then now I've got my my middleware what I can do is I can I can use it so I created this sub brooder a sub Rooter has a use function which takes a middle way the middleware I've just created which is my middle bar a date product just this year I can apply that to both the put and the GATT request so now what we have is this middle way so the middleware will run the middleware will get executed before the actual handler code so in terms of the request the request comes in to the server it's gonna get picked up by the Rooter the Rooter is gonna say hey that's a put request send that to the put sub Rooter the put sub Rooter is going to say oh well I've got this middle way so it'll execute the middleware if that passes then it goes into the handle funk and the same for the post so we we now in our code for the put and our post well we are kind of doing all of this stuff we're getting the product out of that we can we can just completely remove all of that we can delete all of this code so update products we need a product where we're gonna get the product from but we're getting the product from the request so it is fraud whupped and it's gonna be request dot context dot dot value and then we're gonna use that key so key for product and of course this is just gonna return us an interface so we do need to cast it it's gonna be pretty safe just to cast this because it's impossible for anything to get into this function here without it going through the middleware first and the middleware we're ensuring that that's that's happening so we're just going to date a dot will just cast that like that and then in our post handler as well we can do exactly the same thing delete all that code which is always nice let's build our code what do we go an error there line 68 expecting func line products line 68 68 is it sure well it's not the right product because I was showing you that one as an example earlier one line 68 blah blah blah it's complaining about this so we got HTTP handler that returns there that will return HTV handler funk what am I doing wrong there just have a quick snoop oh gosh yeah I give up it's a funk is no all right come on what are you complaining about now did that save if anybody is completely new to go long and wondering why intellisense just does not work anymore it unfortunately is due to the move away from modules and into the sorry from in towards the the Google kind of modules of thing it is unfortunately gonna take a little bit of time and in the meantime you do end up with a sort of situation where you get somewhat working intellisense what am I doing wrong yeah I think I fixed that one up did it save expected funk expecting racket handle funk not handler well I am a little bit confused as to what I'm doing so I'm not going to bother you with me staring in a blank spaces to the Lord I'm just going to Wow it really is not yeah sorry yeah good good cool curricula byte we missed that one can I use type as product let's have a look products what is this what does update products take ok I take the reference so that's just update that and it will be the same input it takes a reference finally thank you chat all right so that's working there we can now just do our put again that blew up where to look that shouldn't work so whoops slash one ever read in product interesting it's not a data product let's have a look at our middleware see what is going wrong here so blah blah blah creating a new contacts contact with value key product that's like this is neck just all the problems today yeah good cool thank you very much chat all right so let's update T and so we've updated our T for our first product not what I wanted to do just wanted to do a guess but we've got T they're updated ours first product we can now add a new product we're gonna call this T what would quickly call it what what beverages would you buy it in Starbucks water some things and go of very weird yes Ivan I agree with you but then we handled our putt post there and we can get that and you see there we now have our third item called water so we've done a little bit of refactoring so we've refactored out the the code from last week we've now got this this kind of MUX Rooter in and I've been doing go for like I swear to you about seven years and it's still makes me trip over my feet we've got all of this that poster we got our put Reuter in there we've refactored our products so we've we've now kind of removed all of that nasty code which was kind of all that duplication the manual parsing of any of the you arise and and things like that and we've also kind of removed some duplication so we created this like middleware validation function which is a as I think is a is a reasonable use of how you can kind of see how to use the the Rooter in and gorila and I think then that's a kind of a pretty pretty good start so where do we go from here that is a very good question and next week what we are going to do is we're going to have a look at doing some validation on our struts so I'm gonna look at a package called go validator which I think's a really really really nice little tool and we can start putting validation on our button post requests we can check things like a minimal minimum lengths on struck fields that fields are present and the numbers and numbers and things like that and I'm thanking you again for watching I hope you're enjoying the series I'll put a link appear of the the previous the previous episode just in case you want to kind of go back and watch but I will see you next time next Sunday and thank you very much [Music] [Music]
Info
Channel: Nic Jackson
Views: 23,241
Rating: undefined out of 5
Keywords: go, microservices, JSON, RESTful
Id: DD3JlT_u0DM
Channel Id: undefined
Length: 43min 32sec (2612 seconds)
Published: Sun Jan 26 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.