Building Microservices with Go: 8 Auto-generating HTTP clients from Swagger files

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] all right how are we all doing we doing good are we doing fine I hope so I'm I'm pleased to be back and I hope you're gonna enjoy the show today one of the things that I'm gonna look at today is we're gonna kind of take all of that swagat documentation that we created last time and let's see how we can use it but let's see how we can use it this time for generating clients no FLE this will be a little bit of a shorter video but you know we'll kind of we'll get through it and I think you'll find it really quite interesting so without further ado let's take a look so what do we got well what we have is our documentation so let's do a quick recap of where we were last time so one of the things we were looking at is how we can use swagger and how we can use go to generate our API documentation so what we created was documentation looked like this let me just run my service oops not like that all right so I'm running my service so what I did was I generated my my documentation and I am using redock so that I can map all of that auto-generated documentation to this really nice kind of view here now we can generate it all of this last time when we added all of this to our code and the way that we we went through and did that was by using the go swagger documentation tool and go swagger documentation tool allows you to take things like go documentation standard go doc and using these special annotations which are defined here over in the the go swagger documentation it allows us to document all of our endpoints so for example we have an endpoint here called get and we can use this swag a route metadata and we can say ok get products and I want to call this list product and I want you to generate the documentation and it's going to return a product to response and again through the swagger documentation we're sort of defining what approach response is where it lives and the kind of the the full output of that is that we get this really rich documentation and we don't really have to do a great deal for it so we took that one step further and we created our own endpoint so we we are mapping slash Doc's and we're using the redox middleware and the redox middleware allows us to to be able to host our documentation website within our API service which is really really useful so I'm gonna stick the video up there for that if you want to go in quick recap on that but what I want to do des is look at how we can use exactly the same process and how we can generate HTTP clients that can be used from other applications and again I'm gonna use go swagger because go is what we're kind of we're at but you know because it's swagger and because it's an open standard you can actually use a number of different kind of clients if we kind of just do a quick search in Google swig swagger doc create client let's say Ruby you know there we go there's a swagger API code Jan which is a ruby gem so we can sort of generate this documentation for a number of different languages it allows us to kind of maintain that whole polyglot approach and it's just easy so let's see so how do we generate the the documentation so we're going to use the the same command the swagger command that we use to generate our specification and we can use this same command to generate an API client we can actually use it to generate our handlers and things but let's um let's take a look at this so the command is going to be swagger generate client now we're going to specify some options such as the name of the service and and the location of our specification let's go to try so what I'm going to do is I am going to just create a new terminal laughs so let me create a new folder and I'm going to call this client and then I can use that swagger command so what is that command so swagger let's have a quick look so specify what come on ok nice well we want to do generate I can do help so we can do swagger generate client and again help and that's the same documentation that we just saw there on the website but we're going to use this command to generate ourselves an HTTP client that we can use from go and I'm going to be honest with you I've never tried this this is gonna be brand new complete unboxing sorry let's hope it works right okay swagger generate client location of our specifications so it's in our API folder product API swag adagiamo what do we call it we're going to call it product API generating an error message so what's going on here well it's because we've got a slightly incomplete swagger specification and that's because I was kind of lazy in the last episode and I maybe didn't finish up this code properly but we can change this now so if we go over to this documentation see what it says it's saying the sweater specs invalid path parameter ID has no parameter definition so what this is referring to is that we have a parameter defined in one of our routes and we haven't actually defined the parameter in the documentation so the routes which have parameters are the get single product parameter M handler and the delete so we can see here that we have products and then there's that parameter there but we don't define where that parameter exists in this documentation and I think this is where it'll catch a lot of folks out where we define this is we define this actually where we define the parameter itself and we've put all of those things in Docs so if we scroll down let's have a look here we go here's the product API parameter and sure enough we have swagger parameters and we've got update product so when you kind of define those parameters we define the links on the parameter itself as opposed to on the root I'm kinda a little unsure on that about whether that's the best way to do it but it's not terrible as long as you know so let's add that and we've I think well what did we call this we called this let's call it less single list single product I'm just gonna give it a better name and we can save that so again we're gonna write that reference there so list single product okay so I'm I'm gonna make an assumption and I am pretty confident that I also haven't defined the delete API so if we look over here delete and again you can see that parameter and of course in the docs we don't have that as a reference so we can just specify that there so del leet product so that's how we do that kind of linking between these parameters here and the docs there so let's generate our API client again and we've we're just gonna use the make file for that which we set up last time so that's that's generated so now if I rerun my command my swagger generate client you can see that it's worked this time and let's see what this is actually generated for us so we have a client here and it's generated us some go code that's kind of neat so we have again an H what looks like an HTTP client so we can do new HTTP client and we can setup all sorts of things what also we got on this o we can this looks pretty sane let's check us out oh look this is pretty nice you can see here we have all of our methods and it's automatically generated the the paths and and everything like that for us which is pretty cool why don't we check out and see how we can do it so let's um I guess just add a simple test or something so we just add a new files can call it main test dot go package main and we're just gonna call this funk test our client oops testing dot t okay so we we have that test now so let's see how we can we can use it so in our main dot what do we got here products client where's the main entry point we have new and new takes a client transport okay and it also takes a registry what else have we got we just got basic new HTTP client which takes of formats string format registry interesting okay and we've got default transport config okay so let's take a look here I'm thinking that which one do we want to use I've got no idea any ideas on the chat no well guess we just go try them so we're just gonna pick this is try the new HTTP client and myself see and that's gonna be or come Rumble the name space on that Wars there it is in package client so it's client dot new well actually you've even got new you've got a default client so we've got new client as default that's pretty nice we can probably just try that actually it is client dot default and of course we're gonna just have to give it a little bit of a help on the import there oh I can never remember what why what this thing is called and using way too big so let's just cut and paste okay and we're not using the product API we are using the client and it is yeah just client client or client interesting let's just quickly run the test and make sure that everything's happy there so can I find get module yes that old a chestnut let me just move move that folder let's try it again bla bla bla no I won't anymore so you could put this in a separate folder put in a separate package separate github repo you might not even keep it with your application you might keep it completely separate it might be part of the the destinations application but it's it's pretty nice anyway come on give me a break computer what are you what are you complaining about product API client client I mean admittedly that's probably not the sensibles gosh Kumada get up calm because Jackson building micro services in the YouTube / client / client which is where it exists at exactly the same all right thank you very much go mod does not count products it does because we have client client products there I wonder if it fuse because I've got let's call it SDK let's run this what is going on here imports YouTube client client products no it isn't well I'm not it's just gonna be one of those days when go mop defeats you isn't it product API SDK package ci SDK imports SDK client and it imports but where does it import that file oh there that's where it imports that far well there's a an interesting lesson for you all it seems to as it turns out you you probably want to generate it in the in the correct folder because it generates all of the sort of the package references for you and I didn't do that so tell you what I'm gonna do I am going to delete all of this I'm going to put my test and put that over there let me delete permanently yeah I wanted to lick permanently let me just run that command again so I'm going to say generate client and do I want to run that from the SDK folder probably Wow all the problems but nothing else what this episode is teaching is how I can add debug some things when they don't go as you would expect them to and all of the things that's happening today make SDK CD SDK okay now we are going to do that generate command again and we are going to generate the API which is in the previous folder look a call product API and there we go right finally you're gonna be nice to me uh you're not gonna be nice to me because why you not being nice to me go cannot find a module which folded I put that in the wrong folder okay right after all that we're getting somewhere so we now have everything up and up and running so we're using our client there and we've got client default and of course the language server is not working properly because it never does so let me just bounce that window and open it up inside the right folder and there we go okay so now we've we've got that intellisense working so we've got our our API and we've got everything hooked up and we've got the code finally generated and we've learned that we have to generate the SDK from the final destination path otherwise all of our imports are going to be kind of screwed up but we can we can call that now so we can call product start create products and list products well let's do list products and we've got these list product params okay so that is I'm guessing client dot list product params it's all right to look at where it expects to find those so you can just jump into that and go to the definition so the params are definitely list product params which resides in the o of the products package okay products dot and then what else we got here new list product params with context okay so this is interesting new list product parameters you set bunch of stuff that okay oh so we can that let's run it and see what happens mm-hm interesting okay so we get back a list of products and an error let's check this out so frauds and error and what I'm going to do is I'm going to say if error is not equal to nil I'm just gonna do t dot fatal error and then format dot print line prod let's just have a quick look at what we get back there so we're getting connection refused and that's because the the direct what we're trying to dial is one of law eighty and we don't have our service running on eighteen we are running on well 1990 so if you look at where it got those defaults from it got those defaults from the documentation because we specified here the scheme we specified the base path and all sorts of stuff like that but we can we can override that and it's it's not it's not going to be a problem if thing find their right so how are we gonna go and do this override well let's have a look and see what params has for us so we can set the HTTP client we could set the context have no idea how you set the actual URI so we have this in the transport [Music] where does it set the URI interesting so look in the product client so we have default host year which is a constant [Music] transport config in there so watch one can we use to create a new one of these so we can create a transport config will host and how do we create new one is interesting so here transport config and with registry is a registry of string formats with validation methods I don't really want to touch that I just want to generate okay transport not so interest not so easy I'm thinking so you actually be client right let's have a look at this now it seems that you can do new it should be Cline here with nil for these registry settings so I'm guessing I can do the same thing here in specifying nil and transport config so let's give that a try so instead of doing the default what we're gonna do is we're gonna create our config so this is going to be client dot and oh we can just get the default default transport config and then we can set ok that's interesting so we can actually just set transport config with host and we're gonna use local host 1990 and then instead of using client of default what we're going to do is we're gonna use new client with config we're gonna pass nil as the first parameter and then we're going to pass our client configures the second and let's see if that works and of course not supported by the text email well you can see that we've actually made the call there because we've we've made the call to get all records and see that in the in the server so the the transport has actually call to what is going on that I can't answer so let's have a look so we have main text echo is not supported by text consumer that can be resolved by text Marshall I'll tell you what I'm gonna do I'm gonna cheat just one second I'm just gonna use client dot default and I'm gonna go over here and I'm gonna change this and I don't recommend we do this in but I want to check to see if it will make a difference no makes no difference at all so we've got this cannot be resolved by the text unmarshal err well let's take a look maybe it's something to do the way that we generated the spec so list products okay for our enough so we can right click here and we can go to implementations look at the parameters all of this is correct the reader okay the result this products of okay transport submit list product reader huh read response so if it's a 200 we're going to read the response of the result this I think is one of the issues with using Auto generated code when it works it works brilliantly and when it doesn't I don't wish it on my worst enemy because you just kind of debug it but let me just check here that this is actually working localhost 1990 products and we definitely there have a list of products so let's take a look and why this is not working main top test list products let's take a look at what it thinks implementation at least this is defining interfaces so it's nice for stowing it out product reader read respond the pay lope models dot product let's have a look at what it thinks this is and that looks absolutely fine to me it's even got a nice little bit of there which is which is pretty cool this is all of this has been picked up from the documentation so that's that's actually quite nice doesn't help me understand why it ain't working models product why would you pass a slice why would you pass a reference to a slice of references that I just cannot answer you I'll get there don't worry let me just try something in my dog's so I'm using this interaction to generate me nice documentation but I've got product response here what if I change this to a lot a single try change in that to just and a slice of pro data dot product and let's just run that swagger again and now they can run run our code Chan again on our client best object there's no key dated of product okay so that didn't work well it wasn't that well I'm pretty stucked I have to say I this thing has got me beat so guess what probably end up doing in the next episode is me spending some time working out why this thing does not work and I'll fix it and I'll show you what and I'll explain exactly what I did to find that what we can also do if you're still hanging around and you've got a few minutes why don't we step debug this that's one of the nice things about working with sort of stuff so right put this back in the way we had it so we're changing the the the client we are going to do client and we're going to do which one was it new with config pounds nil and that's CFG right now so we run this we see that bounces that fails that's what we expect but did get called there so let's do that step debug through this so we can debug okay it's gonna put a breakpoint there so the debugger and Visual Studio code I'm hitting that breakpoint now what I can do is I can step over it I can just continue to the next breakpoint or I can step into it let's step into it so now we're into the list products parameter so I'm gonna step over that we can see that's defining the parameters that's all fine step over there defining my client my reader and all sort of this internal stuff all of that is just getting set up let me just put a breakpoint there and I can skip through this right it's the next step so do have an error well you can see on the right hand side here that we do we have an error so the error has come from that same thing so it's the somewhere inside this reader or inside this submit command where things are going wrong so let's just stop that and let's just kind of run through that again debugging test okay so we're gonna step into this and then we put our list products what I want to do is go to that I'm gonna step into the submit command so now I can skip over everything that's going on here so let's have a look we are going down we're doing new requests again this is all cogent and stuff so it's not particularly interesting to us but we can kind of see the HTTP request that is getting created we're hitting slash products method GATT this is all good it's kind of using a writer here which I guess for writing the body which we don't have one in this instance and we're kind of gonna do the except let's have a look at what what it will accept so that should be the header so I'm guessing client Jason application Jason yeah okay skip over this then default like an indication we don't have any default authentication we're not defining any particular media type application Jason so then do some stuff build HTTP this is about 50 more lines of code than I would write to do an HTTP well pick the scheme set the host and then we are going to create a client we could actually have debug on which is interesting wow this is interesting this is kind of where the body is going to come into so let's just come down here so this is actually the httpclient do method so step over that what have we got have we got an error no so we will have a response now the response is going to be OS res response is going tough gosh oh there we go it's just too far my last name is crow so the response standard HTTP response state is 200 which we got from our thing and then we get a read closer and that's that's just a string so skip over that and over that let's a look get the header content type and then we have this pars media type so let's look oh look at that that's interesting now our service is just returning text plane but the client is expecting application JSON which makes sense now normally the sort of the media camp you don't pay a great deal of heed to it I'd like to bet that what is going on here is that we are going to be doing that and that's where we're getting the error from it's getting an error because it it doesn't know what content type to parse it thinks it's text plain but it should be application Jason which is what it's expecting here you see so that's just let's hit play play again it really they're driving me nuts and I don't care anymore all over all the breakpoints right and of course that that that fails so I think I know what's going on now so if we look at our service and we specifically look at our our product API well what we are doing in our not get handler is richest returning tax plane which is the default for service but we're actually we've told the from the swagger spec that we are returning application Jason what kind of not doing that so here we're doing data dot - Jason - right so let's add the response header see if that makes a difference so we're gonna do our W dot and we are going to do header dot pad and it is con 10th type and the value is going to be not that it's are going to be application Jason and let's just run our application there again and let's just double check first that we're going to get that header so curl localhost 1990 put V on Jesus that fullscreen button in Windows which is f11 or whatever it is really drives me up the wall because I keep hitting it by mistake but when duco localhost - be logos 990 slash products so content type application Jason on the 200 sponsor that's what we asked what we expect let's run our test again ok it's passing now interesting so let's just I'm just gonna fail the test so that I can I can get the output there and there we go we are getting some products so if I do print F let's do percentage hash fee a test and we do have this slice of products which is exactly what we were expecting to get back so let me just do the first one in that slice though and it doesn't support indexing okay that's interesting dot okay get payload this returns a model so let's try this okay so now we can start seeing those those products so actually there it is there look that's the model I'm pretty impressed with this actually I've been twisting and complaining at you for the last 40 minutes through to nothing other than my own stupidity but I think this is this is quite quite nice we've we've kind of defined all of this documentation just using the swagger spec and now we've generated this this client we also discovered and unfortunately that well as swagger spec was kind of missing some stuff we weren't returning the right content type headers and it seems that this Waguespack genuinely cares about that when me I'm too lazy I just don't but we've also I think learned that it really isn't very easy to to try and debug or who generated code but as you mean you don't make silly mistakes you shouldn't shouldn't have to this is literally about 20 minutes longer than I intended on this less lectured lesson and for that I do apologize but you know I hope the the kind of the things that we've been looking at I hope in some ways it's been useful to you I think I the process of running through and debugging stuff you know maybe that's useful to next time what we're going to look at well I'm going to tidy up this code and I'm gonna check it in for you all and I'll put the link in the thing below I'm pretty much finished here with swagger and almost finished with rest there is one more thing which I want to show you and the thing that I want to show you is is a kind of a little neat thing that I've been working on which is a very very simple file server and why I think it's cool is because I'm gonna show you how we can use the default HTTP file server and how you can override the behavior to implement gzip which is great for files we'll do that in Sunday so again thank you so much for watching like and subscribe smash the bell button that's the thing to go to say I look forward to seeing you on Sunday and until then I hope you have a great week
Info
Channel: Nic Jackson
Views: 11,816
Rating: 4.9358974 out of 5
Keywords: go, microservices, JSON, RESTful
Id: Zn4joNjqBFc
Channel Id: undefined
Length: 46min 4sec (2764 seconds)
Published: Wed Feb 12 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.