Skip to content

Conversation

@talissoncosta
Copy link
Contributor

@talissoncosta talissoncosta commented Nov 10, 2025

The Angular HttpClient fetch adapter was not properly implementing the Fetch API interface, causing critical issues:

  • ❌ Response objects missing status property
  • ❌ Error messages and response bodies displaying as [Object object] instead of actual content
  • ❌ No way to detect HTTP error status codes (401, 404, 500, etc.)
  • ❌ Inconsistent error handling between success and error responses

This prevented proper error handling in Angular applications using the Flagsmith SDK, making debugging difficult and breaking standard HTTP error flows.

Solution

Refactored utils/angular-fetch.ts to properly bridge Angular's Observable-based HttpClient API with the standard Fetch API interface expected by the Flagsmith SDK.

Key Changes

1. Added required Angular HttpClient options:

const options = {
  headers,
  observe: 'response',    // Access full response with status/headers
  responseType: 'text'     // Get raw text instead of auto-parsed JSON
}

Why these are critical:

  • observe: 'response' - Angular returns only the body by default. This option gives us the full HttpResponse object with status, headers, and body.
  • responseType: 'text' - Angular auto-parses JSON responses. The SDK expects raw text to call .text() on the response, matching the Fetch API contract.

2. Unified response transformation:

Created a buildResponse() helper that transforms both success and error responses into a consistent Fetch-compatible format:

const buildResponse = (response: any, ok: boolean) => ({
  status: response?.status ?? (ok ? 200 : 500),
  ok,
  headers: { get: (name: string) => response?.headers?.get?.(name) ?? null },
  text: () => {
    const value = response?.body ?? response?.error ?? response?.message ?? '';
    return Promise.resolve(typeof value !== 'string' ? JSON.stringify(value) : value);
  }
});

Benefits:

  • Single source of truth for response transformation
  • Proper ok field derivation based on HTTP status codes (200-299 = true)
  • Fallback handling for missing status codes
  • Error messages properly extracted from error or message fields
  • JSON objects properly stringified instead of becoming [Object object]

3. Improved error handling:

  • Both success and error callbacks now use the same transformation logic
  • Errors resolve (not reject) with ok: false, matching Fetch API behavior
  • 405 status for unsupported HTTP methods (with descriptive error message)

4. Fixed JSON object stringification in text() method:

When Angular HttpClient returns JSON objects (even with responseType: 'text'), the text() method now properly stringifies them:

text: () => {
  const value = body ?? error ?? message ?? '';
  return Promise.resolve(typeof value !== 'string' ? JSON.stringify(value) : value);
}

Why this matters:

  • Angular sometimes returns parsed JSON objects even when responseType: 'text' is set
  • Without stringification, objects become "[Object object]" when coerced to strings
  • The Fetch API contract requires text() to return a string, which is then parsed by JSON.parse() in the SDK
  • This ensures proper JSON parsing in flagsmith-core.ts line 865

Testing

Unit Tests

Added comprehensive test suite with 12 test cases covering all scenarios in test/angular-fetch.test.ts:

Core functionality:

  • ✅ GET requests return proper status and ok properties
  • ✅ POST requests work correctly with body data
  • ✅ PUT requests handled properly
  • ✅ Headers retrieval via headers.get() method

Error handling:

  • ✅ Various HTTP error codes (400, 403, 404, 500, 503) with proper ok: false
  • ✅ Error messages correctly extracted from response
  • ✅ 3xx redirect status codes marked as ok: false

Edge cases:

  • ✅ Fallback status codes when status is missing (200 for success, 500 for errors)
  • ✅ Fallback error messages when error/message properties are missing
  • ✅ Unsupported HTTP methods return 405 status
  • ✅ JSON objects in response body/error/message properly stringified
  • ✅ String responses passed through without modification
  • ✅ Full integration with Flagsmith initialization

Test results:

npm test -- angular-fetch.test

PASS test/angular-fetch.test.ts
  ✓ 12 tests passed

Manual Testing in Angular App

Quick setup with npm link:

# In flagsmith-js-client repo
npm run build
cd lib/flagsmith
npm link

# In your Angular app
npm link flagsmith

# Then run the Angular app and check if there is any error on console

Test scenarios:

Scenario Before Fix After Fix
Valid API key [object Object] error ✅ Initializes successfully
Invalid API key (401) [object Object] error ✅ Shows "Unauthorized"
Network error [object Object] error ✅ Shows descriptive error
Flag access ❌ Not working hasFeature() works

Files Changed

  • utils/angular-fetch.ts - Core fix with proper response/error handling and JSON stringification
  • test/angular-fetch.test.ts - New comprehensive test suite with 12 test cases

Breaking Changes

None - This fix maintains backward compatibility while adding missing properties and fixing bugs.

@talissoncosta talissoncosta requested a review from a team as a code owner November 10, 2025 20:20
@talissoncosta talissoncosta requested review from kyle-ssg and removed request for a team November 10, 2025 20:20
@talissoncosta talissoncosta marked this pull request as draft November 10, 2025 20:20
@talissoncosta talissoncosta linked an issue Nov 12, 2025 that may be closed by this pull request
@talissoncosta talissoncosta force-pushed the fix/angular-client-init branch from e5effa0 to 7232757 Compare November 12, 2025 20:21
@talissoncosta talissoncosta force-pushed the fix/angular-client-init branch from 7232757 to 6b7760e Compare November 12, 2025 20:24
@talissoncosta talissoncosta marked this pull request as ready for review November 12, 2025 20:29
Copy link
Contributor

@Zaimwa9 Zaimwa9 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, thanks for the comprehensive testing, just 2 comments

Copy link
Contributor

@Zaimwa9 Zaimwa9 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@talissoncosta talissoncosta merged commit 44e4b79 into main Nov 18, 2025
1 check passed
@talissoncosta talissoncosta deleted the fix/angular-client-init branch November 18, 2025 12:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Using angularHttpClient cause Fetch error:

3 participants