Welcome to the Penguin's tech demo! Today we will be introducing you to the OpenAPI Specification (OAS) and the Swagger Editor tool. In this tech demo, we will guide you through the process of setting up and using OAS and Swagger, configuring code generation, and utilizing a testing toolkit to create robust API backends for your websites. Get ready to dive into the world of API documentation and development!
The OpenAPI Specification (OAS) offers developers and teams a streamlined framework for structuring and documenting HTTP-based APIs. By adhering to this specification, all stakeholders in product development gain a cohesive and standardized method for API documentation. Moreover, OAS supports the generation of client code, the sending of requests, and the creation of test cases. Tools like the Swagger Editor leverage OAS to provide syntax error feedback, visualize APIs, facilitate HTTP requests, and more.
The following is a demonstration of OpenAPI to understand the main concepts and provide a practical example of how this could be used in a real project.
Let's start our journey with the Swagger Editor, a powerful tool by SmartBear Software for designing OpenAPI schemas.
Key Features:
- Syntax Highlighting: Enhances readability and reduces the chance of errors.
- IDE-like Editing: Provides a familiar environment for developers, boosting productivity.
- Clean User Interface: Allows for efficient navigation and operation.
The Swagger Editor accommodates both yaml
and json
file types, providing a user-friendly and comprehensible language for all individuals involved in website development.
If you're new to Swagger, you'll initially see a default OpenAPI example. For more insights on their demo, please refer to the provided page.
To utilize our example, follow these steps:
- Clone our repository:
git clone https://github.com/csci5117s24/the-penguins-Open-API/
- Import
schema.yaml
into the Swagger Editor. You can do this by either copying and pasting the file content or using the import function in the editor.
Upon successful import, your Swagger Editor should resemble the following:
The right-hand side of the editor displays an editable version of the OpenAPI schema. The left-hand side contains a visual representation of the schema, that is, the API endpoints and their associated request objects.
Our OpenAPI document is composed of three primary elements: Servers, Paths, and Schemas. Let's delve into each one:
This section defines the base URL for your API. In our case, we're using localhost:7071
. This means that our API is running locally on our machine, specifically on port 7071. All the paths defined in the paths
section of the OpenAPI document will be appended to this base URL when making requests. This setup can be expanded in the future to include additional servers, such as those for staging or production environments.
Paths define the endpoints of your API. Each path corresponds to a specific request URL. Under each path, you specify the HTTP methods (GET, POST, PUT, DELETE, etc.) that the endpoint supports. For each method, you define the request parameters, body, and responses.
Here's the /todo
endpoint from our example:
paths:
/api/todo:
post:
tags:
- todo
summary: Add a new todo to the store
description: Add a new todo to the store
operationId: addTodo
requestBody:
description: Create a new todo
content:
application/json:
schema:
$ref: '#/components/schemas/todo'
required: true
responses:
'200':
description: Successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/todo'
'400':
description: Invalid input
'422':
description: Validation exception
Schemas define the structure of the data that your API sends and receives. They are used in request bodies and responses to validate the data and ensure it matches the expected format.
Here's the todo schema from our example:
components:
schemas:
todo:
type: object
properties:
id:
type: integer
format: int64
example: 10
description:
type: string
example: "Do Something"
done:
type: boolean
example: false
Once you've defined your servers, paths, and schemas, you can finally start using the Swagger UI tools to visualize your API and interact with it directly from your browser.
Note: To start sending requests, continue until step 5
Unfortunately, there are no working code-generation resources for creating Azure Http requests, but many other backend API services support OpenAPI autogeneration.
What follows is the sample backend code we created as shown in the /api
directory.
If you would like to test the APIs using your own data, make sure to change the local.settings.json
file with your own MongoDB connection string.
{
"Values": {
"AZURE_MONGO_DB":"<INSERT MONGO_DB CONNECTION STRING HERE>",
"FUNCTIONS_WORKER_RUNTIME": "node"
},
"IsEncrypted": false
}
We will use the Mongoose library to provide database interactivity for our Todo
items. If you would like to learn more about Mongoose as a utility for MongoDB, please visit their website.
In /api/index.js
we define a todo schema as well as a route to post todo items.
Notice how the todo schema is identical to the one defined in our OpenApi!
const { app } = require('@azure/functions');
const { ObjectId } = require('mongodb');
const mongoClient = require("mongodb").MongoClient;
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const todoSchema = new Schema({
description: { type: String, required: true },
done: { type: Boolean, default: false },
id: { type: Number, required: true }
});
app.http('newTodo', {
methods: ['POST'],
authLevel: 'anonymous',
route: 'todo',
handler: async (request, context) => {
await mongoose.connect(process.env.AZURE_MONGO_DB);
const body = await request.json();
const Todo = mongoose.model('Todo', todoSchema);
const name = body.description ?? "Todo 1"
const id = body.id ?? 1
const done = body.done;
const newTodo = new Todo();
newTodo.description = name;
newTodo.id = id;
newTodo.done = done;
const savedTask = await newTodo.save();
return{
status: 201,
jsonBody: savedTask
};
},
});
Make sure to run npm i
in both your main project folder and the /api
folder to install the correct dependencies.
In your main project folder, you can now run
npm run web
to start the frontend and backend servers.
With your API set up and configured, you can now test these endpoints using the Swagger Editor. Go back to the page that you created your schema. On the right-hand side, you should see your specified endpoints and requests. Make sure to specify the correct server in the dropdown.
For azure we use by default http://localhost:7071
Once you're ready to execute, click the "Execute" button. your response will then show up below near the expected server responses.
Now that you have your openAPI specification set up and communicating with your server, you can now use the OpenAPI ecosystem that has a lot of support and useful tools such as:
- Postman Integration
- Code generation for a variety of tech stacks
- Documentation helpers
OpenAPI lets you integrate with Postman to send requests and collaborate with others on API development. First, you must export your OpenAPI YAML file from swagger editor. Select File > Save as YAML. In Postman's online or desktop client, create a workspace. Once in your workspace, you can drag and drop your YAML file into your workspace. Click import.
You can now use your API definition to send requests from Postman.
Postman also has many other OpenAPI features such as viewing and editing documentation, generating schemas, and much more.
There are many libraries that can be used to generate fetch code for a variety of different tech stacks. For react, we found this OpenApi Typescript Generator to work pretty well with some modifications.
first go to your root project directory and install the generator with
npm i -D openapi-typescript typescript
Then with our openapi schema in our project's root directory, we ran
mkdir ./src/api
npx openapi-generator-cli generate -i openapi.yaml -g typescript -o ./src/api
This generated all the request code from our OpenAPI schema, and it even generates auth middleware and other useful tools that you can easily implement.
To use the generated code, we must first remove the unnecessary imports that aren't being used in path ./src/api/index.ts
. You can remove the following lines of code:
export { Configuration } from "./configuration"
export { PromiseMiddleware as Middleware } from './middleware';
Modify the import structure of ./src/models/ObjectSerializer.ts :
import { Todo } from '../models/Todo';
export * from '../models/Todo';
Once that is complete, you can now use your generated API definitions! An example of this in action for our post request:
import './App.css';
import * as TodoApi from './api/index'
import { Todo } from './api/index';
import * as fs from 'fs';
const configuration = TodoApi.createConfiguration();
const apiInstance = new TodoApi.TodoApi(configuration);
let body:Todo = {
id: 10,
description: "Do Nothing",
done: false,
};
export default function App() {
function postTodo() {
apiInstance.addTodo(body).then((data:any) => {
console.log('API called successfully. Returned data: ' + data);
}).catch((error:any) => console.error(error));
}
return (
<div className="App">
<button onClick={postTodo}>Post</button>
</div>
);
}
One of the key advantages of OpenAPI is its rich support for detailed documentation that could be especially useful in designing software with a waterfall approach if one needs to comply with regulations, or if there are other parties involved. To generate open API documentation, in your swagger editor, click "Generate Client" on the top bar and then select "HTML" from the dropdown.
The resulting html serves as detailed documentation for your designed API.
There are so many other programs and tools that can be used with OpenAPI, a detailed list can be found here: https://openapi.tools/
To conclude, OpenAPI is not just a helpful one-off visualizer for website APIs, but an entire ecosystem for full-stack API development. Now that you are equipped with the knowledge of how to develop and test an API within this ecosystem, you're on your way to become a more efficient and equipped web API developer. If you've made it this far then you probably can submit your feedback! Hope you enjoyed!