Response returns undefined

I’m creating a worker to add new contacts to Constant Contact. Their API requires access token which expires in 1-2 hours after usage. So every time there is a new request to add contact I need to check if there is “unauthorized” error and get a new access token then rerun the same function with recursion.

The issue I’m encountering is only when I get and use a new access token the response returns ‘undefined’ even though a new contact was successfully added. But when access token is valid the response is fine. I have no idea why and if it’s a side effect of using recursion.

You can see in my code below I added three console logs ‘err’, ‘success’, and ‘main’ to debug. When I need to grab a new token and rerun the function this is what I get in the console:

err {error_key: "unauthorized", error_message: "Unauthorized"} 
success {contact_id: "7a918b16-21d4-11ec-aed4-fa163e0f14qq", action: "updated"}
main undefined

Here is my worker:

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

async function handleRequest(request) {
    const data = {
          'email_address': '[email protected]',
          'first_name': 'test',
          'last_name': 'test',
          'list_memberships': [
              '6743746e-1f3d-11ec-b320-fa163ef3b06c'
          ]
      }

    const response = await addContact(data)
    console.log('main', response)
    return new Response(JSON.stringify(response))
}

async function addContact(data, token) {
  let access = token || await CC_TOKENS.get('access')
  const endpoint = 'https://api.cc.email/v3/contacts/sign_up_form'
  const init = {
      method: 'POST',
      headers: {
           'Authorization': `Bearer ${access}`,
           'Content-Type': 'application/json'
      },
      body: JSON.stringify(data)
  }

  try {
      const newContact = await fetch(endpoint, init)
      const response = await newContact.json()

      if(response.error_key === 'unauthorized') {
        console.log('err', response)
        const newAccess = await getTokens()
        if(newAccess) await addContact(data, newAccess)         
      } else {
          console.log('success', response)
          return response
      }
  } 
  catch(error) {
      return error
  }   
}

async function getTokens() {
  const apiKey = CC_API_KEY
  const secret = CC_API_SECRET
  const refreshToken = await CC_TOKENS.get('refresh')
  const auth = btoa(`${apiKey}:${secret}`)
  const tokenUrl = 'https://idfed.constantcontact.com/as/token.oauth2'
  const endpoint = `${tokenUrl}?refresh_token=${refreshToken}&grant_type=refresh_token`

  try {
    const data = await fetch(endpoint, {
      method: 'POST',
      headers: {
        'Authorization': `Basic ${auth}`,
      }
    })
    const response = await data.json()
    const accessToken = response.access_token
    const refreshToken = response.refresh_token 
    await CC_TOKENS.put('access', accessToken)
    await CC_TOKENS.put('refresh', refreshToken)
    return accessToken

  } catch(error) {
    return error
  }
}

Yep, this is expected. Let me walk through your code:

  1. handleRequest is fired
  2. You fire addContact(data)
  3. You do a fetch and look at the response
    const newContact = await fetch(endpoint, init)
    const response = await newContact.json()
  4. The error_key is unauthorized as shown in your console
  5. Your if statement is ran but nothing is returned
  6. The method finishes with no return (so undefined)

You will want to return something in that unauthorized if statement

If you need any more help you can get help quickly on Discord (https://workers.community). Feel free to ping me over there if no one is around

1 Like

Ah it’s always something simple. I appreciate your help!

1 Like

This topic was automatically closed 3 days after the last reply. New replies are no longer allowed.