Skip to content

idea: use swagger sec to abstract away more of the express/req details from handler implementation #96

@lucidNTR

Description

@lucidNTR

currently swagger specs are used to parse and validate the incoming requests to a blue oak server but a handler has to get the data from the request like in old express times similar to this example facebook webhook definition:

"/facebook": {
      "x-bos-handler": "facebook",
      "get": {
        "operationId": "facebookVerify",
        "consumes": [
          "text/plain"
        ],
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "name": "hub.mode",
            "in": "query",
            "type": "string",
            "required": true,
            "example": "subscribe"
          },
          {
            "name": "hub.challenge",
            "in": "query",
            "type": "number",
            "required": true,
            "example": "1231054077"
          },
          {
            "name": "hub.verify_token",
            "in": "query",
            "type": "string",
            "required": true,
            "example": "test_token"
          }
        ],
        "responses": {
          "200": {
            "schema": {
              "type": "number"
            }
          }, ... error spec...

The handler code would currently look similar to:

export const facebookVerify = (req, res) => {
  if (req.query['hub.mode'] === 'subscribe' && req.query['hub.verify_token'] === process.env.fbWebhookVerifyToken) {
    res.status(200).set('Content-Type', 'application/json').send(req.query['hub.challenge'])
  } else {
    res.sendStatus(403)
  }
}

As a first draft to make better use of the swagger spec:

"/facebook": {
      "x-bos-handler2": "handlers/facebook",

/*-> depending if backward compatibility to express handlers of current bos is needed, 
would be named differently. handler values would not be interpreted as js files 
inside a handler folder but simply as javascript import/require statements.
This way typescipt support would be trivial, as it is handled by the node runtime/ compiler,
also this would allow direct handover to external modules or other modules
without writing server handler glue functions.
Also this would make using plugins for bos handlers as trivial as eg. 
"yarn install bos-rabbitMQ-forwarder" and then using 
"x-bos-handler2": "bos-rabbitMQ-forwarder"*/

      "get": {
        "operationId": "facebookVerify", 
-> would not need to change as the call format of operation id is implementation specific anyways

        "consumes": [
          "text/plain"
        ],
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "name": "hub.mode",
             "x-bos-rename": "mode", 
/* optional if the key name is awkward to work with as in this facebook example,
if not set the name would be used for key */

            "in": "query",
            "type": "string",
            "required": true,
            "example": "subscribe"
          }, ... etc.

then the x-bos-handler2 function signature would look like this:

export const facebookVerify = ({mode, verify_token, challenge, res}) => {
  if (mode === 'subscribe' && verifyToken === process.env.fbWebhookVerifyToken) {
    res.status(200).set('Content-Type', 'application/json').send(challenge)
  } else {
    res.sendStatus(403)
  }
}

notice:

  • this could also made to work for the body and all nested json schemas, hugely obsoleting handler glue code for most use cases,
  • the function signature with parameter destructuring would free us of sticking to a parameter order.
  • of course the req object and next function would still be there if needed, so all use cases of the old function signature would be possible ({mode, verifyToken, challenge, res, req, next}) => {...}
  • default values in swagger would be respected for everything
  • maybe its advantageous to use a data object for all parsed out data like this
    ({data, res, req, next}) => { data.mode .... data.verifyToken...}?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions