<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ibrahim</title>
    <description>The latest articles on DEV Community by Ibrahim (@ibrahimislam).</description>
    <link>https://dev.to/ibrahimislam</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F9016%2F5cadc35d-78eb-43e5-b7b9-ccdcc6f244f5.jpeg</url>
      <title>DEV Community: Ibrahim</title>
      <link>https://dev.to/ibrahimislam</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ibrahimislam"/>
    <language>en</language>
    <item>
      <title>Auto Generate Client From OpenAPI Specification (Swagger)</title>
      <dc:creator>Ibrahim</dc:creator>
      <pubDate>Tue, 06 Apr 2021 16:17:33 +0000</pubDate>
      <link>https://dev.to/ibrahimislam/auto-generate-client-from-openapi-specification-swagger-6h9</link>
      <guid>https://dev.to/ibrahimislam/auto-generate-client-from-openapi-specification-swagger-6h9</guid>
      <description>&lt;p&gt;&lt;em&gt;TL;DR - Working script at the end&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In a microservices system, one of the mechanism for one service to talk to another is using Http. For example, if &lt;strong&gt;Service A&lt;/strong&gt; wants to invoke an endpoint on &lt;strong&gt;Service B&lt;/strong&gt; it can do something like below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;HttpClient&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BaseAddress&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"https://service-b"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;responseMessage&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;PostAsJsonAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/some-endpoint"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Payload&lt;/span&gt;&lt;span class="p"&gt;(...));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The issue here is that the model class &lt;code&gt;Payload&lt;/code&gt; was already written in &lt;code&gt;B&lt;/code&gt; but then &lt;code&gt;A&lt;/code&gt; would have to write it again in order to have typing and whenever there would be a change in specification in &lt;code&gt;B&lt;/code&gt; then &lt;code&gt;A&lt;/code&gt; would have to be manually changed also. So coupled and duplication.&lt;/p&gt;

&lt;p&gt;Now, lets assume another &lt;code&gt;Service C&lt;/code&gt; wants to invoke the same endpoint on &lt;code&gt;B&lt;/code&gt; so, &lt;code&gt;C&lt;/code&gt; would have to duplicate the code like &lt;code&gt;A&lt;/code&gt; again.&lt;/p&gt;

&lt;p&gt;We can can get rid of this manual and redundant process by auto-generating clients from the services like API SDKs which can then be consumed by another service.&lt;/p&gt;

&lt;h4&gt;
  
  
  To Dos:
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Integrate with Swagger for your web api&lt;/li&gt;
&lt;li&gt;Access to auto-generated &lt;code&gt;swagger.json&lt;/code&gt; based on your web api&lt;/li&gt;
&lt;li&gt;Tool to auto-generate code according to choice of language&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  1. Integrate with Swagger for your web api
&lt;/h4&gt;

&lt;p&gt;Pretty easy in ASP.NET Core. Use &lt;a href="https://github.com/domaindrivendev/Swashbuckle.AspNetCore"&gt;Swashbuckle&lt;/a&gt; to integrate swagger into your web api. Getting started tutorial &lt;a href="https://docs.microsoft.com/en-us/aspnet/core/tutorials/getting-started-with-swashbuckle"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Access to auto-generated &lt;code&gt;swagger.json&lt;/code&gt; based on your web api
&lt;/h4&gt;

&lt;p&gt;When you run your web api app, you can access the &lt;code&gt;swagger.json&lt;/code&gt; at &lt;code&gt;http://localhost:&amp;lt;port&amp;gt;/swagger/v1/swagger.json&lt;/code&gt;. Now either you can pass the link to &lt;code&gt;swagger.json&lt;/code&gt; or make it accessible from file system. If you go the former route then you need to ensure your web api is up somewhere and updated or spin it up locally. I went ahead with downloading the file into file system using &lt;a href="https://github.com/domaindrivendev/Swashbuckle.AspNetCore#swashbuckleaspnetcorecli"&gt;Swashbuckle.AspNetCore.Cli&lt;/a&gt; which can generate &lt;code&gt;swagger.json&lt;/code&gt; from your web api assembly. &lt;/p&gt;

&lt;h4&gt;
  
  
  3. Tool to auto-generate code according to choice of language
&lt;/h4&gt;

&lt;p&gt;I only found &lt;code&gt;NSwag&lt;/code&gt; or &lt;a href="(https://github.com/swagger-api/swagger-codegen)"&gt;&lt;code&gt;swagger-codegen&lt;/code&gt;&lt;/a&gt; for this and went ahead with the latter because it has more options and configurability. A great feature of this tool is that you can control the generated code through the use of mustache templates documented &lt;a href="https://github.com/swagger-api/swagger-codegen/wiki/Mustache-Template-Variables"&gt;here&lt;/a&gt;. If you want to kickstart your template customization for your preferred language then look &lt;a href="https://github.com/swagger-api/swagger-codegen/tree/master/modules/swagger-codegen/src/main/resources"&gt;here&lt;/a&gt;. Now, you can execute a command as simple as &lt;code&gt;swagger-codegen generate -i ./swagger.json -l ruby -o /tmp/test/&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example script
&lt;/h2&gt;

&lt;p&gt;Below is an example of bash script that is generating a customized C# client in a Linux machine.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="nv"&gt;swaggerCodeGenCliDownloadLink&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'https://repo1.maven.org/maven2/io/swagger/codegen/v3/swagger-codegen-cli/3.0.25/swagger-codegen-cli-3.0.25.jar'&lt;/span&gt;
&lt;span class="nv"&gt;swaggerCodeGenCliPath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'./swagger-codegen-cli.jar'&lt;/span&gt;
&lt;span class="nv"&gt;finalGeneratedClientPath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'./DEV.Client/generated'&lt;/span&gt;
&lt;span class="nv"&gt;swaggerGenOut&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'./swagger-code-gen-out'&lt;/span&gt;
&lt;span class="nv"&gt;swaggerInputFilePath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'./swagger.json'&lt;/span&gt; 
&lt;span class="nv"&gt;swaggerTemplateFolderPath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'./swagger-code-gen-templates'&lt;/span&gt;
&lt;span class="nv"&gt;ApiProjectName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'DEV.API'&lt;/span&gt;
&lt;span class="nv"&gt;clientProjectName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'DEV.Client'&lt;/span&gt;

&lt;span class="c"&gt;# Color&lt;/span&gt;
&lt;span class="nv"&gt;RED&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'\033[0;31m'&lt;/span&gt;
&lt;span class="nv"&gt;GREEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'\033[0;32m'&lt;/span&gt;
&lt;span class="nv"&gt;YELLOW&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'\033[0;33m'&lt;/span&gt;
&lt;span class="nv"&gt;NC&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'\033[0m'&lt;/span&gt; &lt;span class="c"&gt;# No Color&lt;/span&gt;

&lt;span class="k"&gt;function &lt;/span&gt;red &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;RED&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;NC&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;function &lt;/span&gt;green &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GREEN&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;NC&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;function &lt;/span&gt;yellow &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;YELLOW&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;NC&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;# build api project&lt;/span&gt;
dotnet build &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ApiProjectName&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;$ApiProjectName&lt;/span&gt;&lt;span class="s2"&gt;.csproj"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;green &lt;span class="s1"&gt;'Building project done!'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;#restore swashbuckle aspnetcore cli tool&lt;/span&gt;
dotnet tool restore
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;green &lt;span class="s1"&gt;'Restored dotnet tools!'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# generate swagger json&lt;/span&gt;
dotnet swagger tofile &lt;span class="nt"&gt;--output&lt;/span&gt; swagger.json &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ApiProjectName&lt;/span&gt;&lt;span class="s2"&gt;/bin/Debug/net5.0/&lt;/span&gt;&lt;span class="nv"&gt;$ApiProjectName&lt;/span&gt;&lt;span class="s2"&gt;.dll"&lt;/span&gt; v1
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;green &lt;span class="s1"&gt;'Generating swagger.json done!'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# download swagger code gen cli&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="nv"&gt;$swaggerCodeGenCliPath&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;yellow &lt;span class="s1"&gt;'Downloading swagger-code-gen cli...'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
    curl &lt;span class="nv"&gt;$swaggerCodeGenCliDownloadLink&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;$swaggerCodeGenCliPath&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="c"&gt;# generate models and apis&lt;/span&gt;
java &lt;span class="nt"&gt;-Dapis&lt;/span&gt; &lt;span class="nt"&gt;-DapiDocs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt; &lt;span class="nt"&gt;-Dmodels&lt;/span&gt; &lt;span class="nt"&gt;-DmodelDocs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt; &lt;span class="nt"&gt;-DapiTests&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt; &lt;span class="nt"&gt;-DmodelTests&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt; &lt;span class="nt"&gt;-jar&lt;/span&gt; &lt;span class="nv"&gt;$swaggerCodeGenCliPath&lt;/span&gt; generate &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nv"&gt;$swaggerInputFilePath&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; csharp &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;$swaggerGenOut&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; &lt;span class="nv"&gt;$swaggerTemplateFolderPath&lt;/span&gt; &lt;span class="nt"&gt;--additional-properties&lt;/span&gt; &lt;span class="nv"&gt;modelPackage&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$clientProjectName&lt;/span&gt; &lt;span class="nv"&gt;apiPackage&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$clientProjectName&lt;/span&gt; &lt;span class="nv"&gt;packageName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$clientProjectName&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;green &lt;span class="s1"&gt;'Generating models and apis done!'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# if there was previously generated then delete it&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nv"&gt;$finalGeneratedClientPath&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;red &lt;span class="s1"&gt;'Deleting stale generated folder'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="nv"&gt;$finalGeneratedClientPath&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="c"&gt;# move the generate code into target client project&lt;/span&gt;
&lt;span class="nb"&gt;mv&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$swaggerGenOut&lt;/span&gt;&lt;span class="s2"&gt;/src/&lt;/span&gt;&lt;span class="nv"&gt;$clientProjectName&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;$clientProjectName&lt;/span&gt;&lt;span class="s2"&gt;/"&lt;/span&gt; &lt;span class="nv"&gt;$finalGeneratedClientPath&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;green &lt;span class="s1"&gt;'Moving files to client project done!'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# remove temp swagger code generated folder&lt;/span&gt;
&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="nv"&gt;$swaggerGenOut&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;green &lt;span class="s1"&gt;'Removed temp generated directory'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>aspnetcore</category>
      <category>swagger</category>
      <category>codegen</category>
      <category>bash</category>
    </item>
  </channel>
</rss>
