swagger编写api

    科技2023-12-25  75

    swagger编写api

    Original article in Portuguese Brazil: (Click here)

    巴西葡萄牙语原文:( 点击这里 )

    For those who develop APIs in Node.js, whether at a professional level or not, you know that keeping the project documentation up to date is not an easy task, especially with short deadlines and other priorities, the documentation ends up most of the time getting out of date or even ignored. To resolve this, today I’m going to talk about an NPM module for Node.js that automatically performs the documentation for Swagger whenever your project is started, without you having to keep doing repairs or touch-ups on the Swagger .json file. The module in question is swagger-autogen.

    对于那些在Node.js中开发API的人员,无论是否处于专业水平,您都知道保持项目文档的更新不是一件容易的事,尤其是在期限短和其他优先级高的情况下,文档大部分时间会失效过时甚至被忽略。 为了解决这个问题,今天我将讨论Node.js的NPM模块,该模块在您启动项目时就自动执行Swagger的文档,而无需继续对Swagger .json文件进行修复或修改。 有问题的模块是swagger-autogen 。

    The swagger-autogen module generates only the Swagger .json file. To interpret it, we will have the help of the swagger-ui-express module and Express.js to create a server, leaving the documentation available on some port. Ah! But does it only work with Express.js? No, the module is independent of any framework, BUT, some frameworks like Express.js (or similar) will have some advantages and we will see more about them later. With the module it is possible to generate the documentation in two ways:

    swagger-autogen模块仅生成Swagger .json文件。 为了解释它,我们将借助swagger-ui-express模块​​和Express.js来创建服务器,而将文档保留在某些端口上。 啊! 但这仅适用于Express.js吗? 不,该模块独立于任何框架,但是,Express.js(或类似框架)之类的某些框架将具有一些优势,我们稍后将详细介绍它们。 使用该模块,可以通过两种方式生成文档:

    Along with the project, that is, every time the project is started, new documentation is generated, making it always updated.

    与项目一起,也就是说,每次启动项目时,都会生成新的文档,使其始终处于更新状态。

    Without starting the project, that is, running a script at the root of the project. This is similar to the npm test (testers will know…).

    无需启动项目,即在项目的根目录下运行脚本。 这类似于npm测试 (测试人员会知道...)。

    The first one I found more interesting, because it keeps the documentation always updated when we change the code. But I will talk about both ways in this article!

    我发现第一个更有趣,因为当我们更改代码时,它可使文档始终保持更新。 但是我将在本文中讨论这两种方式!

    The idea of ​​the module is very simple, just indicate the output file (.json) of Swagger, the files containing the endpoints, which are the files containing the get(), post(), etc functions, and a object containing the details of the documentation, such as: version, title, description, schemes, etc., the latter is not mandatory, it already has some standard values. A complete example can be seen at this link: https://github.com/davibaltar/example-swagger-autogen. Well, enough talking and let’s go to the code!

    该模块的思想很简单,只需指出Swagger的输出文件( .json ),包含端点的文件,即包含get(),post()等函数的文件以及包含以下内容的对象文档的详细信息,例如:版本,标题,描述,方案等,后者不是强制性的,它已经具有一些标准值。 可以在以下链接中看到完整的示例: https : //github.com/davibaltar/example-swagger-autogen 。 好了,足够多的讨论,让我们看一下代码!

    In its simplest form, I will create a project with the following structure:

    以最简单的形式,我将创建一个具有以下结构的项目:

    |-- package.json|-- swagger.js|-- index.js|--

    Where index.js is the root file of your project, that is, where execution starts and endpoints.js is the file that contains the .get(), post(), etc functions. The swagger.js file will only be in charge of calling the swagger-autogen module to generate the documentation.

    其中index.js是项目的根文件,即执行开始的地方,而endpoints.js是包含.get(),post()等函数的文件。 swagger.js文件仅负责调用swagger-autogen模块以生成文档。

    If you already use Express.js (or similar) the good news is that the module automatically recognizes the methods, path, status of responses and content-type of Header! If you don’t use Express.js or similar, I’ll talk about how to resolve this later.

    如果您已经使用Express.js(或类似版本),那么好消息是该模块会自动识别Header的方法,路径,响应状态和内容类型! 如果您不使用Express.js或类似的东西,我将在稍后讨论如何解决。

    For didactic purposes, I will write the index.js file, which will contain a simple structure of a server, looking like this:

    出于教学目的,我将编写index.js文件,其中将包含服务器的简单结构,如下所示:

    Recalling that in this article we are not looking at API security, good programming practices, MVC standard, versioning or routes. The idea here is to simplify as much as possible so that we can see only the documentation part.

    回顾本文,我们不讨论API安全性,良好的编程习惯,MVC标准,版本控制或路由。 这里的想法是尽可能简化,以便我们只能看到文档部分。

    Looking at the index.js file, we have in line 4 the import of the file in the Swagger format (this is the file that the swagger-autogen module will generate), the server started in line 6, the middleware responsible for creating a Swagger graphical interface on line 9 and the endpoints on line 11.

    查看index.js文件,我们在第4行中以Swagger格式导入了文件(这是swagger-autogen模块将生成的文件),服务器从第6行开始,中间件负责创建Swagger图形界面位于第9行,端点位于第11行。

    We will start the endpoints.js file with a single endpoint for now, and in the course of the article we will be adding more things to it. So, initially the file will have the following content:

    现在,我们将以单个终结点启动Endpoints.js文件,在本文中,我们将向其中添加更多内容。 因此,该文件最初将具有以下内容:

    module.exports = function (app) { app.get('/users/:id', (req, res) => { const filtro = req.query.filtro return res.status(404).send(false) }) }

    Now just call the swagger-autogen module to take action! To do this, add the following content to the swagger.js file:

    现在,只需调用swagger-autogen模块即可采取行动! 为此,请将以下内容添加到swagger.js文件:

    const swaggerAutogen = require('swagger-autogen')() const outputFile = './swagger_output.json' const endpointsFiles = ['./endpoints.js'] swaggerAutogen(outputFile, endpointsFiles)

    At the beginning of the article I said that the documentation could be generated without starting the project or together with the project. Now let’s look at these two ways. Let’s start with the documentation being generated without starting the project. To do this, add a script called “swagger-autogen” with “node swagger.js” to your package.json file. Thus, your package.json scripts should look like this:

    在本文的开头,我说过可以在不启动项目或不与项目一起的情况下生成文档。 现在让我们看看这两种方式。 让我们从不启动项目的情况下生成文档开始。 为此,请在package.json文件中添加一个名为“ swagger-autogen”和“ node swagger.js”的脚本。 因此,您的package.json脚本应如下所示:

    { "name": "exemplo-swagger-autogen", "version": "1.0.0", "main": "index.js", "scripts": { "start": "node index.js", "swagger-autogen": "node swagger.js" }, "dependencies": { "express": "^4.17.1", "swagger-autogen": "^1.1.0", "swagger-ui-express": "^4.1.4" } }

    All ready! We will install the dependencies by running the following command at the root of the project:

    准备好了! 我们将通过在项目的根目录中运行以下命令来安装依赖项:

    npm install

    npm安装

    After that, to generate the documentation without starting the project, just execute the following command at the project root:

    之后,要生成文档而不启动项目,只需在项目根目录下执行以下命令:

    npm run swagger-autogen

    npm运行swagger-autogen

    Generated! The swagger_output.json file will be generated and is ready to upload! But what if I want this file to be generated every time I start the project? To do this, just make a small change to the swaggerAutogen(…) function of the swagger.js file, as follows:

    产生了! swagger_output.json文件将生成并准备上传! 但是,如果我希望每次启动项目时都生成此文件怎么办? 为此,只需对swagger.js文件的swaggerAutogen(…)函数进行少量更改,如下所示:

    const swaggerAutogen = require('swagger-autogen')() const outputFile = './swagger_output.json' const endpointsFiles = ['./endpoints.js'] swaggerAutogen(outputFile, endpointsFiles).then(() => { require('./index.js') })

    The index.js in line 7 is the root file for our project. Ready! Just run the command again:

    第7行中的index.js是我们项目的根文件。 准备! 只需再次运行命令:

    npm run swagger-autogen

    npm运行swagger-autogen

    The documentation will be generated and the project will start shortly thereafter. If you use Visual Studio Code, you can also modify your launch.json file to point to swagger.js instead of index.js, thereby gaining the possibility to generate the documentation and debug your code right away. You can see the result in the image below or by visiting: http://localhost:3000/doc

    将生成文档,此后不久将开始该项目。 如果使用Visual Studio Code,还可以修改launch.json文件,使其指向swagger.js而不是index.js,从而可以立即生成文档并调试代码。 您可以在下面的图像中或通过访问http:// localhost:3000 / doc来查看结果。

    Note that the module automatically identified the “get” method, the “/users” path, the path’s “id” parameter, the query’s “filter” parameter (or “filtro” in Portuguese Brazil) and the “404” response code, adding the description “Not Found” automatically. But you may be wondering, what about the title, description, version and description of the parameters? Calm down, you can add it all up. Let’s boost our swagger.js file:

    请注意,该模块会自动识别“获取”方法,“ /用户”路径,路径的“ id”参数,查询的“过滤器”参数(或葡萄牙语(巴西)中的“ filtro”)和“ 404”响应代码,添加说明“未找到”。 但是您可能想知道,参数的标题,描述,版本和描述如何? 冷静下来,您可以全部添加。 让我们增强swagger.js文件:

    const swaggerAutogen = require('swagger-autogen')() const outputFile = './swagger_output.json' const endpointsFiles = ['./endpoints.js'] const doc = { info: { version: "1.0.0", title: "My API", description: "Documentation automatically generated by the <b>swagger.autogen</b> module." }, host: "localhost:3000", basePath: "/", schemes: ['http', 'https'], consumes: ['application/json'], produces: ['application/json'], tags: [ { "name": "User", "description": "Endpoints" } ], securityDefinitions: { api_key: { type: "apiKey", name: "api_key", in: "header" }, petstore_auth: { type: "oauth2", authorizationUrl: "https://petstore.swagger.io/oauth/authorize", flow: "implicit", scopes: { read_pets: "read your pets", write_pets: "modify pets in your account" } } }, definitions: { User: { name: "Jhon Doe", age: 29, parents: { father: "Simon Doe", mother: "Marie Doe" }, diplomas: [ { school: "XYZ University", year: 2020, completed: true, internship: { hours: 290, location: "XYZ Company" } } ] }, AddUser: { $name: "Jhon Doe", $age: 29, about: "" } } } swaggerAutogen(outputFile, endpointsFiles, doc).then(() => { require('./index.js') })

    Note that we added an object called doc and passed it as the third parameter of the swaggerAutogen(…) function. For those who are already used to writing Swagger files, there is nothing new there. To other people, here’s a short explanation of each of the doc object’s parameters:

    请注意,我们添加了一个名为doc的对象,并将其作为swaggerAutogen(…)函数的第三个参数传递。 对于那些已经习惯于编写Swagger文件的人来说,这里没有什么新东西。 对于其他人,这是每个doc对象参数的简短说明:

    info: General information about the API, such as: version, title and description.

    info:有关API的常规信息,例如:版本,标题和描述。

    host: Path and port where your API will start. In our case, we maintain the http://localhost:3000 default.

    host:您的API将在其中启动的路径和端口。 在我们的情况下,我们保持http:// localhost:3000的默认值。

    basePath: This is the root of your project. In our case, we keep the “/” default.

    basePath:这是您项目的根。 在本例中,我们保留默认的“ /”。

    schemes: These are the protocols used. Although we don’t use HTTPS in this article, I added it only for educational purposes, but you can choose HTTP and/or HTTPS.

    方案:这些是使用的协议。 尽管在本文中我们不使用HTTPS,但是我仅出于教育目的添加了它,但是您可以选择HTTP和/或HTTPS。

    consumes: Here is the type of the input content (famous: Content-Type of the header), that is, if you receive a parameter by the body, for example, it is the consumes that will tell Swagger if the data type is a JSON , XML or other.

    消费:这是输入内容的类型(著名:标头的Content-Type),也就是说,例如,如果您通过正文接收到参数,则消费将告诉Swagger数据类型是否为JSON,XML或其他。

    produces: Similar to consumes, produces informs the type of the output content, that is, it tells Swagger if the type of the response is JSON, XML or other.

    产生:类似于消耗,产生通知输出内容的类型,即告诉Swagger响应的类型是JSON,XML还是其他。

    tags: It is a given goal, that is, it will be the groups of endpoints within your API. An API can have, for example, a “Users” tag and a tag called “Books” to separate the endpoints.

    标签:这是给定的目标,也就是说,它将是您API中的端点组。 API可以具有例如“用户”标签和称为“书”的标签来分隔端点。

    securityDefinitions: For those who use API authentication like JWT or OAuth, this option allows you to perform these authentications. NOTE: In this article I am not going to show you how to authenticate, this is a lengthy subject, I am simply showing that the module accepts the security parameters recognized by Swagger.

    securityDefinitions:对于使用JWT或OAuth之类的API身份验证的用户,此选项使您可以执行这些身份验证。 注意:在本文中,我不会向您展示如何进行身份验证,这是一个冗长的主题,我只是在说明该模块接受Swagger识别的安全参数。

    definitions: These are your inputs and outputs. The difference here is that the module does this in a simpler way, just enter the input/output parameters the way you want to see them in the documentation. This helps a lot, because anyone who has already created definitions by hand knows what it’s like to get lost when creating an object within an array, for example. When informing an object in the definition, the module automatically identifies the type and creates an example for it based on the informed parameter. NOTE: To inform that a field is mandatory, just add the "$" symbol before the parameter (see the AddUser object in the code above).

    定义:这些是您的输入和输出。 此处的区别在于,该模块以更简单的方式执行此操作,只需按照您希望在文档中看到它们的方式输入输入/输出参数即可。 这很有帮助,因为例如,已经手工创建定义的任何人都知道在数组中创建对象时会迷失什么。 在定义中通知对象时,模块会自动识别类型并根据通知的参数为其创建示例。 注意:要通知该字段是必填字段,只需在参数之前添加“ $”符号(请参见上面代码中的AddUser对象)。

    Run the code and see how it looks:

    运行代码,看看它的外观:

    Let’s go to the endpoints! The way to communicate with the swagger-autogen module is through the tag “#swagger” inside comments (which can be of the type // or /* … */) and must be inside a function. In this article I will talk about the main tags used. The tags are self-describing, but whoever has any questions can check the official module documentation (link at the end of the article).

    让我们去端点! 与swagger-autogen模块进行通信的方式是通过注释内的标签“ #swagger”(可以是//或/ *…* /类型),并且必须在函数内。 在本文中,我将讨论使用的主要标签。 标签是自描述的,但是有任何疑问的人可以查看官方模块文档(本文结尾的链接)。

    Now it’s time to improve our young grasshopper! We will improve our endpoint by adding a description and informing which group it belongs to (tags).

    现在是时候改善我们的小蚱!了! 我们将通过添加描述并通知其所属的组(标签)来改善端点。

    module.exports = function (app) { app.get('/users/:id', (req, res) => { // #swagger.tags = ['User'] // #swagger.description = 'Endpoint para obter um usuário.' const filtro = req.query.filtro return res.status(404).send(false) }) }

    See the result after executing the code:

    执行代码后,查看结果:

    Now, let’s add more information to the id and filter parameters of our endpoint:

    现在,让我们向端点的id和filter参数添加更多信息:

    module.exports = function (app) { app.get('/users/:id', (req, res) => { // #swagger.tags = ['User'] // #swagger.description = 'Endpoint para obter um usuário.' // #swagger.parameters['id'] = { description: 'ID do usuário.' } /* #swagger.parameters['filtro'] = { description: 'Um filtro qualquer.', type: 'string' } */ const filtro = req.query.filtro return res.status(404).send(false) }) }

    The result will be:

    结果将是:

    Now, let’s add more information to the answers:

    现在,让我们向答案中添加更多信息:

    module.exports = function (app) { app.get('/users/:id', (req, res) => { // #swagger.tags = ['User'] // #swagger.description = 'Endpoint para obter um usuário.' // #swagger.parameters['id'] = { description: 'ID do usuário.' } /* #swagger.parameters['filtro'] = { description: 'Um filtro qualquer.', type: 'string' } */ const filtro = req.query.filtro if(false) return res.status(404).send(false) /* #swagger.responses[200] = { schema: { $ref: "#/definitions/User" }, description: 'Usuário encontrado.' } */ return res.status(200).send(data) }) }

    And the result will be:

    结果将是:

    Note that I added one more response, but with status 200 and the definition User that we wrote in the swagger.js file. Finally, let’s add another endpoint that uses the POST method:

    请注意,我又添加了一个响应,但是状态为200,定义为我们在swagger.js文件中编写的用户。 最后,让我们添加另一个使用POST方法的端点:

    module.exports = function (app) { app.get('/users/:id', (req, res) => { // #swagger.tags = ['User'] // #swagger.description = 'Endpoint para obter um usuário.' // #swagger.parameters['id'] = { description: 'ID do usuário.' } /* #swagger.parameters['filtro'] = { description: 'Um filtro qualquer.', type: 'string' } */ const filtro = req.query.filtro if(false) return res.status(404).send(false) /* #swagger.responses[200] = { schema: { $ref: "#/definitions/User" }, description: 'Usuário encontrado.' } */ return res.status(200).send(data) }) app.post('/users', (req, res) => { /* #swagger.tags = ['User'] #swagger.description = 'Endpoint para adicionar um usuário.' */ /* #swagger.parameters['newUser'] = { in: 'body', description: 'Informações do usuário.', required: true, type: 'object', schema: { $ref: "#/definitions/AddUser" } } */ const newUser = req.body if (true) { // #swagger.responses[201] = { description: 'Usuário registrado com sucesso!' } return res.status(201).send(data) } return res.status(500) // #swagger.responses[500] }) }

    In the end, the result will be this:

    最后,结果将是这样的:

    There are other possibilities, such as: ignoring a given endpoint using the tag “#swagger.ignore = true”, making the endpoint not appear in the documentation. You can find more resources directly in the official documentation (link at the end of the article).

    还有其他可能性,例如:使用标签“#swagger.ignore = true”忽略给定的端点,使该端点不出现在文档中。 您可以直接在官方文档中找到更多资源(本文末尾的链接)。

    For those who use frameworks with a different pattern than Express.js, that is, endpoints are not called in the foo.method (path, callback) style, it is possible to manually inform the begging and end of the endpoint with the tags “#swagger.start “and” #swagger.end “, respectively, in addition to having to add the tags” #swagger.path “and” #swagger.method “. The content between the “#swagger.start” and “#swagger.end” tags are the same as seen in the examples above. See the “Manual capture” section in the official documentation (link at the end of the article) for more details on these tags, but here’s a simple example of how to recognize an endpoint manually. Consider any function (here called myFunction):

    对于那些使用与Express.js模式不同的框架的人,也就是说,端点不是以foo.method(路径,回调)样式调用的,可以通过标签“除了必须添加标签“#swagger.path”和“#swagger.method”之外,还分别需要#swagger.start和“#swagger.end”。 “#swagger.start”和“#swagger.end”标签之间的内容与上面的示例相同。 有关这些标记的更多详细信息,请参见官方文档中的“手动捕获”部分(本文末尾的链接),但这是一个如何手动识别端点的简单示例。 考虑任何函数(此处称为myFunction):

    function myFunction(params) { // #swagger.start /* #swagger.path = '/forcedEndpoint/{id}' #swagger.method = 'put' #swagger.description = 'Endpoint forçado' #swagger.produces = ["application/json"] #swagger.tags = ['User'] */ /* #swagger.parameters['id'] = { in: 'path', description: 'ID do Usuário' } */ const dataId = users.getUser(req.params.id) /* #swagger.parameters['obj'] = { in: 'body', description: 'Informações do usuário', type: 'object', schema: { $ref: "#/definitions/AddUser" } } */ const dataObj = req.body if (true) return res.status(200).send(true) // #swagger.responses[200] return res.status(404).send(false) // #swagger.responses[404] // #swagger.end }

    And the result will be:

    结果将是:

    Well guys, the idea of ​​this article was just to give you an idea about the module and what it can do. Anyone who wants to go deeper and learn about his other resources, visit the link below. That’s it! See you!

    伙计们,本文的想法只是让您对模块及其功能有所了解。 任何想深入了解他的其他资源的人,请访问下面的链接。 而已! 再见!

    Module:

    模块:

    A complete example can be seen at this link: https://github.com/davibaltar/example-swagger-autogen.

    可以在以下链接中看到完整的示例: https : //github.com/davibaltar/example-swagger-autogen 。

    翻译自: https://medium.com/swlh/automatic-api-documentation-in-node-js-using-swagger-dd1ab3c78284

    swagger编写api

    相关资源:使用node生成swagger接口文档
    Processed: 0.009, SQL: 8