Azure Functions Team has recently announced the Swagger support as a preview. If we use Azure Functions as APIs, this will be very useful. In this post, we will have a look how to enable Swagger support on Azure Functions.
Sample codes used for this post can be found here.
Sample Azure Functions Instance
First of all, with the sample code provided, we’re creating two HTTP triggers,
GetProduct. Once we deploy them, we can find it from the Azure Portal like:
Here are simple requests and responses through Postman:
Let’s create a Swagger definition document for those Functions.
Auto-Generate Swagger Definition
If we have at least a Function endpoint in our Function instance, we can automatically generate a Swagger definition in YAML format. Click the
API definition (preview) tab.
As a default, the
External URL button is chosen. Click the
Functions button right next to it.
Because we have never generated the Swagger definition, it spits the error screen.
Now, click the
Generate API definition template button so that the document is automatically generated.
Now we’ve got the Swagger definition doco. The actual document generated looks like:
However, there are at least three missing gaps that we have to fill in:
definitions: There’s no request/response model definition. We have to fill in.
consumes: There’s no document type defined. In general, as JSON format is the most popular for REST API, we can simply add
securityDefinitions: Azure Functions use either
codein the querystring or
x-functions-keyin the request header for processing. The auto-generated template only defines the
codeone, not the other one. So we have to define the other
Here’s the updated Swagger definition including the missing ones:
Once we update the Swagger definition, we can test the API right away by providing function key code and payload. Easy, huh? Also the address specified in the middle of the picture,
https://xxxx.azurewebsites.net/admin/host/swagger?code=xxxx, allows us to access to the Swagger definition document in JSON format. Azure Functions instance automatically converts the YAML document to the JSON one.
It seems to be very easy. However, there is a critical point we have to bear in mind. The Function instance must have at least one function endpoint so that the Swagger definition should be auto-generated. In other words, API design-first approach is not applicable.
Now, we’ve got a question. If we only have Swagger definition document, not the actual implementation, what can we do with Azure Functions? Why not directly rendering Swagger document by Azure Function code?
Render Swagger Definition via Azure Functions
Here’s the deal. We basically create an Azure Function code that reads Swagger definition and render it as a response. The following function code will give us a brief idea:
The Function instance contains a
swagger-v1.yaml file in its root level. When we see the code above, firstly it reads the file. In order to read the file, we have to set a value to represent the root path, called
WEBROOT_PATH (or whatever) in the
AppSettings section. Its value will be
D:\home\site\wwwroot, which never changes unless Azure App Service changes it. There are two ways to read the settings value:
var wwwroot = Environment.GetEnvironmentVariable("WEBROOT_PATH");
var wwwroot = ConfigurationManager.AppSettings["WEBROOT_PATH"];
Either is fine to read the settings value. If we omit this settings value, Azure Functions basically assumes that the file is located at
C:\Windows\System32, which will cause an unexpected result.
According to this document, at the time of this writing, we can pass the
Microsoft.Azure.WebJobs.ExecutionContextinstance as a function parameter so that we can handle the file path a little bit easier. However, as it’s not fully rolled out yet nor dev tools don’t have that feature yet, we should wait for it until it’s fully rolled out.
The code above then read the YAML file, convert it to JSON and render it. We can now see the Swagger definition through a web browser:
So far, we have briefly looked how to enable Swagger support in Azure Functions in two different ways. Both of course have goods and bads. The first one might be the easiest option but needs more work. Also if we want to access to the swagger definition with the first option, we have to use a different access code. This is a bit critical because we have to manage at least two different keys – one for Functions and the other for Swagger, which is not ideal. On the other hand, the second option needs another Function code but can be handled by the same host key that is accessible to the other Function codes. Therefore, from the management point of view, the second option might be better. It’s still in preview, so we hope that the GA version of the Swagger support will be better than now.