Skip to content

Remove axios dep#466

Open
KoblerS wants to merge 2 commits into
mainfrom
remove-axios-dep
Open

Remove axios dep#466
KoblerS wants to merge 2 commits into
mainfrom
remove-axios-dep

Conversation

@KoblerS

@KoblerS KoblerS commented Jun 15, 2026

Copy link
Copy Markdown
Member

Remove axios Dependency in Favor of Built-in fetch API

Chore

♻️ Refactor: Replaced the axios external dependency with Node.js built-in fetch and https APIs across the codebase, reducing the dependency footprint.

Changes

Two internal helper functions were introduced to replace axios behavior:

  • _fetch(url, options) — wraps the global fetch API with JSON parsing and error handling.
  • _fetchWithAgent(url, options) — uses Node.js https.request for requests requiring a custom TLS agent (e.g., MTLS flows).
  • package.json: Removed axios from the dependencies list.
  • lib/helper.js: Replaced all axios calls (GET, POST with client credentials, POST with MTLS) with _fetch and _fetchWithAgent. Updated response data access from response.data.* to direct response properties.
  • lib/mtx/server.js: Replaced all axios calls (GET, POST, DELETE) in service manager operations with _fetch and _fetchWithAgent. Updated header access to use headers.get("location") (Fetch API Headers object). Removed the axios import.
  • tests/unit/unitTests.test.js: Removed axios mock and replaced all axios.get/axios.post mock implementations with global.fetch mock chains. Updated the global.fetch default mock to include ok: true for proper response simulation.
  • CHANGELOG.md: Added changelog entry noting the replacement of axios with the built-in fetch API.
  • 🔄 Regenerate and Update Summary
PR Bot Information

Version: 1.22.9

  • LLM: anthropic--claude-4.6-sonnet
  • Summary Prompt: Default Prompt
  • File Content Strategy: Full file content
  • Correlation ID: d2199f26-87b9-414b-a48f-468a1180a244
  • Output Template: Default Template
  • Event Trigger: pull_request.opened

@KoblerS KoblerS requested a review from a team as a code owner June 15, 2026 08:39

@hyperspace-insights hyperspace-insights Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The PR successfully removes the axios dependency and replaces it with the built-in fetch API, but introduces several correctness issues: OAuth credentials are sent as URL query parameters instead of in the POST body (a spec violation that can also leak secrets into access logs), the response body is consumed before the status check (making error body capture unreliable), and _pollUntilDone can silently return undefined on timeout/failure causing a downstream null-dereference. Additionally, _fetch/_fetchWithAgent are copy-pasted into two files rather than shared, creating a maintenance burden.

PR Bot Information

Version: 1.22.9

  • Event Trigger: pull_request.opened
  • File Content Strategy: Full file content
  • Correlation ID: d2199f26-87b9-414b-a48f-468a1180a244
  • LLM: anthropic--claude-4.6-sonnet

Comment thread lib/helper.js
Comment on lines +316 to 324
const params = new URLSearchParams({
grant_type: "client_credentials",
client_id: clientid,
client_secret: clientsecret,
})
const response = await _fetch(`${url}/oauth/token?${params}`, {
method: "POST",
headers,
params: {
grant_type: "client_credentials",
client_id: clientid,
client_secret: clientsecret,
},
})

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Bug: OAuth token sent as query parameter instead of request body

The client credentials (grant_type, client_id, client_secret) are appended to the URL as query string parameters. The OAuth 2.0 spec (RFC 6749) requires these to be sent in the request body with Content-Type: application/x-www-form-urlencoded, not as URL query parameters. Some authorization servers will reject this or log credentials in access logs, creating a security concern.

The old axios implementation also used params (which axios sent as query string for POST), so this is a pre-existing behavioral issue—but it is explicitly worsened here by making it visible. The Content-Type header already declares application/x-www-form-urlencoded, so the body should carry the payload.

Consider sending the credentials in the request body instead:

Suggested change
const params = new URLSearchParams({
grant_type: "client_credentials",
client_id: clientid,
client_secret: clientsecret,
})
const response = await _fetch(`${url}/oauth/token?${params}`, {
method: "POST",
headers,
params: {
grant_type: "client_credentials",
client_id: clientid,
client_secret: clientsecret,
},
})
const body = new URLSearchParams({
grant_type: "client_credentials",
client_id: clientid,
client_secret: clientsecret,
})
const response = await _fetch(`${url}/oauth/token`, {
method: "POST",
headers,
body: body.toString(),
})

Double-check suggestion before committing. Edit this comment for amendments.


Please provide feedback on the review comment by checking the appropriate box:

  • 🌟 Awesome comment, a human might have missed that.
  • ✅ Helpful comment
  • 🤷 Neutral
  • ❌ This comment is not helpful

Comment thread lib/mtx/server.js
Comment on lines +145 to 153
const params = new URLSearchParams({
grant_type: "client_credentials",
client_id: clientid,
client_secret: clientsecret,
})
const { data: tokenData } = await _fetch(`${tokenUrl}?${params}`, {
method: "POST",
headers,
params: {
grant_type: "client_credentials",
client_id: clientid,
client_secret: clientsecret,
},
})

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Bug: OAuth token sent as query parameter instead of request body

Same issue as in lib/helper.js: client_id, client_secret, and grant_type are appended to the URL as query string parameters for a POST request. The Content-Type: application/x-www-form-urlencoded header signals the server to expect these in the request body. Many OAuth providers will reject a POST with credentials only in the query string, and query params appear in server access logs.

Consider sending the credentials in the request body:

Suggested change
const params = new URLSearchParams({
grant_type: "client_credentials",
client_id: clientid,
client_secret: clientsecret,
})
const { data: tokenData } = await _fetch(`${tokenUrl}?${params}`, {
method: "POST",
headers,
params: {
grant_type: "client_credentials",
client_id: clientid,
client_secret: clientsecret,
},
})
const params = new URLSearchParams({
grant_type: "client_credentials",
client_id: clientid,
client_secret: clientsecret,
})
const { data: tokenData } = await _fetch(`${tokenUrl}`, {
method: "POST",
headers,
body: params.toString(),
})

Double-check suggestion before committing. Edit this comment for amendments.


Please provide feedback on the review comment by checking the appropriate box:

  • 🌟 Awesome comment, a human might have missed that.
  • ✅ Helpful comment
  • 🤷 Neutral
  • ❌ This comment is not helpful

Comment thread lib/mtx/server.js
})
const instancePath = headers.get("location").substring(1)
const instanceId = await _pollUntilDone(sm_url, instancePath, token)
return instanceId.data.resource_id

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Bug: _pollUntilDone returns { data, headers } but callers use .data.resource_id and .data.state directly

_fetch in server.js now returns { data, headers }. The _pollUntilDone function passes through the full _fetch result at line 342 (return instanceStatus) and line 306 uses instanceId.data.resource_id. However, at lines 340 and 352 within _pollUntilDone itself, instanceStatus.data.state is checked correctly. At line 306 in _createObjectStoreInstance, instanceId.data.resource_id is accessed on the value returned from _pollUntilDone, which itself returned the raw instanceStatus object from _fetch—so instanceId.data.resource_id is correct.

However, note that _pollUntilDone can return undefined when it times out (falls out of the while loop without isReady becoming true) or when STATE.FAILED is reached. In both those cases, execution continues looping without error or return, and _createObjectStoreInstance will receive undefined from _pollUntilDone, then crash with Cannot read properties of undefined (reading 'data') at line 306.

Should add a break or throw when the FAILED or timeout condition is detected, and guard against a null/undefined return from _pollUntilDone.


Please provide feedback on the review comment by checking the appropriate box:

  • 🌟 Awesome comment, a human might have missed that.
  • ✅ Helpful comment
  • 🤷 Neutral
  • ❌ This comment is not helpful

Comment thread lib/helper.js
Comment on lines +8 to +17
async function _fetch(url, options = {}) {
const res = await fetch(url, options)
const data = await res.json().catch(() => null)
if (!res.ok) {
const err = new Error(`HTTP ${res.status} ${res.statusText}`)
err.response = { status: res.status, data }
throw err
}
return data
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Bug: Duplicate code — _fetch and _fetchWithAgent are defined identically in both lib/helper.js and lib/mtx/server.js

Both files define their own private copies of _fetch and _fetchWithAgent with identical implementations (modulo the return shape of _fetch: helper.js returns data directly, while server.js returns { data, headers }). This duplication will lead to maintenance issues—any bug fix or change must be applied twice.

Consider extracting these helpers into a shared utility module (e.g., lib/http-utils.js) and importing from both files.


Please provide feedback on the review comment by checking the appropriate box:

  • 🌟 Awesome comment, a human might have missed that.
  • ✅ Helpful comment
  • 🤷 Neutral
  • ❌ This comment is not helpful

Comment thread lib/helper.js
Comment on lines +8 to +16
async function _fetch(url, options = {}) {
const res = await fetch(url, options)
const data = await res.json().catch(() => null)
if (!res.ok) {
const err = new Error(`HTTP ${res.status} ${res.statusText}`)
err.response = { status: res.status, data }
throw err
}
return data

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Bug: _fetch reads the response body before checking res.ok, discarding non-JSON error bodies silently

res.json() is called with .catch(() => null) before the !res.ok check. For error responses with a non-JSON body (e.g., plain-text 500 errors, HTML gateway errors), data will be null, which is fine. However, for successful responses with a non-JSON body (e.g., a 204 No Content, or a plain-text 200), calling .json() will throw and silently set data = null—the caller receives null and has no way to distinguish a successful empty response from a JSON parse failure.

More critically: calling res.json() consumes the response body stream. If ever needed for non-JSON content, the body is already gone.

Consider checking res.ok first and only parsing JSON when content is expected:

Suggested change
async function _fetch(url, options = {}) {
const res = await fetch(url, options)
const data = await res.json().catch(() => null)
if (!res.ok) {
const err = new Error(`HTTP ${res.status} ${res.statusText}`)
err.response = { status: res.status, data }
throw err
}
return data
async function _fetch(url, options = {}) {
const res = await fetch(url, options)
if (!res.ok) {
const data = await res.json().catch(() => null)
const err = new Error(`HTTP ${res.status} ${res.statusText}`)
err.response = { status: res.status, data }
throw err
}
const data = await res.json().catch(() => null)
return data
}

Double-check suggestion before committing. Edit this comment for amendments.


Please provide feedback on the review comment by checking the appropriate box:

  • 🌟 Awesome comment, a human might have missed that.
  • ✅ Helpful comment
  • 🤷 Neutral
  • ❌ This comment is not helpful

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.

1 participant