Auto Generate Client From OpenAPI Specification (Swagger)
Ibrahim
Posted on April 6, 2021
TL;DR - Working script at the end
In a microservices system, one of the mechanism for one service to talk to another is using Http. For example, if Service A wants to invoke an endpoint on Service B it can do something like below:
var client = new HttpClient();
client.BaseAddress = "https://service-b";
var responseMessage = client.PostAsJsonAsync("/some-endpoint", new Payload(...));
The issue here is that the model class Payload
was already written in B
but then A
would have to write it again in order to have typing and whenever there would be a change in specification in B
then A
would have to be manually changed also. So coupled and duplication.
Now, lets assume another Service C
wants to invoke the same endpoint on B
so, C
would have to duplicate the code like A
again.
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.
To Dos:
- Integrate with Swagger for your web api
- Access to auto-generated
swagger.json
based on your web api - Tool to auto-generate code according to choice of language
1. Integrate with Swagger for your web api
Pretty easy in ASP.NET Core. Use Swashbuckle to integrate swagger into your web api. Getting started tutorial here.
2. Access to auto-generated swagger.json
based on your web api
When you run your web api app, you can access the swagger.json
at http://localhost:<port>/swagger/v1/swagger.json
. Now either you can pass the link to swagger.json
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 Swashbuckle.AspNetCore.Cli which can generate swagger.json
from your web api assembly.
3. Tool to auto-generate code according to choice of language
I only found NSwag
or swagger-codegen
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 here. If you want to kickstart your template customization for your preferred language then look here. Now, you can execute a command as simple as swagger-codegen generate -i ./swagger.json -l ruby -o /tmp/test/
.
Example script
Below is an example of bash script that is generating a customized C# client in a Linux machine.
#!/bin/bash
swaggerCodeGenCliDownloadLink='https://repo1.maven.org/maven2/io/swagger/codegen/v3/swagger-codegen-cli/3.0.25/swagger-codegen-cli-3.0.25.jar'
swaggerCodeGenCliPath='./swagger-codegen-cli.jar'
finalGeneratedClientPath='./DEV.Client/generated'
swaggerGenOut='./swagger-code-gen-out'
swaggerInputFilePath='./swagger.json'
swaggerTemplateFolderPath='./swagger-code-gen-templates'
ApiProjectName='DEV.API'
clientProjectName='DEV.Client'
# Color
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
NC='\033[0m' # No Color
function red {
printf "${RED}$@${NC}\n"
}
function green {
printf "${GREEN}$@${NC}\n"
}
function yellow {
printf "${YELLOW}$@${NC}\n"
}
# build api project
dotnet build "$ApiProjectName/$ApiProjectName.csproj"
echo $(green 'Building project done!')
#restore swashbuckle aspnetcore cli tool
dotnet tool restore
echo $(green 'Restored dotnet tools!')
# generate swagger json
dotnet swagger tofile --output swagger.json "$ApiProjectName/bin/Debug/net5.0/$ApiProjectName.dll" v1
echo $(green 'Generating swagger.json done!')
# download swagger code gen cli
if [ ! -f $swaggerCodeGenCliPath ]; then
echo $(yellow 'Downloading swagger-code-gen cli...')
curl $swaggerCodeGenCliDownloadLink -o $swaggerCodeGenCliPath
fi
# generate models and apis
java -Dapis -DapiDocs=false -Dmodels -DmodelDocs=false -DapiTests=false -DmodelTests=false -jar $swaggerCodeGenCliPath generate -i $swaggerInputFilePath -l csharp -o $swaggerGenOut -t $swaggerTemplateFolderPath --additional-properties modelPackage=$clientProjectName apiPackage=$clientProjectName packageName=$clientProjectName
echo $(green 'Generating models and apis done!')
# if there was previously generated then delete it
if [ -d $finalGeneratedClientPath ]; then
echo $(red 'Deleting stale generated folder')
rm -r $finalGeneratedClientPath
fi
# move the generate code into target client project
mv "$swaggerGenOut/src/$clientProjectName/$clientProjectName/" $finalGeneratedClientPath
echo $(green 'Moving files to client project done!')
# remove temp swagger code generated folder
rm -r $swaggerGenOut
echo $(green 'Removed temp generated directory')
Posted on April 6, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.