Building Microservices with Go: 3. RESTful services

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
all right what are we gonna look at today well today what we're going to look at is how to build restful services with go in the previous two episodes we've looked at sort of things like how to build a very very simple service and we've also looked at how do we kind of restructure that simple service and starting to kind of look at some of the patterns that we will use as and when we are moving forward but I really want to start digging into restful services because I think restful services are some of the the most common that you will will use all right so first things first rest well what is rest for a good question I hear you ask well rest is is a kind of term which stands for represent a representational state transfer so it's an architectural pattern proposed by Roy fielding and I think you'll find this is one of the most commonly used patterns certainly with regard to consumer api's G RPC totally different ballpark we will look at G RPC later on but right for now we're gonna concentrate on rest so what do we mean by rest well most commonly what you people mean when they sort of saying rest is Jason over HTTP and I don't think that's too wrong a kind of a statement but rest has some some sort of very specific kind of way that you go about structuring your api's so you know for example you structure things in terms of resources and you use HTTP verbs like get post update delete rather than using kind of like a controller approach where you might have you know get products as a as an API endpoint you don't need gap products if you're gonna have an API which is products and then use the HTTP verb get just go to mark that as though as a get pros alright so but that's kind of like that's kind of all cool and Jason so we you will kind of often see that folks are using Jason for for for for data interchange in and out of their their services you you absolutely don't have to use Jason I don't believe there's anything in the restful kind of specification that states that you must use Jason but it's very common Jason is certainly very easily serialized in a multiple number of different languages so it's it's one of the most sort of common data formats you'll see so we're gonna kind of start digging into this and we're gonna start taking that service that we built in the previous episode and we're going to make it restful so let's look at our source this is where we we left off so we'd we defined our kind of our server pattern and we'd started to break out all of our handlers into separate files so we've got our hello and our goodbye handler so we're actually going to say goodbye to this a very very simple example and hello to a brand new one in this episode because what I want to start to do throughout this course is try and build a real-world application I don't want to just be building senseless toy code hello hello world it doesn't really help you so we're gonna kind of follow an approach of building an e-commerce type site where we're gonna build actually a brand new online coffee shop and by using that real-world example what I can do is I can show you the various different layers that are involved in a micro service application so things like the sort of the product API is presentation layers but also kind of back-end services caching the requirements for security all of those things we can much much easier ly demonstrate when we've got this real-world multi-tier application and this week that's what we're going to start so we're going to start with the product API so in our product API what we need is the ability to return some coffee and and this is going to be consumed by the the front-end the website and it's also going to be consumed by the mobile app because everybody needs a mobile app so we are going to use data for that s re and Jason for that data rate at interchange format so let's start digging into that alright so this is going to be our product structure and I've just kind of created this ahead of time it's it's pretty pretty straightforward structure so what we have is an ID and this is going to be the unique ID of our product or our coffee we're going to give it a name a description it's gonna have a price a SKU which is just the kind of the the internal product ID and then it's gonna have some some basic kind of stuff like when it was the product was created updated and deleted and and this is kind of this sort of the typical stuff that you might find in a database we are not going to to use a database in in this episode we will start looking at databases in in a sort of a future episode but for now we're just gonna keep things simple we're going to just have a statically defined product list so I've got two products here I have one which is a latte and one which is an espresso and that hasn't spelt correctly nevermind so let's start to look at how we can return this information from from our API so this hello handler I'm actually just going to add a brand new a brand new handler I think it's probably the quickest way to go and we'll delete these in a little bit I'm just gonna call it product I might reflector that out later but but for now products so package handlers and type type products so if you remember we we kind of said that we we don't want to call it products handler because it's already in the handlers package kind of this is one of the nice things about go when you start a structure your code you can kind of use packages to to kind of add to the name or the meaning of your um your structures so again we're gonna we're gonna put a logger in there that is going to be of type log dot logger and I'm gonna create that new function which is kind of that idiomatic go based approach so func new products and it's gonna take a logger it's going to return our product handler so I'm just let me just fill in those details all right so we need our service GDP because this is going to be an HTTP handler again just a quick recap from last time anything that that here's to the HTTP handlers interface needs to have that serve HTTP methods or funk P oops products serve HTTP signature for that is an HTTP response writer which is an interface and an HTTP request all right so we are good we can fill in the the details around naming and things like that later so we've got this product list and what I want to do is I want to make a get request to serve HTTP and I want to return this product list so how can I do that well what we need to look at is a package called encoding dot JSON so encoding JSON in the go standard library allows you to marshal a strut or any sort of reference into and out of Jason so we can convert our product strut that we have here and we can convert it into the JSON representation so something that's going to you know look like all of this stuff and it works really really really easy there's there's kind of two main ways that you go about using encoding Jason and I'm gonna show you both of them and I'll explain my preferred choice but first so let's get this let's get this going right so in our main dot I'm just going to add my product handler in here new products and I'm gonna reference that just in my route so everything there will will be fine and we'll clear the other stuff up later on okay so we want to return our information so how do we do that so I have a let's add a method to my my products package and and this is going to be my my data access model so whether I'm using a database or whether I'm using just a fixed list or a text file or whatever it is here I always find it useful to kind of abstract that detailed logic of where the data is coming from from the the rest of the code so rather than kind of exposing the data connection and doing the sequel right in my handler I tend to put that into a method or a function on my my data object so I'm gonna call off I'm gonna add a function to my data and I'm just gonna call it get products get products it's gonna return all of my products and it's gonna return a list of product so this is very very simple because we are just using a sort of a statically defined list but I'm just gonna return my my product list oh gosh back trying the right key on the keyboard evidently not all right and then we can go back to our handler so we now our handler what we can now do is we can get a list of products so let's call this LP list of products and we're gonna call data dot get products so now LP is going to contain a list of products so how do we return that to the user now the way that we do that is by converting LP into a jason jason byte array or Jason string and we do that using and coding Jason so the the kind of the simplest method if you look at sort of the the signature is jason dot Marshall so let's take a look at oh I don't know what happened there Jason dot Marshall and let's have a look at that that signature inside of the documentation so we have Marshall so Marshall returns the JSON encoding a V and it's going to return it as a byte slice of bytes but it says here it's going to traverse the the object that you pass to it recursively and it's going to convert all of the field names and all of the the values into valid kind of JSON structure nice and easy so let's see that how that works so Jason dot Marshall I pass it my my interface so I can pass it LP and that's going to return me a slice of data and an error okay so let's do that go go defensive programming we're gonna do if error is not equal to nil then we're gonna say HTTP error so we're going to use that convenience method RW unable to Marshall Jason in reality we're gonna probably want to return a more friendly use a message something that's meaningful to to users but that'll do for right now and that's going to be HTTP status status in turn all turn now internal server error so I've now got this data and then what I can do is I can take my response writer and if you look at the signature for response writer it has this write method so I can just simply write my data out there so let's um let's take a look at that let's run it so got my server's running there I'm just gonna create another terminal and I'm gonna curl it so curl localhost 1990 and there we go so we've got that JSON representation now I'm gonna curl that and I'm gonna pipe it into a really handy little command called JQ and it's gonna give me a little bit better formatting so you can see that that that product information that we we defined in our data our data package has user through the JSON serializer it's just been converted our and Jason now there's a couple of things that I don't like about this so I like using camelcase so I don't want ID as a capital in my Jason I want Aidid lowercase and I want description as lowercase and price and and actually I really don't even want to include the created on updated on and deleted on so I'm going to I want to remove those so how do I do that well what you can do through the the kind of the the Jason package is you can use strut tags so if you don't know a strut tag is a is a kind of a special feature of go which allows you to add these annotations to a field and then you can write parsers to pick up those annotations so Jason as encoding Jason has these strut tags of field tags so if I write Jason then what I can do is I can change the name of the output so for example here I could rename the output field as my name or here I could rename it my name and I could completely omit it if it's empty what this examples showing me is that just completely ignore it from the JSON output all together so let's see that in action so we have ID so I'm gonna use that strut tag Jason right and then I'm gonna give it its name and I want to call it ID lowercase like that I can do the same for name Jason name and description the price whoops the SKU so I'm converting all of this into camel case now with created on I don't actually want to return that as part of the API those are internal fields and I'm only using inside the database so I'm just going to completely omit those from the output we could do that like so now we can save that so let's let's see that in action so I'm just gonna restart my server and then I can again curl it so now you can see the difference there you see that those strut tags the effect that they've had is that the ID is now lowercase name description all of those things and the created on the updated on and the deleted on are not present I've I've actually emitted those completely from my my output which is really nice so that's all relatively straightforward let's um let's kind of see how we can kind of tie you this up a little bit how would we kind of change this around so I can use Jason Marshall like this but if you look at the documentation what you will see is that the Jason package also has this encoder so rename coder what this does is it can return the new encoder that it's gonna write to W so then what I call an encode azzam method and code so encode will write the JSON encoding of the type followed by a new line character so in a sense it's doing exactly the same as what Marshall is doing but rather than returning it a slice of data and an error it's writing the output direct to an i/o writer now you remember we've got an i/o writer because the response writer which is part of the HTTP handler is an i/o writer it implements the the writer interface so I can actually pass writer to my new encoder and then I can write directly to it but well why would I want to do that why don't I just use the kind of the the standard Marshall it's pretty clear and simple well the reason that I want to use an encoder and why I want to write direct is because I'm not having to buffer anything into memory I don't have to allocate memory for that data object now if you've got a large JSON document then you know that that could be a real a real consideration the encoder is also faster and and I'm kind of not got any benchmarks here but I'll add some benchmarks to the to this code base and we you can just kind of see that but it's marginally faster as well than using Marshall which while that's not necessarily important when you've only got a single thread when you're building a micro service if that micro service is gonna have a number of different threads it's doing a number of different concurrent operations you want to be able to take advantage of all of the port form and so you can and this is a quick win it's not an over optimization it's just using a different method on the encoder so let's implement this so one of the things that that I like to do again is I like to keep my handle as clean and not necessarily I don't really want to see sort of too much noise going on here so what go actually has this really nice capability so rather than kind of returning a slice of product like this what I can actually do is I can define a type which is a slice of product so I could define type I'm going to call it products and it is of type product now why I want to do this is because I can then add a method to this so func in the same way as I would do it if it was a strut P products and I'm going to add a method I'm going to call it to Jason and it's going to take an IO and I a writer and it's gonna return an error so now what I can add is I can encapsulate all of that logic for all encoding my Jason into this nice little handy method here so let's do that okay so I need to create the the encoder so encoder which is going to be Jason dot new encoder and I'm gonna pass that the writer now what I can do is I can return e dot encode and I'm going to encode myself let me just save that up so encode is going to return an arrow my method written has an error as a response and this way I can just kind of encapsulate that logic there nicely inside of this this to Jason so if there is anything that I wanted to do if I wanted to do some manipulation before I output it as Jason I can do so then in my handler what I can do is I can just call LP dot to Jason and I pass it my response writer and this is kind of much much cleaner because it's just kind of abstracting some of the implementation details it's kind of a nice practice to do this okay so gap products there is is complaining let me just change the signature of gap products rather than it defining returning a light a slice I'm gonna return my my custom type of course the two are directly in the changeable so again let's just test this everything should be working well it would be fired not made a typo par for the course I think you will find okay well we don't need this anymore oops and there we go so it's working in in exactly the same way as we we had it before but we're we're just kind of saving a couple of a couple of steps there we're also making our code a little bit quicker all right so that's writing Jason which is all kind of simple but how do we how do we read Jason good question I hear you ask so let's have a look at that so we want to to implement now get and we want to implement post so this is get products it's only going to be get requests so that's going to use the HTTP verb get so this is kind of following that represent tional representational state transfer the rest based approach so let me just refactor a little so I'm gonna add a new function I'm just going to call it P and I'm going to call it get products so this is an internal function it is going to have read HTTP dot response writer so exactly the same signature request and it's just going to do all of this stuff in here because what we want to be able to do is when a request comes into the server we want to determine well where is it bound is it a gat wait as in are we wanting to retrieve the products or is it a post do we want to create a new product or maybe a put we want to update a product so in the eat they could go standard like a lujah the go standard library doesn't really have very good provision for for kind of managing that person make excellent frameworks like gin and my personal favorite the the guerrilla framework and we're gonna kinda look at those but first we want to look at the standard library let's see how standard does it and then we can really see the benefit of using a framework of course if we need the maximum performance then maybe we just use the the bear standard library but let's take a look at that so recapping we have a handler which is on the root path and it's going to call our products handler so when a request comes in to the server regardless of whatever the path is because we're going to handle all parts with this it's gonna hit our product server so internally the go server is going to call our handlers serve HTTP method so we need to make some some logic decisions in here so we're going to say if the request I don't know why I call that H and then change out our Eric and I was say the wrong button there if H dot method so the request method if that equals HTTP dot method get' so if this is a get request then what we want to do is call our gap products so I'm just going to chain that up call gap products same record response writer and forward on the request and then I'm going to return for anything else I'm gonna have this catch-all and I'm going to write HTTP not implemented method not allowed so for any other method I can just add this generic kind of catch-all method not all allowed and I'm going to return so now let's quickly kind of see this in in action so again I'm just going to clear this rerun my server and I'm gonna curl it so I'm curling it and I'm curling it with a get so that works perfectly fine now if I just change this to X let's just say X delete so X delete what that's doing is that's going to just change the the the HTTP verb that curls going to use and you can see there that we get back method not allowed you can see requests there so that's the the raw request that the curl has sent and that was because of this block here so we've done our dot method and Method or get then get products so we want to handle an update so to handle an update using this kind of this API or this restful based approach then we're going to use a different HTTP verb and the HTTP verb that quite often people will use is cut so a put either creates or replaces the resource at a specific URL so we're going to we're going to implement this and to do this we're also going to see how we can post sre we can we can send and read jason from the server and we're going to do that in the next episode the next show which will be wednesday at 8 p.m. GMT all of the the resources from today I'm going to include in the description just down there and I'm also going to put the the links to the documentation for the the Microsoft docs on represent on REST API is the Jason packages inside of the go standard library and also the if you want to look at the JSON specification and then have a look at it I think probably I'll be honest with you I'll find about a link because if you've never seen Jason before looking at that specifications not the best place to start I'll I'll pull up a link out of Wikipedia or something for you that'll all go in the link down below Wednesday we're gonna start implementing that put request to do our updates please like and subscribe to kind of keep keep up to date with notifications for channel and also all of the previous episodes episode one and episode two can also be found in the the playlist now I'll still make sure there's a link for that as well as always it has been a pleasure thank you so much for joining me I'm hope you're enjoying this if you are please comment if there's anything you would like me to cover again please comment and we will see you I guess next time latest
Info
Channel: Nic Jackson
Views: 42,113
Rating: undefined out of 5
Keywords: go, microservices, JSON, RESTful
Id: eBeqtmrvVpg
Channel Id: undefined
Length: 32min 44sec (1964 seconds)
Published: Sun Jan 19 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.