【问题标题】:NodeJS Listener for webhooks returns empty body用于 webhook 的 NodeJS 侦听器返回空主体
【发布时间】:2021-04-22 00:25:18
【问题描述】:

我已经做了大约 2 天了,准备拔掉头发。

我有一个系统可以触发我需要捕获和解析的简单 Webhook。我创建了一个非常简单的 Nodejs 侦听器,并且正在运行 Ngrok 来创建公共地址。我收到一个请求,但无论我做什么,身体都是空的。与 content-type 或 app.use(bodyParser.urlencoded()) 无关。

正文仍以 {}

的形式返回
'use strict'

const express = require('express')
const bodyParser = require('body-parser')

// Create a new instance of express
const app = express()

// Tell express to use the body-parser middleware and to not parse extended bodies
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: false }))

// Route that receives a POST request to /sms
app.post('/', function (req, res) {
    console.log(req);
  const body = req.body
  console.log("body")
  console.log(body);
  res.set('Content-Type', 'text/plain')
  res.send(`You sent: ${body} to Express`)
})


// Tell our app to listen on port 4545
app.listen(4545, function (err) {
  if (err) {
    throw err
  }

  console.log('Server started on port 4545')
})

但是,如果我将地址设置为https://webhook.sitehttps://pipedream.com,那么正文确实已发布。我尝试过内容类型、urlencode 的组合,甚至认为它是 gzip 或其他东西,甚至部署在 Azure VM 和其他上。什么都没有。

但是当我将地址设置为 webhook 或 pipedream 时,数据显示没有问题。

在一些 cmets 之后,我想添加 console.log(req) 的结果(部分结果):

complete: false,
    headers: {
      connection: 'Keep-Alive',
      'accept-encoding': 'gzip',
      host: 'localhost:4646',
      'max-forwards': '10',
      'user-agent': 'Go-http-client/2.0',
      'content-length': '339'
    },
    rawHeaders: [
      'Connection',
      'Keep-Alive',
      'Accept-Encoding',
      'gzip',
      'Host',
      'localhost:4646',
      'Max-Forwards',
      '10',
      'User-Agent',
      'Go-http-client/2.0',
      'X-Original-URL',
      '/',
      'Content-Length',
      '339'
    ],
    trailers: {},
    rawTrailers: [],
    aborted: false,
    upgrade: false,
    url: '/',
    method: 'POST',
    statusCode: null,
    statusMessage: null,
    client: Socket {
      connecting: false,
      _hadError: false,
      _parent: null,
      _host: null,
      _readableState: [ReadableState],
      readable: true,
      _events: [Object: null prototype],
      _eventsCount: 8,
      _maxListeners: undefined,
      _writableState: [WritableState],
      writable: true,
      allowHalfOpen: true,
      _sockname: null,
      _pendingData: null,
      _pendingEncoding: '',
      server: [Server],
      _server: [Server],
      timeout: 120000,
      parser: [HTTPParser],
      on: [Function: socketListenerWrap],
      addListener: [Function: socketListenerWrap],
      prependListener: [Function: socketListenerWrap],
      _paused: false,
      _httpMessage: [Circular],
      [Symbol(asyncId)]: 115,
      [Symbol(kHandle)]: [TCP],
      [Symbol(kSetNoDelay)]: false,
      [Symbol(lastWriteQueueSize)]: 0,
      [Symbol(timeout)]: Timeout {
        _idleTimeout: 120000,
        _idlePrev: [TimersList],
        _idleNext: [Timeout],
        _idleStart: 6602,
        _onTimeout: [Function: bound ],
        _timerArgs: undefined,
        _repeat: null,
        _destroyed: false,
        [Symbol(refed)]: false,
        [Symbol(asyncId)]: 116,
        [Symbol(triggerId)]: 115
      },
      [Symbol(kBuffer)]: null,
      [Symbol(kBufferCb)]: null,
      [Symbol(kBufferGen)]: null,
      [Symbol(kCapture)]: false,
      [Symbol(kBytesRead)]: 0,
      [Symbol(kBytesWritten)]: 0
    },
    _consuming: false,
    _dumped: false,
    next: [Function: next],
    baseUrl: '',
    originalUrl: '/',
    _parsedUrl: Url {
      protocol: null,
      slashes: null,
      auth: null,
      host: null,
      port: null,
      hostname: null,
      hash: null,
      search: null,
      query: null,
      pathname: '/',
      path: '/',
      href: '/',
      _raw: '/'
    },
    params: {},
    query: {},
    res: [Circular],
    body: {},
    route: Route { path: '/', stack: [Array], methods: [Object] },
    [Symbol(kCapture)]: false
  },
  locals: [Object: null prototype] {},
  [Symbol(kCapture)]: false,
  [Symbol(kNeedDrain)]: false,
  [Symbol(corked)]: 0,
  [Symbol(kOutHeaders)]: [Object: null prototype] {
    'x-powered-by': [ 'X-Powered-By', 'Express' ]
  }
}

console.log(req)时可以看到body为空

任何人都可以让我按照正确的方式解决这个问题吗?

非常感谢。

【问题讨论】:

  • 正文将在req.body 中,而不是在req.req
  • 抱歉,它是 req.body (已更正)。 req.req 是由于尝试其他所有输入而感到沮丧。 req.budy 只返回 {}
  • 发送你的身体空虚的卷曲

标签: node.js express webhooks


【解决方案1】:

你可以在req.body获取body数据 包括 body-parser 中间件,它解析 body 并设置 req.body 属性。

var bodyParser = require('body-parser')
app.use(bodyParser.urlencoded({ extended: false })) 

// Route that receives a POST request to /sms
app.post('/', function (req, res) {
  console.log(req);
  const body = req.body
  console.log("body")
  console.log(body);
  res.set('Content-Type', 'text/plain')
  res.send(`You sent: ${body} to Express`)
})

【讨论】:

  • 抱歉,我之前有一个错字。它是 req.body 并返回一个空的 body {}。控制台日志返回(为了更清楚,我在上面添加了新的编辑和粘贴)
【解决方案2】:

因此,对于遇到类似问题的其他人,这就是我要解决的问题:

我必须在标题中注入一个内容类型,然后中提琴开始出现正文:

var customParser = bodyParser.json({type: function(req) {
    if (req.headers['content-type'] === ""){
        return req.headers['content-type'] = 'application/json';
    }
    else if (typeof req.headers['content-type'] === 'undefined'){
        return req.headers['content-type'] = 'application/json';
    }else{
        return req.headers['content-type'] = 'application/json';
    }
}});


app.use(bodyParser.json({
  limit: '50mb',
  extended: true
})); // support encoded bodies

app.use(bodyParser.urlencoded({
  limit: '50mb',
  extended: true
})); // support encoded bodies


app.post("/hook", customParser, (req, res) => {
    //console.log(req);
    //const fs = require('fs');
    console.log("Events req.body", req.body) // Call your action on the request here

    res.status(200).end()
  })

这对我有用。

谢谢

【讨论】:

  • 谢谢,它有效
猜你喜欢
  • 1970-01-01
  • 2015-06-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多