Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

swagger-node(swagger and node.js) #241

Open
uniquejava opened this issue Oct 16, 2018 · 3 comments
Open

swagger-node(swagger and node.js) #241

uniquejava opened this issue Oct 16, 2018 · 3 comments

Comments

@uniquejava
Copy link
Owner

uniquejava commented Oct 16, 2018

项目地址: https://github.com/swagger-api/swagger-node
官方文档: https://github.com/swagger-api/swagger-node/tree/master/docs
非常重要的官方文档(如: default.yaml的配置)
https://github.com/apigee-127/swagger-node-runner/releases/tag/v0.6.0

必须要配置_swagger_params_parser不然连req.body都取不到.

npm i -g swagger
swagger project create hello-world
swagger project start
swagger project edit

但是这个swagger project edit打开的界面特别LOW且buggy, 我是直接到这里去编辑yaml文件: http://editor.swagger.io

使用swagger命令生成的项目结构:
image

测试: http://127.0.0.1:10010/hello?name=Scott

内置的swagger-express-mw还是0.1.0版本, editor界面十分之丑陋.

可以将其升级到swagger-express-mw到0.7.0:
详见: https://github.com/swagger-api/swagger-node/issues/551

0.7.0不再自带swagger-tools需要单独安装

npm i swagger-tools

在app.js中

const SwaggerUi = require("swagger-tools/middleware/swagger-ui");

swaggerExpress.register(app);
let defaultOptions = {
  apiDocs: "/xxxxx/api-docs",
  swaggerUi: "/xxxxx/docs"
};

if (isDev) {
  app.use(SwaggerUi(swaggerExpress.runner.swagger, defaultOptions));
  let swaggerUiURL = `http://localhost:${port}${defaultOptions.swaggerUi}`;
  logger.info(`Swagger UI is available at:\n${swaggerUiURL}`);
}

OpenAPI specification(v2 / v3)
https://swagger.io/resources/open-api/

See swagger and OpenAPI in general #167

swagger project edit会打开chrome browser在线编辑yaml文件, 这个文件和项目中的api/swagger/swagger.yaml是同步变化的.

x-swagger-router-controller指定使用api/controllers/下的哪个文件处理请求
operationId 指定应该调用controller中的哪个方法

https://stackoverflow.com/questions/48111459/how-to-define-a-property-that-can-be-string-or-null-in-openapi-swagger

@uniquejava
Copy link
Owner Author

uniquejava commented Oct 26, 2018

怎么在mongodb初始化结束后再启动test case

搭配使用app.emit('ready')before(()=>app.on('ready', done))
https://stackoverflow.com/questions/18941736/ensuring-express-app-is-running-before-each-mocha-test

为什么在POST body为空时还需要指定content-type为application/json?

原因见: https://github.com/swagger-api/swagger-ui/issues/1576
解决办法, 修改swagger.yaml对consumes部分的定义:

consumes:
  - application/json
  - application/octet-stream

这样测试POST请求时如果body为空, 可以不必指定content-type: application/json.

swagger-node怎么定义securityHandlers

app.js:

var config = {
  appRoot: __dirname, // required config
  swaggerSecurityHandlers: {
    api_key: function (req, authOrSecDef, scopesOrApiKey, cb) {
      // your security code
      if ('1234' === scopesOrApiKey) {
        cb(null);
      } else {
        cb(new Error('access denied!'));
      }
    }
  }
};

api/swagger/swagger.yaml:

securityDefinitions:
  api_key:
    type: apiKey
    in: query
    name: api_key
paths:
  /hello:
    get:
      security:
        - api_key: [ ]

感谢: https://github.com/swagger-api/swagger-node/issues/228#issuecomment-163805253

怎么修改securityHandler返回的statusCode

var err = new Error('Failed to authenticate using bearer token');
err['statusCode'] = 403; // custom error code
callback(err);

感谢: https://github.com/apigee-127/swagger-tools/issues/203#issuecomment-246210465

还有这里!! https://github.com/swagger-api/swagger-node/issues/228

异常处理

如果想在app.js中添加自己的global error handler

// error handler
const errorHandler = (err, req, res, next) => {
  logger.error("caught by global error handler...");

  logger.error(err);

  let code = err.code || "server_error";
  let message = err.message;
  let statusCode = err.statusCode || 500;

  res.status(statusCode);
  res.json({ code, message, statusCode });
};

就是让next(error)能走到app.js、就得在default.yaml中注释掉这行 - onError: json_error_handler

    # pipe for all swagger-node controllers
    swagger_controllers:
      # - onError: json_error_handler
      - cors
      - _swagger_params_parser
      - swagger_security
      - _swagger_validate
      - express_compatibility
      - _router

一下子, 感觉空气好多了.
参考: No clear error handling documentation https://github.com/swagger-api/swagger-node/issues/410

@uniquejava uniquejava changed the title swagger and node.js node-swagger(swagger and node.js) Oct 26, 2018
@uniquejava uniquejava changed the title node-swagger(swagger and node.js) swagger-node(swagger and node.js) Oct 26, 2018
@uniquejava
Copy link
Owner Author

uniquejava commented Nov 19, 2018

格式问题

https://stackoverflow.com/questions/45549663/swagger-editor-shows-the-schema-error-should-not-have-additional-properties-e

https://stackoverflow.com/questions/31033394/swagger-editor-multiple-parameters-in-body

https://swagger.io/docs/specification/2-0/describing-request-body/

关于body要说的

  1. body的类型必定是object,即使body中只包含一个字段.因为我们统一了content-type为applicaton/json,
    只有object和json能对应上(不可以是string)
  2. 基本上name也写成body, 即in: body, name: body, 这样方便在swagger中查看,换成其它的name既不统一,也不便于查看.

      parameters:
        - in: body
          name: client_id
          description: client id(speaker or web)
          required: true
          type: string

      parameters:
        - in: body
          name: client_id
          description: client id(speaker or web)
          required: true
          schema:
            type: string

你至多只能传一个body参数. 见: https://stackoverflow.com/questions/31033394/swagger-editor-multiple-parameters-in-body

paths:
  # This is a path endpoint. Change it.
  /tasks:
    post:
      description: |
        Add 'Task' object.
      parameters:
        - name: task 
          in: body
          description: task object
          required: true
          schema:
            $ref: '#/definitions/Task'

再一例

      parameters:
        - in: body
          name: user
          description: The user to create.
          schema:
            type: object
            required:
              - userName
            properties:
              userName:
                type: string
              firstName:
                type: string
              lastName:
                type: string

@uniquejava
Copy link
Owner Author

uniquejava commented Dec 10, 2018

swagger-node 内置了multer做为文件上传组件.

upload single file

swagger-node完全支持单文件上传

相关的swagger文档: https://swagger.io/docs/specification/2-0/file-upload/

需要在app.js中对multer进行配置:

    let upload = multer({
      storage: multer.memoryStorage(),
      limits: {
        fileSize: 5 * 1024 * 1024
      }
    });

    app.use(upload.fields([{ name: "myfile" }]));

swagger.yaml

      consumes:
        - multipart/form-data
      parameters:
        - name: client_id
          in: query
          description: client id
          type: string
          required: true
        - name: first_name
          in: formData
          type: string
          required: true
        - name: last_name
          in: formData
          type: string
          required: true
        - name: email
          in: formData
          type: string
          required: true
        - name: myfile
          in: formData
          type: file
          # items:
          #   type: string
          #   format: binary
          required: true

upload multiple files

swagger-node不支持多文件上传, 不过有一个PR: https://github.com/apigee-127/swagger-tools/pull/550, 好用但未被合并.

        - name: myfile
          in: formData
          type: array
          items:
            type: string
            format: binary
          required: true

final solution

        - name: myfile
          in: formData
          type: file
          items:
            type: string
            format: binary
          required: true

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant