1-0-5-hai-aage-dekhte-hein-kya-aat-hai 中文文档教程
OpenAPI Generated JavaScript/Express Server
Overview
该服务器是使用 OpenAPI Generator 项目生成的。 代码生成器及其生成的代码允许您以 API 优先的态度开发您的系统,其中 API 契约是您项目的锚点和定义者,您的代码和业务逻辑旨在完成并遵守API 合约。
prerequisites
- NodeJS >= 10.6
- NPM >= 6.10.0
代码是在 Mac 上编写的,因此假设所有代码都可以在基于 Linux 的计算机上顺利运行。 但是,没有理由不在基于 Windows 的机器上运行这个库。 如果您发现与操作系统相关的问题,请打开一个问题,它将得到解决。
Running the server
This is a long read, but there's a lot to understand. Please take the time to go through this.
使用 OpenAPI 生成器生成您的应用程序: 假设您有 Java (1.8+),并且有 jar 来生成应用程序,跑步:
java -jar {path_to_jar_file} generate -g nodejs-express-server -i {openapi yaml/json 文件} -o {target_directory_where_the_app_will_be_installed}
如果您没有 jar,或者不想从本地计算机运行 Java,请按照 OpenAPITools 页面 上的说明进行操作. 您可以在线、在 docker 上以及其他各种方式运行脚本。转到您定义的生成目录。 有一个完全可用的 NodeJS-ExpressJs 服务器等着你。 这很重要 - 代码由您更改和更新! 查看 config.js,看看那里的设置是否适合您 - 服务器将在端口 3000 上运行,文件将上传到新目录“uploaded_files”。
服务器将基于位于 /api/openapi.yaml 下的 openapi.yaml 文件。 这与您用于生成应用程序的文件不完全相同: I. 如果您在路径对象中定义了
application/json
contentBody - 生成器会将其移动到 openapi 文档的组件/模式部分。 二。 每个进程都添加了一个新元素 -x-eov-operation-handler: controllers/PetController
将调用定向到该文件。 三、 我们有一个将 operationId 转换为方法的 Java 应用程序,以及一个执行相同过程以调用该方法的 nodeJS 脚本。 两者都将方法转换为camelCase
,但可能存在差异。 请注意 operationID 名称,并查看它们在controllers
和services
目录中表示。花时间了解应用程序的结构。 可能存在错误,并且可能存在不符合您期望的设置和业务逻辑。 与其放弃此解决方案并寻找其他解决方案,不如看看您是否可以使生成的代码为您工作。 为使解释简短(随后将进行更详细的解释):应用程序以对 index.js 的调用开始(稍后您将在此处插入数据库)。 它调用 expressServer.js,这是 express.js 和 openapi-validator 启动的地方。这是一个重要的文件。 学习吧。 所有对 openapi.yaml 文档中配置的端点的调用都转到
controllers/{name_of_tag_which_the_operation_was_associated_with}.js
,这是一个非常小的方法。 所有的业务逻辑都在controllers/Controller.js
中,从那里到services/{name_of_tag_which_the_operation_was_associated_with}.js
。一旦您了解将要发生什么,启动应用程序并确保一切按预期工作:
npm start
Tests
不幸的是,我没有编写任何单元测试。 那些会在未来出现。 然而,这个包确实包含了编写和运行测试所需的一切——mocha 和 sinon 以及相关的库包含在 package.js 中,并将在 npm install 命令上安装
View and test the API
(假设没有对 config.js 进行任何更改)
- API documentation, and to check the available endpoints: http://localhost:3000/api-docs/. To
- Download the oepnapi.yaml document: http://localhost:3000/openapi.
- Every call to an endpoint that was defined in the openapi document will return a 200 and a list of all the parameters and objects that were sent in the request.
- Endpoints that require security need to have security handlers configured before they can return a successful response. At this point they will return a response code of 401.
- ##### At this stage the server does not support document body sent in xml format.
Node version and guidelines
代码是使用 Node 10.6 版编写的,符合 Airbnb .eslint 指导规则。
Project Files
Root Directory:
在根目录中,我们有(除了 package.json、config.js 和日志文件):
- logger.js - where we define the logger for the project. The project uses winston, but the purpose of this file is to enable users to change and modify their own logger behavior.
- index.js - This is the project's 'main' file, and from here we launch the application. This is a very short and concise file, and the idea behind launching from this short file is to allow use-cases of launching the server with different parameters (changing config and/or logger) without affecting the rest of the code.
- expressServer.js - The core of the Express.js server. This is where the express server is initialized, together with the OpenAPI validator, OpenAPI UI, and other libraries needed to start our server. If we want to add external links, that's where they would go. Our project uses the express-openapi-validator library that acts as a first step in the routing process - requests that are directed to paths defined in the
openapi.yaml
file are caught by this process, and it's parameters and bodyContent are validated against the schema. A successful result of this validation will be a new 'openapi' object added to the request. If the path requested is not part of the openapi.yaml file, the validator ignores the request and passes it on, as is, down the flow of the Express server.
api/
- openapi.yaml - This is the OpenAPI contract to which this server will comply. The file was generated using the codegen, and should contain everything needed to run the API Gateway - no references to external models/schemas.
utils/
目前只有一个文件:
- openapiRouter.js - This is where the routing to our back-end code happens. If the request object includes an
openapi
object, it picks up the following values (that are part of theopenapi.yaml
file): 'x-openapi-router-controller', and 'x-openapi-router-service'. These variables are names of files/classes in the controllers and services directories respectively. The operationId of the request is also extracted. The operationId is a method in the controller and the service that was generated as part of the codegen process. The routing process sends the request and response objects to the controller, which will extract the expected variables from the request, and send it to be processed by the service, returning the response from the service to the caller.
controllers/
在验证请求并确保它属于我们的 API 网关之后,我们将请求发送到 控制器
,其中从请求中提取变量和参数,并发送到相关的 service
进行处理。 controller
处理来自 service
的响应并构建适当的 HTTP 响应以发送回用户。
index.js - 加载为此项目生成的所有控制器,并将它们导出以供
openapiRouter.js
动态使用。 如果您想自定义您的控制器,建议您在此处链接到您的控制器,并确保代码生成器不会重写此文件。Controller.js - 生成控制器的核心处理器。 生成的控制器被设计得尽可能简洁和通用,引用
Controller.js
的业务逻辑从请求中解析所需的变量和参数,并构建 HTTP 响应被送回。Controller.js
是一个带有静态方法的类。.js - 自动生成代码,处理所有操作。 Controller 是一个类,它由它将向其发送请求的服务类构建。
openapi.yaml
定义的每个请求都有一个 operationId。 operationId 是将要调用的方法的名称。 每个方法接收请求和响应,并调用Controller.js
处理请求和响应,添加实际业务逻辑处理应该调用的服务方法。
services/
这是 API 网关结束的地方,您的应用程序的独特业务逻辑开始发挥作用。openapi.yaml
中的每个端点都有一个变量“x-openapi-router-service”,它是生成的服务类的名称。 端点的 operationID 是将要调用的方法的名称。 生成的代码提供了一个带有 try/catch 子句的简单承诺。 成功的操作以调用通用 Service.js
来构建成功的响应(有效负载和响应代码)而结束,失败将调用通用 Service.js
来使用错误对象和相关响应代码构建响应。 建议让服务自动生成一次,并在初始构建后手动添加方法。
index.js - 加载为此项目生成的所有服务,并将它们导出以供
openapiRouter.js
动态使用。 如果您想自定义您的服务,建议您在此处链接到您的控制器,并确保代码生成器不会重写此文件。Service.js - 一个实用程序类,此时非常简单和薄,具有两个静态方法,用于构建服务操作中成功和失败结果的响应对象。 默认响应代码为 200 表示成功,500 表示失败。 建议发送更准确的响应代码并在相关时覆盖这些默认值。
.js - 自动生成的代码,为
openapi.yaml
中定义的每个 operationId 提供存根 Promise。 每个方法都接收在openapi.yaml
文件中定义的变量,并将 Promise 包装在 try/catch 子句中。 Promise 解析调用Service.js
实用程序类的成功和失败,以构建适当的响应,该响应将发送回控制器,然后发送给此端点的调用者。
tests/
- serverTests.js - basic server validation tests, checking that the server is up, that a call to an endpoint within the scope of the
openapi.yaml
file returns 200, that a call to a path outside that scope returns 200 if it exists and a 404 if not. - routingTests.js - Runs through all the endpoints defined in the
openapi.yaml
, and constructs a dummy request to send to the server. Confirms that the response code is 200. At this point requests containing xml or formData fail - currently they are not supported in the router. - additionalEndpointsTests.js - A test file for all the endpoints that are defined outside the openapi.yaml scope. Confirms that these endpoints return a successful 200 response.
应编写未来的测试以确保发送的每个请求的响应都应符合 openapi.yaml
中定义的结构。 该测试最初将 100% 失败,开发团队的工作将是清除这些测试。
models/
目前是一个等待反馈的概念。 这个想法是让 openapi.yaml 中定义的对象充当在不同模块之间传递的模型。 这将使程序员使用定义的对象而不是松散定义的 JSON 对象进行交互。 考虑到 JavaScript 程序员的本性,他们希望使用自己的自举参数,这个概念可能行不通。 将其保留在这里以供将来讨论和反馈。
OpenAPI Generated JavaScript/Express Server
Overview
This server was generated using the OpenAPI Generator project. The code generator, and it's generated code allows you to develop your system with an API-First attitude, where the API contract is the anchor and definer of your project, and your code and business-logic aims to complete and comply to the terms in the API contract.
prerequisites
- NodeJS >= 10.6
- NPM >= 6.10.0
The code was written on a mac, so assuming all should work smoothly on Linux-based computers. However, there is no reason not to run this library on Windows-based machines. If you find an OS-related problem, please open an issue and it will be resolved.
Running the server
This is a long read, but there's a lot to understand. Please take the time to go through this.
Use the OpenAPI Generator to generate your application: Assuming you have Java (1.8+), and have the jar to generate the application, run:
java -jar {path_to_jar_file} generate -g nodejs-express-server -i {openapi yaml/json file} -o {target_directory_where_the_app_will_be_installed}
If you do not have the jar, or do not want to run Java from your local machine, follow instructions on the OpenAPITools page. You can run the script online, on docker, and various other ways.Go to the generated directory you defined. There's a fully working NodeJS-ExpressJs server waiting for you. This is important - the code is yours to change and update! Look at config.js and see that the settings there are ok with you - the server will run on port 3000, and files will be uploaded to a new directory 'uploaded_files'.
The server will base itself on an openapi.yaml file which is located under /api/openapi.yaml. This is not exactly the same file that you used to generate the app: I. If you have
application/json
contentBody that was defined inside the path object - the generate will have moved it to the components/schemas section of the openapi document. II. Every process has a new element added to it -x-eov-operation-handler: controllers/PetController
which directs the call to that file. III. We have a Java application that translates the operationId to a method, and a nodeJS script that does the same process to call that method. Both are converting the method tocamelCase
, but might have discrepancy. Please pay attention to the operationID names, and see that they are represented in thecontrollers
andservices
directories.Take the time to understand the structure of the application. There might be bugs, and there might be settings and business-logic that does not meet your expectation. Instead of dumping this solution and looking for something else - see if you can make the generated code work for you. To keep the explanation short (a more detailed explanation will follow): Application starts with a call to index.js (this is where you will plug in the db later). It calls expressServer.js which is where the express.js and openapi-validator kick in. This is an important file. Learn it. All calls to endpoints that were configured in the openapi.yaml document go to
controllers/{name_of_tag_which_the_operation_was_associated_with}.js
, which is a very small method. All the business-logic lies incontrollers/Controller.js
, and from there - toservices/{name_of_tag_which_the_operation_was_associated_with}.js
.Once you've understood what is going to happen, launch the app and ensure everything is working as expected:
npm start
Tests
Unfortunately, I have not written any unit-tests. Those will come in the future. However, the package does come with all that is needed to write and run tests - mocha and sinon and the related libraries are included in the package.js and will be installed upon npm install command
View and test the API
(Assuming no changes were made to config.js)
- API documentation, and to check the available endpoints: http://localhost:3000/api-docs/. To
- Download the oepnapi.yaml document: http://localhost:3000/openapi.
- Every call to an endpoint that was defined in the openapi document will return a 200 and a list of all the parameters and objects that were sent in the request.
- Endpoints that require security need to have security handlers configured before they can return a successful response. At this point they will return a response code of 401.
- ##### At this stage the server does not support document body sent in xml format.
Node version and guidelines
The code was written using Node version 10.6, and complies to the Airbnb .eslint guiding rules.
Project Files
Root Directory:
In the root directory we have (besides package.json, config.js, and log files):
- logger.js - where we define the logger for the project. The project uses winston, but the purpose of this file is to enable users to change and modify their own logger behavior.
- index.js - This is the project's 'main' file, and from here we launch the application. This is a very short and concise file, and the idea behind launching from this short file is to allow use-cases of launching the server with different parameters (changing config and/or logger) without affecting the rest of the code.
- expressServer.js - The core of the Express.js server. This is where the express server is initialized, together with the OpenAPI validator, OpenAPI UI, and other libraries needed to start our server. If we want to add external links, that's where they would go. Our project uses the express-openapi-validator library that acts as a first step in the routing process - requests that are directed to paths defined in the
openapi.yaml
file are caught by this process, and it's parameters and bodyContent are validated against the schema. A successful result of this validation will be a new 'openapi' object added to the request. If the path requested is not part of the openapi.yaml file, the validator ignores the request and passes it on, as is, down the flow of the Express server.
api/
- openapi.yaml - This is the OpenAPI contract to which this server will comply. The file was generated using the codegen, and should contain everything needed to run the API Gateway - no references to external models/schemas.
utils/
Currently a single file:
- openapiRouter.js - This is where the routing to our back-end code happens. If the request object includes an
openapi
object, it picks up the following values (that are part of theopenapi.yaml
file): 'x-openapi-router-controller', and 'x-openapi-router-service'. These variables are names of files/classes in the controllers and services directories respectively. The operationId of the request is also extracted. The operationId is a method in the controller and the service that was generated as part of the codegen process. The routing process sends the request and response objects to the controller, which will extract the expected variables from the request, and send it to be processed by the service, returning the response from the service to the caller.
controllers/
After validating the request, and ensuring this belongs to our API gateway, we send the request to a controller
, where the variables and parameters are extracted from the request and sent to the relevant service
for processing. The controller
handles the response from the service
and builds the appropriate HTTP response to be sent back to the user.
index.js - load all the controllers that were generated for this project, and export them to be used dynamically by the
openapiRouter.js
. If you would like to customize your controller, it is advised that you link to your controller here, and ensure that the codegen does not rewrite this file.Controller.js - The core processor of the generated controllers. The generated controllers are designed to be as slim and generic as possible, referencing to the
Controller.js
for the business logic of parsing the needed variables and arguments from the request, and for building the HTTP response which will be sent back. TheController.js
is a class with static methods..js - auto-generated code, processing all the operations. The Controller is a class that is constructed with the service class it will be sending the request to. Every request defined by the
openapi.yaml
has an operationId. The operationId is the name of the method that will be called. Every method receives the request and response, and calls theController.js
to process the request and response, adding the service method that should be called for the actual business-logic processing.
services/
This is where the API Gateway ends, and the unique business-logic of your application kicks in. Every endpoint in the openapi.yaml
has a variable 'x-openapi-router-service', which is the name of the service class that is generated. The operationID of the endpoint is the name of the method that will be called. The generated code provides a simple promise with a try/catch clause. A successful operation ends with a call to the generic Service.js
to build a successful response (payload and response code), and a failure will call the generic Service.js
to build a response with an error object and the relevant response code. It is recommended to have the services be generated automatically once, and after the initial build add methods manually.
index.js - load all the services that were generated for this project, and export them to be used dynamically by the
openapiRouter.js
. If you would like to customize your service, it is advised that you link to your controller here, and ensure that the codegen does not rewrite this file.Service.js - A utility class, very simple and thin at this point, with two static methods for building a response object for successful and failed results in the service operation. The default response code is 200 for success and 500 for failure. It is recommended to send more accurate response codes and override these defaults when relevant.
.js - auto-generated code, providing a stub Promise for each operationId defined in the
openapi.yaml
. Each method receives the variables that were defined in theopenapi.yaml
file, and wraps a Promise in a try/catch clause. The Promise resolves both success and failure in a call to theService.js
utility class for building the appropriate response that will be sent back to the Controller and then to the caller of this endpoint.
tests/
- serverTests.js - basic server validation tests, checking that the server is up, that a call to an endpoint within the scope of the
openapi.yaml
file returns 200, that a call to a path outside that scope returns 200 if it exists and a 404 if not. - routingTests.js - Runs through all the endpoints defined in the
openapi.yaml
, and constructs a dummy request to send to the server. Confirms that the response code is 200. At this point requests containing xml or formData fail - currently they are not supported in the router. - additionalEndpointsTests.js - A test file for all the endpoints that are defined outside the openapi.yaml scope. Confirms that these endpoints return a successful 200 response.
Future tests should be written to ensure that the response of every request sent should conform to the structure defined in the openapi.yaml
. This test will fail 100% initially, and the job of the development team will be to clear these tests.
models/
Currently a concept awaiting feedback. The idea is to have the objects defined in the openapi.yaml act as models which are passed between the different modules. This will conform the programmers to interact using defined objects, rather than loosley-defined JSON objects. Given the nature of JavaScript progrmmers, who want to work with their own bootstrapped parameters, this concept might not work. Keeping this here for future discussion and feedback.