Webhooks send empty body to Vercel API

I’m using Moralis webhooks to write my cloud functions and am deploying them to Vercel.

When I run my server locally (next dev) and point the Moralis webhooks to it by using ngrok, I see the body and everything works. But, when the webhooks are pointing to the actual deployed API in Vercel, the body is always empty in the request object.

Somebody was having the exact same issue but when using Moralis.cloud.httpRequest to call their Vercel endpoint: https://discord.com/channels/819584798443569182/819584798443569185/872549645367263252. This seems like the same scenario but for webhooks.

Can you paste a complete request with the http headers of what you receive on your local server from webhooks (when it works ok)?
Just to see how that content-length was set there. As you assume that it is a problem how web hooks set content length header field.

Here it is:

{
  req: IncomingMessage {
    _readableState: ReadableState {
      objectMode: false,
      highWaterMark: 16384,
      buffer: BufferList { head: null, tail: null, length: 0 },
      length: 0,
      pipes: [],
      flowing: true,
      ended: true,
      endEmitted: true,
      reading: false,
      sync: true,
      needReadable: false,
      emittedReadable: false,
      readableListening: false,
      resumeScheduled: false,
      errorEmitted: false,
      emitClose: true,
      autoDestroy: false,
      destroyed: false,
      errored: null,
      closed: false,
      closeEmitted: false,
      defaultEncoding: 'utf8',
      awaitDrainWriters: null,
      multiAwaitDrain: false,
      readingMore: true,
      decoder: null,
      encoding: null,
      [Symbol(kPaused)]: false
    },
    _events: [Object: null prototype] { end: [Function: clearRequestTimeout] },
    _eventsCount: 1,
    _maxListeners: undefined,
    socket: Socket {
      connecting: false,
      _hadError: false,
      _parent: null,
      _host: null,
      _readableState: [ReadableState],
      _events: [Object: null prototype],
      _eventsCount: 8,
      _maxListeners: undefined,
      _writableState: [WritableState],
      allowHalfOpen: true,
      _sockname: null,
      _pendingData: null,
      _pendingEncoding: '',
      server: [Server],
      _server: [Server],
      parser: [HTTPParser],
      on: [Function: socketListenerWrap],
      addListener: [Function: socketListenerWrap],
      prependListener: [Function: socketListenerWrap],
      _paused: false,
      _httpMessage: [ServerResponse],
      [Symbol(async_id_symbol)]: 64633,
      [Symbol(kHandle)]: [TCP],
      [Symbol(kSetNoDelay)]: false,
      [Symbol(lastWriteQueueSize)]: 0,
      [Symbol(timeout)]: null,
      [Symbol(kBuffer)]: null,
      [Symbol(kBufferCb)]: null,
      [Symbol(kBufferGen)]: null,
      [Symbol(kCapture)]: false,
      [Symbol(kBytesRead)]: 0,
      [Symbol(kBytesWritten)]: 0,
      [Symbol(RequestTimeout)]: undefined
    },
    httpVersionMajor: 1,
    httpVersionMinor: 1,
    httpVersion: '1.1',
    complete: true,
    headers: {
      host: 'redacted',
      'transfer-encoding': 'chunked',
      'content-type': 'application/json',
      'x-forwarded-for': redacted',
      'x-forwarded-proto': 'https',
      'accept-encoding': 'gzip'
    },
    rawHeaders: [
      'Host',
      'redacted',
      'Transfer-Encoding',
      'chunked',
      'Content-Type',
      'application/json',
      'X-Forwarded-For',
      'redacted',
      'X-Forwarded-Proto',
      'https',
      'Accept-Encoding',
      'gzip'
    ],
    trailers: {},
    rawTrailers: [],
    aborted: false,
    upgrade: false,
    url: '/api/user/edit',
    method: 'POST',
    statusCode: null,
    statusMessage: null,
    client: Socket {
      connecting: false,
      _hadError: false,
      _parent: null,
      _host: null,
      _readableState: [ReadableState],
      _events: [Object: null prototype],
      _eventsCount: 8,
      _maxListeners: undefined,
      _writableState: [WritableState],
      allowHalfOpen: true,
      _sockname: null,
      _pendingData: null,
      _pendingEncoding: '',
      server: [Server],
      _server: [Server],
      parser: [HTTPParser],
      on: [Function: socketListenerWrap],
      addListener: [Function: socketListenerWrap],
      prependListener: [Function: socketListenerWrap],
      _paused: false,
      _httpMessage: [ServerResponse],
      [Symbol(async_id_symbol)]: 64633,
      [Symbol(kHandle)]: [TCP],
      [Symbol(kSetNoDelay)]: false,
      [Symbol(lastWriteQueueSize)]: 0,
      [Symbol(timeout)]: null,
      [Symbol(kBuffer)]: null,
      [Symbol(kBufferCb)]: null,
      [Symbol(kBufferGen)]: null,
      [Symbol(kCapture)]: false,
      [Symbol(kBytesRead)]: 0,
      [Symbol(kBytesWritten)]: 0,
      [Symbol(RequestTimeout)]: undefined
    },
    _consuming: false,
    _dumped: false,
    cookies: [Getter/Setter],
    __NEXT_INIT_QUERY: {},
    __nextHadTrailingSlash: undefined,
    query: {},
    previewData: [Getter/Setter],
    preview: [Getter/Setter],
    body: {
      params: [Object],
      master: false,
      user: [Object],
      installationId: 'redacted',
      log: [Object],
      headers: [Object],
      ip: 'redacted',
      functionName: 'editProfile',
      context: {}
    },
    [Symbol(kCapture)]: false,
    [Symbol(RequestTimeout)]: undefined
  }
}

And to be clear, the content-length does not seem to be present for this request either, but it seems like my local server doesn’t care and still parses the body correctly. It seems that the issue is only when it’s actually deployed in Vercel where the content-length starts coming into play.

Were you guys able to look into this today? Our team is basically blocked for promoting to our staging and prod envs because of this. Right now we’re just able to develop locally.

Thanks!

@cryptokid shameless ping. Sorry, we’re just blocked on promotions with this issue. Is there a way that you guys can check what headers the webhook calls attach to the requests they make?

Maybe the content-length is not being passed.

1 Like

@cryptokid I opened an issue on the Parse repo here: https://github.com/parse-community/parse-server/issues/7646. I’ll try to make a PR and see if they accept it.

@cryptokid and the PR: https://github.com/parse-community/parse-server/pull/7647/files

It’d be great that someone from Moralis could back me up in the PR comments and hopefully also keep track of it so you guys can update once it gets merged.

1 Like

Hi there, Manuel from the Parse Server team here. Thanks for opening the PR, it will be merged (pending review changes), but only into our Parse Server 5.0 alpha release. If it helps the Moralis team, we could also backport it into our 4.x release, which we would usually only do with security fixes. Let us know in case you need that.

3 Likes

Hi @mtrezzathanks thanks a lot for helping us out!
It’s great to have confirmation from you guys that this is valid solution, we can merge it ourselves into our server as it’s a small change.

Thanks for great work :clap::clap:

1 Like

@ivan Sure, feel free to reach out anytime. Off-topic, we are working internally on a blockchain module for Parse Server. We’d be interested in your expert opinion on that topic before we make it public. If you are interested, just send a PM and we can schedule a demo.

For sure - sending DM :raised_hands:

Thanks everyone!

Could you please ping me here when the fix out?

1 Like

We will ping you when the fix is out.

1 Like

Content-length has just been added to the header.
Can you update your server (v0.0.281) and check if it works with this fix?

3 Likes

Confirmed! Everything is working on Vercel now!

Thanks for following up on this.

2 Likes