Access the Body of an Object Literal Response

Hi everyone,

My apologies if this has been asked before.

I’m working on a project with Workers is triggered by webhooks from our Ghost blog. The eventual plan is to use the data from the Ghost webhooks to update our Algolia index with new and recently changed articles. The problem I’m having is that the response from Ghost is a JavaScript object, the body of which is a JSON object that contains all the information about the article. I can read the response with response.text(), but unfortunately that returns a string, making it difficult to access the body of the Ghost object.

Has anyone run into a similar problem? Here’s some code for reference:

const { addIndex } = require('./src/handler.js');
import Router from './src/router';

addEventListener('fetch', event => {
  event.respondWith(handleRequest(event.request));
})

async function handleRequest(request) {
  const r = new Router();

  let data = await request.text();

  console.log(data); // Returns Ghost Object literal as a string

  r.post('.*/add', req => addIndex(req));

  let response = await r.route(request);

  if (!response) {
    response = new Response('Not found', { status: 404 });
  }

  return response;
}

And here’s the Ghost object that becomes a string with await request.text():

{ body:
   '{"post":{"current":{"id":"5d5f54ae954bd5570f5db4f1","uuid":"d34d53b2-43f9-4a4e-bc3a-f3f7c02d5604","title":"published test","slug":"published-test","mobiledoc":"{\\"version\\":\\"0.3.1\\",\\"atoms\\":[],\\"cards\\":[],\\"markups\\":[],\\"sections\\":[[1,\\"p\\",[[0,[],0,\\"sdfsdfsdf\\"]]]]}","html":"<p>sdfsdfsdf</p>","comment_id":"5d5f54ae954bd5570f5db4f1","plaintext":"sdfsdfsdf","feature_image":"http://localhost:2368/content/images/2019/08/0_gbMqAQW9_uIJYIcj.jpeg","featured":false,"status":"published","meta_title":null,"meta_description":null,"created_at":"2019-08-23T02:51:26.000Z","updated_at":"2019-08-23T02:58:05.887Z","published_at":"2019-08-23T02:51:46.000Z","custom_excerpt":null,"codeinjection_head":null,"codeinjection_foot":null,"og_image":null,"og_title":null,"og_description":null,"twitter_image":null,"twitter_title":null,"twitter_description":null,"custom_template":null,"canonical_url":null,"authors":[{"id":"1","name":"Kris K.","slug":"kris","email":"[email protected]","profile_image":null,"cover_image":null,"bio":null,"website":null,"location":null,"facebook":null,"twitter":null,"accessibility":null,"status":"active","meta_title":null,"meta_description":null,"tour":"[\\"upload-a-theme\\"]","last_seen":"2019-08-23T02:13:54.000Z","created_at":"2019-06-25T03:29:08.000Z","updated_at":"2019-08-23T02:13:54.000Z","roles":[{"id":"5d119504007beb5f31d48ddd","name":"Owner","description":"Blog Owner","created_at":"2019-06-25T03:29:08.000Z","updated_at":"2019-06-25T03:29:08.000Z"}],"url":"http://localhost:2368/author/kris/"}],"tags":[{"id":"5d119504007beb5f31d48dd4","name":"Getting Started","slug":"getting-started","description":null,"feature_image":null,"visibility":"public","meta_title":null,"meta_description":null,"created_at":"2019-06-25T03:29:08.000Z","updated_at":"2019-06-25T03:29:08.000Z","url":"http://localhost:2368/tag/getting-started/"}],"primary_author":{"id":"1","name":"Kris K.","slug":"kris","email":"[email protected]","profile_image":null,"cover_image":null,"bio":null,"website":null,"location":null,"facebook":null,"twitter":null,"accessibility":null,"status":"active","meta_title":null,"meta_description":null,"tour":"[\\"upload-a-theme\\"]","last_seen":"2019-08-23T02:13:54.000Z","created_at":"2019-06-25T03:29:08.000Z","updated_at":"2019-08-23T02:13:54.000Z","roles":[{"id":"5d119504007beb5f31d48ddd","name":"Owner","description":"Blog Owner","created_at":"2019-06-25T03:29:08.000Z","updated_at":"2019-06-25T03:29:08.000Z"}],"url":"http://localhost:2368/author/kris/"},"primary_tag":{"id":"5d119504007beb5f31d48dd4","name":"Getting Started","slug":"getting-started","description":null,"feature_image":null,"visibility":"public","meta_title":null,"meta_description":null,"created_at":"2019-06-25T03:29:08.000Z","updated_at":"2019-06-25T03:29:08.000Z","url":"http://localhost:2368/tag/getting-started/"},"url":"http://localhost:2368/published-test/","excerpt":"sdfsdfsdf"},"previous":{"status":"draft","updated_at":"2019-08-23T02:58:04.000Z"}}}',
  headers:
   { 'user-agent': 'Ghost/2.29.1 (https://github.com/TryGhost/Ghost)',
     'content-length': '2994',
     'content-type': 'application/json',
     'accept-encoding': 'gzip, deflate',
     Host: 'localhost:3000',
     Connection: 'close' },
  httpMethod: 'POST',
  multiValueHeaders:
   { 'user-agent': [ 'Ghost/2.29.1 (https://github.com/TryGhost/Ghost)' ],
     'content-length': [ '2994' ],
     'content-type': [ 'application/json' ],
     'accept-encoding': [ 'gzip, deflate' ],
     Host: [ 'localhost:3000' ],
     Connection: [ 'close' ] },
  multiValueQueryStringParameters: null,
  path: '/add',
  pathParameters: null,
  queryStringParameters: null,
  requestContext:
   { accountId: 'offlineContext_accountId',
     apiId: 'offlineContext_apiId',
     authorizer:
      { principalId: 'offlineContext_authorizer_principalId',
        claims: undefined },
     httpMethod: 'POST',
     identity:
      { accountId: 'offlineContext_accountId',
        apiKey: 'offlineContext_apiKey',
        caller: 'offlineContext_caller',
        cognitoAuthenticationProvider: 'offlineContext_cognitoAuthenticationProvider',
        cognitoAuthenticationType: 'offlineContext_cognitoAuthenticationType',
        cognitoIdentityId: 'offlineContext_cognitoIdentityId',
        cognitoIdentityPoolId: 'offlineContext_cognitoIdentityPoolId',
        sourceIp: '127.0.0.1',
        user: 'offlineContext_user',
        userAgent: 'Ghost/2.29.1 (https://github.com/TryGhost/Ghost)',
        userArn: 'offlineContext_userArn' },
     protocol: 'HTTP/1.1',
     requestId: 'offlineContext_requestId_cjzniyyom000a9ywu61zy3iu5',
     requestTimeEpoch: 1566529085968,
     resourceId: 'offlineContext_resourceId',
     resourcePath: '/add',
     stage: 'dev' },
  resource: '/add',
  stageVariables: null,
  isOffline: true }

Shouldnt JSON.parse() take care of that?

Thanks for the quick response!

JSON.parse(data) throws an error, at least when I use wrangler preview and do a POST request with the object in the body.

And the error is?

The error reads Uncaught (in response) SyntaxError: Unexpected token b in JSON at position 2.

Well, in that case whatever you are passing is not a valid JSON object/string.

But generally, that subject is slightly off-topic here. This is just regular JavaScript development and not really Cloudflare related. I’d take it to e.g. StackOverflow.

1 Like

I see, I was afraid of that. Was hoping that someone else had experience dealing with an object literal as a response with some nested JSON, or that I missed something in the Cloudflare docs.

Thanks for your help! Sorry for the off topic question. I could delete this thread so it doesn’t distract from other issues.

Just make sure you are passing a valid JSON string and you should be fine.

1 Like