{"id":5123,"date":"2017-06-10T10:38:02","date_gmt":"2017-06-10T10:38:02","guid":{"rendered":"http:\/\/putridparrot.com\/blog\/?p=5123"},"modified":"2017-06-10T10:38:02","modified_gmt":"2017-06-10T10:38:02","slug":"rest-services-with-mux-and-go","status":"publish","type":"post","link":"https:\/\/putridparrot.com\/blog\/rest-services-with-mux-and-go\/","title":{"rendered":"REST services with Mux and Go"},"content":{"rendered":"<p><a href=\"https:\/\/github.com\/gorilla\/mux\" target=\"_blank\">Mux<\/a> is a &#8220;powerful URL router and dispatcher&#8221; for Go and that means it allows us to route REST style requests to produce REST\/micro services.<\/p>\n<p><strong>Creating our service<\/strong><\/p>\n<p>Let&#8217;s start out by creating a very simple EchoService which will contain our service implementation.<\/p>\n<p>In my code based I create a service folder and add a service.go file, here&#8217;s the code<\/p>\n<p><em>Note: This creation of a new go file, interface etc. is a little over the top to demonstrate mux routes\/handlers, but my OO roots are probably showing through. In reality we just need a simple function with an expected signature &#8211; which we&#8217;ll see later.<\/em><\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\npackage service\r\n\r\ntype IEchoService interface {\r\n\tEcho(string) string\r\n}\r\n\r\ntype EchoService struct {\r\n\r\n}\r\n\r\nfunc (EchoService) Echo(value string) (string, error) {\r\n\tif value == &quot;&quot; {\r\n\t\t\/\/ create an error\r\n\t\treturn &quot;&quot;, nil\r\n\t}\r\n\treturn value, nil\r\n}\r\n<\/pre>\n<p>We&#8217;ve created an interface to define our service and then a simple implementation which can return a string and an error. For now we&#8217;ll not use the error, hence return nil for it.<\/p>\n<p>Before we move onto the Mux code which will allow us to route requests\/responses, let&#8217;s create a bare bones main.go file<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\npackage main\r\n\r\nimport (\r\n   &quot;goecho\/service&quot;\r\n)\r\n\r\nfunc main() {\r\n   svc := service.EchoService{}\r\n}\r\n<\/pre>\n<p>At this point this code will not compile because we haven&#8217;t used <em>svc<\/em>.<\/p>\n<p><strong>Implementing our router<\/strong><\/p>\n<p>Before we get started we need to run<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\ngo get -u github.com\/gorilla\/mux\r\n<\/pre>\n<p>from the shell\/command prompt. <\/p>\n<p>Now let&#8217;s add the code to create the mux router and to create a server on port 8080 that will be used to connect to our router (and service). We&#8217;ll also include code to log any fatal errors (again this code will not compile as the previously created <em>svc<\/em> variable remains unused at this point)<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\npackage main\r\n\r\nimport (\r\n   &quot;goecho\/service&quot;\r\n   &quot;github.com\/gorilla\/mux&quot;\r\n   &quot;log&quot;\r\n   &quot;net\/http&quot;\r\n)\r\n\r\nfunc main() {\r\n\r\n   svc := service.EchoService{}\r\n\r\n   router := mux.NewRouter()\r\n\r\n   \/\/ service setup goes here\r\n\r\n   log.Fatal(http.ListenAndServe(&quot;:8080&quot;, router))\r\n}\r\n<\/pre>\n<p>I think this code is pretty self-explanatory, so we&#8217;ll move straight on to the implementation of our route and handler.<\/p>\n<p>I&#8217;m going to add the handler to the service package but this handler needn&#8217;t be a method on the EchoService and could just be a function in the main.go (as mentioned previously).<\/p>\n<p>You&#8217;ll need to add the following imports<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nimport (\r\n   &quot;net\/http&quot;\r\n   &quot;github.com\/gorilla\/mux&quot;\r\n)\r\n<\/pre>\n<p>and then add this method, which is the handler and will call into our EchoService method. <\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nfunc (e EchoService) EchoHandler(w http.ResponseWriter, r *http.Request) {\r\n   vars := mux.Vars(r)\r\n\r\n   result, _ := e.Echo(vars&#x5B;&quot;s&quot;])\r\n\r\n   w.WriteHeader(http.StatusOK)\r\n   w.Write(&#x5B;]byte(result))\r\n}\r\n<\/pre>\n<p>To allow us to call the EchoService Echo method we declare a variable <em>e<\/em> for the EchoService. The arguments, of types ResponseWriter and Request are required to decode a request and to allow us to write a response. In this example the <em>mux.Vars<\/em> will be used to get us part of the rest command\/URL. <\/p>\n<p>Again, we&#8217;re not bothering (at this point to worry about the errors, so <em>result, _<\/em> is used to ignore the error.<\/p>\n<p>Next we write a Status OK code back and write the result back as a byte array.<\/p>\n<p>Obviously we now need to set up our handler in main.go, so replace the line<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n\/\/ service setup goes here\r\n<\/pre>\n<p>with <\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nrouter.HandleFunc(&quot;\/echo\/{s}&quot;, svc.EchoHandler).Methods(&quot;GET&quot;)\r\n<\/pre>\n<p>this simply creates the route for calls onto http:\/\/&lt;hostname&gt;\/echo\/??? (where ??? is any value which gets mapped to the mux.Vars[&#8220;s&#8221;]) through to the supplied handler (svc.EchoHandler) using the GET method.<\/p>\n<p>For example, navigating to http:\/\/localhost:8080\/echo\/HelloWorld in your preferred web browser should display HelloWorld.<\/p>\n<p>We can add multiple routes\/handlers, for example let&#8217;s create a handler to respond with &#8220;Welcome to the EchoService&#8221; if the user navigates to http:\/\/localhost:8080. Place this function in main.go <\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nfunc WelcomeHandler(w http.ResponseWriter, r *http.Request) {\r\n   w.WriteHeader(http.StatusOK)\r\n   w.Write(&#x5B;]byte(&quot;Welcome to the EchoService&quot;))\r\n}\r\n<\/pre>\n<p>and add this handler code before (or after) your existing handler code in main<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nrouter.HandleFunc(&quot;\/&quot;, WelcomeHandler).Methods(&quot;GET&quot;)\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Mux is a &#8220;powerful URL router and dispatcher&#8221; for Go and that means it allows us to route REST style requests to produce REST\/micro services. Creating our service Let&#8217;s start out by creating a very simple EchoService which will contain our service implementation. In my code based I create a service folder and add a [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[178,164],"tags":[],"class_list":["post-5123","post","type-post","status-publish","format-standard","hentry","category-go","category-rest"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/5123","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/comments?post=5123"}],"version-history":[{"count":3,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/5123\/revisions"}],"predecessor-version":[{"id":5126,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/5123\/revisions\/5126"}],"wp:attachment":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/media?parent=5123"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/categories?post=5123"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/tags?post=5123"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}