This post builds on what we’ve learned already to create a working Swagger front-end that talks to a real server. (See Testing Swagger and Making Swagger work for real, part 1)
The previous example used generated server code for the back end so it worked nicely with the Swagger UI front end by design. The next step is to make it work with a real Zulip server, which does not.
For the codegen-based test, a curl command to create a new item looked like this:
curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' -d '{ "id": 5, "name": "potato" }' 'http://10.2.3.4:8080/api/items'
But creating a new message in Zulip looks like this:
curl -X POST --header 'Content-Type: application/x-www-form-urlencoded' --header 'Accept: application/json' --header 'Authorization: Basic MyAuthHash' -d 'type=stream&content=bar&to=test&subject=foo' 'http://10.2.3.4:9991/api/v1/messages'
There are two differences to account for here. The first is that the Zulip endpoint is expecting url-encoded text, not JSON, in the POST data. The second is that it requires authentication. Both of these need to be correctly described in the YAML description of the API.
Building the YAML file
The store example specified that the endpoint both accepts and produces “application/json” data:
consumes: - application/json produces: - application/json
and “in: body” in the parameter list means it expects them to be in the body of the POST in the format described by the newItem schema.
post: description: Creates a new item in the store. Duplicates are allowed operationId: addItem produces: - application/json parameters: - name: item in: body description: Item to add to the store required: true schema: $ref: '#/definitions/newItem'
For Zulip, the endpoint still returns JSON, but is expecting to receive x-www-form-urlencoded data (just like an HTML form.)
consumes: - application/x-www-form-urlencoded produces: - application/json
The individual parameters must be defined as “formData”, which doesn’t use a separate schema definition:
parameters: - name: type in: formData description: type of message to create required: true type: string - name: content in: formData description: content of message to create required: true type: string - name: to in: formData description: recipient of message to create required: true type: string - name: subject in: formData description: subject of message to create required: true type: string
Now that the incoming data is defined, we need to make it use Basic Auth to authenticate with the Zulip back end. The first part of that is to add a “securityDefinitions” section:
securityDefinitions: basicAuth: type: basic description: HTTP Basic Auth
and in the parameters specify that they require this security:
security: - basicAuth: []
Here’s the full YAML file:
swagger: '2.0' info: version: '1.0.0' title: Sample API description: Some Stuff I wrote termsOfService: http://example.com contact: name: Feorlen email: nobody@example.com url: http://example.com license: name: Foo url: http://example.com host: 10.2.3.4:9991 basePath: /api/v1 schemes: - http consumes: - application/x-www-form-urlencoded produces: - application/json securityDefinitions: basicAuth: type: basic description: HTTP Basic Auth paths: /messages: post: description: Creates a new Zulip message operationId: addMessage produces: - application/json parameters: - name: type in: formData description: type of message to create required: true type: string - name: content in: formData description: content of message to create required: true type: string - name: to in: formData description: recipient of message to create required: true type: string - name: subject in: formData description: subject of message to create required: true type: string security: - basicAuth: [] responses: '200': description: message response schema: $ref: '#/definitions/messageResponse' default: description: unexpected error schema: $ref: '#/definitions/errorModel' definitions: messageResponse: type: object required: - msg - result - id properties: msg: type: string result: type: string id: type: string errorModel: type: object required: - code - message properties: code: type: integer format: int32 message: type: string
With this configuration, Swagger UI generates a curl command that can connect to the server, authenticate, and create a new post. The problem is, however, that the nice clickable demo that Swagger UI offers doesn’t.
I’ll get into that with the next post.
Leave a Reply