nodejsnotes

Topic 020: NodeJS Handling Undefined Values in API Responses: A Guide to Sanitization and Error Management

Topic 020: NodeJS Handling Undefined Values in API Responses: A Guide to Sanitization and Error Management


Sanitization and Undefined Issue with POST Response

When making API calls in JavaScript, sanitizing the response data can sometimes lead to unexpected behavior, especially when dealing with undefined values. Additionally, handling errors based on specific response codes is crucial for better user experience. In this post, we’ll explore a scenario where sanitizing data causes issues with checking for undefined, and how error handling can be managed in the .catch() block based on API responses.

Example Code:

const response = await axios
  .post(apiEndpoint, payload, {
    headers: {
      "content-type": "application/json",
      authorization: "Bearer " + (await getAuthToken(apiKey, userCredentials)),
      transactionID: transactionID,
      requestType: "AUTH_CHECK",
    },
  })
  .then((result) => {
    // Sanitize the result data
    console.log("SessionToken: " + JSON.parse(JSON.stringify(result.data)).sessionToken);

    // Check if sessionToken is undefined after sanitization
    if (Object.is(JSON.parse(JSON.stringify(result.data)).sessionToken, undefined)) {
      // Handling undefined session token
      console.log("SessionToken is undefined");
    }
  })
  .catch((error) => {
    console.log("Error occurred: " + error);

    if (error.response.status < 500) {
      // Client-side errors (4xx)
      console.log("Client-side error occurred");

      const errorCode = error.response.data.errors[0].code;

      // Handle error based on specific error codes
      if ("10001".match(errorCode)) {
        redirectToLoginPage();
      } else if ("10002".match(errorCode)) {
        redirectToVFPage();
      } else {
        redirectToERPage();
      }
    }
  });

Sanitization Issue:

In the example above, we’re making an axios.post() request to an API endpoint. When handling the success response inside the .then() block, we use JSON.stringify() followed by JSON.parse() to sanitize the data. This method is often used to:

However, this sanitization can also cause problems if you’re expecting certain properties to be present in the response. For instance, if result.data.sessionToken is undefined, after the sanitization process (JSON.stringify() and JSON.parse()), the sessionToken property will no longer exist in the object.

This makes checking for undefined problematic, as the property is removed entirely. The condition:

if (Object.is(JSON.parse(JSON.stringify(result.data)).sessionToken, undefined))

will not be met because sessionToken is removed during sanitization. The correct way to handle this would be to check for the existence of the property first, using hasOwnProperty():

if (!result.data.hasOwnProperty("sessionToken")) {
  console.log("SessionToken is missing or undefined");
}
if (result.data.hasOwnProperty("SessionToken") && Object.is(result.data.SessionToken, undefined)) {
  // Your logic for undefined SessionToken
}

Error Handling Based on Response:

In the .catch() block, we handle potential errors returned by the API. First, we check if the error status is a client-side error (status codes 4xx). If so, we inspect the error code returned in the API response and take specific actions based on this error code.

Here’s how the error handling logic works:

This error handling structure allows you to customize the user experience based on the specific error scenario, ensuring users are directed to the appropriate next steps.

Handling Response Scenarios:

Here are some example scenarios and how they would be handled in the .catch() block:

Scenario 1: Missing Session Token

{
  "sessionToken": undefined
}

In this case, after sanitization, the sessionToken property is removed from the object. We handle this by checking for the existence of sessionToken using hasOwnProperty() and logging an appropriate message.

Scenario 2: Client Error with Error Code 10002

{
  "response": {
    "errors": [
      {
        "code": "10002",
        "message": "Email not verified"
      }
    ]
  }
}

In this scenario, the error response contains the code 10002, indicating that the email is not verified. The .catch() block will match this error code and invoke redirectToVFPage(), directing the user to complete email verification.

Scenario 3: Client Error with Unhandled Error Code

{
  "response": {
    "errors": [
      {
        "code": "10040",
        "message": "Unexpected error"
      }
    ]
  }
}

Here, the error code 10040 does not match any specific conditions in our error handling logic, so the default action will be to redirect the user to a general error page via redirectToERPage().


Explanation: