{"id":3713,"date":"2016-03-19T12:48:15","date_gmt":"2016-03-19T12:48:15","guid":{"rendered":"http:\/\/putridparrot.com\/blog\/?p=3713"},"modified":"2016-03-19T12:48:15","modified_gmt":"2016-03-19T12:48:15","slug":"getting-restful-with-suave","status":"publish","type":"post","link":"https:\/\/putridparrot.com\/blog\/getting-restful-with-suave\/","title":{"rendered":"Getting RESTful with Suave"},"content":{"rendered":"<p>I wanted to implement some microservices and thought, what&#8217;s more micro than REST style functions, executing single functions using a functional language (functional everywhere!). So let&#8217;s take a dip into the world of Suave using F#.<\/p>\n<p>Suave is a lightweight, non-blocking, webserver which can run on Linux, OSX and Windows. It&#8217;s amazingly simple to get up and running and includes routing capabilities and more. Let&#8217;s try it out.<\/p>\n<p><strong>Getting Started<\/strong><\/p>\n<p>Create an F# application and the run <em>Install-Package Suave via Package Manager Console<\/em>.<\/p>\n<p>Now, this code (below) is taken from the Suave website.<\/p>\n<pre class=\"brush: fsharp; title: ; notranslate\" title=\"\">\r\nopen Suave\r\nopen Suave.Filters\r\nopen Suave.Operators\r\nopen Suave.Successful\r\n\r\n&#x5B;&lt;EntryPoint&gt;]\r\nlet main argv = \r\n\r\n    let app =\r\n        choose\r\n            &#x5B; GET &gt;=&gt; choose\r\n                &#x5B; path &quot;\/hello&quot; &gt;=&gt; OK &quot;Hello GET&quot;\r\n                  path &quot;\/goodbye&quot; &gt;=&gt; OK &quot;Good bye GET&quot; ]\r\n              POST &gt;=&gt; choose\r\n                &#x5B; path &quot;\/hello&quot; &gt;=&gt; OK &quot;Hello POST&quot;\r\n                  path &quot;\/goodbye&quot; &gt;=&gt; OK &quot;Good bye POST&quot; ] ]\r\n\r\n    startWebServer defaultConfig app\r\n\r\n    0 \/\/ return an integer exit code\r\n<\/pre>\n<p>Run your application and then from you favourite web browser, type in either <em>http:\/\/localhost:8083\/hello<\/em> and\/or <em>http:\/\/localhost:8083\/goodbye<\/em> and you should see &#8220;Hello GET&#8221; and\/or &#8220;Good bye GET&#8221;. From the code you can see the application also supports POST.<\/p>\n<p>Let&#8217;s test this using Powershell&#8217;s Invoke-RestMethod. Typing <em>Invoke-RestMethod -Uri http:\/\/localhost:8083\/hello -Method Post<\/em> and you will see &#8220;Hello POST&#8221;.<\/p>\n<p><strong>Passing arguments<\/strong><\/p>\n<p>Obviously invoking a REST style method is great, but what about passing arguments to the service. We&#8217;re going to need to add the import <em>open Suave.RequestErrors<\/em> to support errors. We can read parameters from the commands using <em>HttpRequest queryParam<\/em><\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\n let browse =\r\n        request (fun r -&gt;\r\n            match r.queryParam &quot;a&quot; with\r\n            | Choice1Of2 a -&gt; \r\n                match r.queryParam &quot;b&quot; with\r\n                | Choice1Of2 b -&gt; OK (sprintf &quot;a: %s b: %s&quot; a b)\r\n                | Choice2Of2 msg -&gt; BAD_REQUEST msg\r\n            | Choice2Of2 msg -&gt; BAD_REQUEST msg)\r\n\r\n    let app =\r\n        choose\r\n            &#x5B; GET &gt;=&gt; choose\r\n                &#x5B; path &quot;\/math\/add&quot; &gt;=&gt; browse ]\r\n            ]\r\n\r\n    startWebServer defaultConfig browse\r\n<\/pre>\n<p>Disclaimer: This is literally my first attempt at such code, there may be a better way to achieve this, but I felt the code was worth recording anyway. So from our preferred web browser we can type <em>http:\/\/localhost:8083\/math\/add?a=10&#038;b=100<\/em> and you should see <em>a: 10 b:100<\/em>.<\/p>\n<p><strong>Passing JSON to our service<\/strong><\/p>\n<p>We can also pass data in the form of JSON. For example, we&#8217;re now going to pass JSON contain two integers to our new service. So first off add the following<\/p>\n<pre class=\"brush: fsharp; title: ; notranslate\" title=\"\">\r\nopen Suave.Json\r\nopen System.Runtime.Serialization\r\n<\/pre>\n<p>Now we&#8217;ll create the data contracts for sending and receiving our data using, these will be serialized automatically for us through the function <em>mapLson<\/em> which will see in use soon. Notice we&#8217;re also able to deal with specific types, such as integers in this case (instead of just strings everywhere).<\/p>\n<pre class=\"brush: fsharp; title: ; notranslate\" title=\"\">\r\n&#x5B;&lt;DataContract&gt;]\r\ntype Calc =\r\n   { \r\n      &#x5B;&lt;field: DataMember(Name = &quot;a&quot;)&gt;]\r\n      a : int;\r\n      &#x5B;&lt;field: DataMember(Name = &quot;b&quot;)&gt;]\r\n      b : int;\r\n   }\r\n\r\n&#x5B;&lt;DataContract&gt;]\r\ntype Result =\r\n   { \r\n      &#x5B;&lt;field: DataMember(Name = &quot;result&quot;)&gt;]\r\n      result : int;\r\n   }\r\n<\/pre>\n<p>Finally let&#8217;s see how we startup our server. Here we use the <em>mapJson<\/em> to map our JSON request into the type <em>Calc<\/em> from here we carry out some function (in this case addition) and the result is returned (type inference turns the result into a Result type).<\/p>\n<pre class=\"brush: fsharp; title: ; notranslate\" title=\"\">\r\nstartWebServer defaultConfig (mapJson (fun (calc:Calc) -&gt; { result = calc.a + calc.b }))\r\n<\/pre>\n<p>Let&#8217;s test this using our <em>Invoke-RestMethod<\/em> Powershell code. We can create the JSON body for this method in the following way.<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nInvoke-RestMethod -Uri http:\/\/localhost:8083\/ -Method Post -Body '{&quot;a&quot;:10, &quot;b&quot;:20}'\r\n<\/pre>\n<p><strong>References<\/strong><\/p>\n<p><a href=\"https:\/\/theimowski.gitbooks.io\/suave-music-store\/content\/en\/query_parameters.html\" target=\"_blank\">Suave Music Store <\/a><br \/>\n<a href=\"https:\/\/technet.microsoft.com\/en-us\/library\/hh849971.aspx\" target=\"_blank\">Invoke-RestMethod<\/a><br \/>\n<a href=\"https:\/\/suave.io\/restful.html\" target=\"_blank\">Building RESTful Web Services<\/a><br \/>\n<a href=\"http:\/\/blog.tamizhvendan.in\/blog\/2015\/06\/11\/building-rest-api-in-fsharp-using-suave\/\" target=\"_blank\">Building REST Api in Fsharp Using Suave<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>I wanted to implement some microservices and thought, what&#8217;s more micro than REST style functions, executing single functions using a functional language (functional everywhere!). So let&#8217;s take a dip into the world of Suave using F#. Suave is a lightweight, non-blocking, webserver which can run on Linux, OSX and Windows. It&#8217;s amazingly simple to get [&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":[6,119],"tags":[],"class_list":["post-3713","post","type-post","status-publish","format-standard","hentry","category-f","category-suave"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/3713","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=3713"}],"version-history":[{"count":11,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/3713\/revisions"}],"predecessor-version":[{"id":3725,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/3713\/revisions\/3725"}],"wp:attachment":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/media?parent=3713"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/categories?post=3713"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/tags?post=3713"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}