You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
chore: DH-24027: Addressing some npm package gaps identified with CLI work - #2803
This PR addresses some gaps identified during CLI work that allow less custom code in downstream consumers
@deephaven/jsapi-nodejs: features the CLI needed, so it can drop its own download
code
Restrict where code is loaded from: isTrustedUrl is checked on the first URL and
on every redirect. The CLI uses this to allow only HTTPS, or plain HTTP to a local
server.
Follow redirects: with a limit, as fetch does. Before, a redirect response's body
was saved as the module.
Fail clearly on HTTP errors and timeouts: they reject with HttpError /
DownloadTimeoutError instead of saving an error page as the module, or rejecting
with undefined.
Configurable timeout: for large downloads like the ~5 MB irisapi, where the fixed
5s was too short.
Cancellation: an AbortSignal stops an in-flight download or a pending retry.
Download options through the loaders: loadModules / loadDhModules now pass trust
checks, timeout, cancellation and a custom logger through to each download.
Before, they always used the defaults and logged to console.
@deephaven/jsapi-utils: auth handler helpers that work in Node
Auth handler constants and fetchAuthHandlers(client): usable from Node, so the CLI
no longer needs its own copies. Before, they lived in React/app packages.
AuthHandlers parsing matches the server: accepts commas and/or spaces, so handlers
listed as a, b are no longer misread.
❌ Patch coverage is 91.07143% with 10 lines in your changes missing coverage. Please review.
✅ Project coverage is 53.89%. Comparing base (fe173e9) to head (a771a71). ⚠️ Report is 10 commits behind head on main.
The server sends the raw AuthHandlers property and accepts commas or
spaces as separators, so space-separated handlers were returned as a
single entry.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (#DH-24027)
Checks the scheduled retry delay and that abort clears the pending retry
timer, rather than relying on wall-clock bounds.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (#DH-24027)
- Reject instead of throwing uncaught when isTrustedUrl or the request
setup throws during a redirect or retry
- Treat any HTTP error for dh-internal.js as missing, not just 404
- Log the original url when retrying, since that is what is retried
- Skip errorTransform and download transforms once aborted
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (#DH-24027)
Other statuses, such as a proxy 5xx, indicate a real failure rather than
the removed file, so they are rethrown.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (#DH-24027)
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
Discarded responses can leave sockets open and keep the CLI running indefinitely, while response-stream network errors reject downloads without using remaining retries.
A request superseded by a redirect could fail the active download when
its discarded body stalled, and a request whose download had settled
never closed its socket. Timeouts now always close their own request,
and only the current request can fail or retry the download.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (#DH-24027)
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
Package-root imports fail on supported Node 16 runtimes because a transitive dependency extends the unavailable global CustomEvent, preventing the helpers from running.
The reason will be displayed to describe this comment to others. Learn more.
You might still be able to use fetch if you explicitly set the agent from undici. But not sure and I don't know if it buys us anything else that the node http methods don't have
The reason will be displayed to describe this comment to others. Learn more.
Claude was being "helpful" by adding that comment, but the historical reason that I used node:http was that I copy / modified the logic from existing code. This was also before undici fetch was a thing on my radar. Possible we could get fetch to work, but I'd consider it out of scope and trying to avoid changing things that are already working in this PR
The reason will be displayed to describe this comment to others. Learn more.
So fetch should be able to follow redirects on its own. Could be a benefit of switching to it if the "VSCode injects agent info" or w/e it was is feasible w/ fetch.
I don't think the isTrustedUrl would work for following the redirects though if it's meant to be rechecked. Was there a specific ask or purpose for that check?
The reason will be displayed to describe this comment to others. Learn more.
The CLI has specific rules for which URLs it supports so it had to re-implement a lot of this code. The isTrustedUrl was the agent request to keep logic upstream while allowing consumers to customize which redirects they support.
The reason will be displayed to describe this comment to others. Learn more.
I don't know if the 404 handling specifically gives any additional benefit. Could just simplify to the one status code message without the special 404. The code is Not Found already
The reason will be displayed to describe this comment to others. Learn more.
After a redirect we call res.resume() to discard the old response's body, so its socket stays open until that body is fully read. If the body stalls, that request can time out after we've already started the next request. The guard closes that old request without failing the current download.
The reason will be displayed to describe this comment to others. Learn more.
You're right for the redirect case: once a response has arrived, Node reports socket failures on the response, not as 'error' on the request, so a redirected request won't reach this handler. The case it guards is destroy() on a request that hasn't had a response yet: onAbort rejects and then destroys (line 122), and the timeout handler fails and then destroys (line 254). Both fire 'error' after the download has finished, and without the settled check that would schedule a retry. Added tests for both and updated the if check and comment on this block
The reason will be displayed to describe this comment to others. Learn more.
Just curious why this is exported. I assume we'd want the public API to just be fetchAuthHandlers and there's not a reason to use this. Just for testing? Not a big deal
The reason will be displayed to describe this comment to others. Learn more.
It was previously exported from PluginUtils. It's now re-exported to avoid api change. I updated the re-export with @deprecated which I had previously forgotten.
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
Synchronous cancellation by a custom retry logger can still schedule another request and keep the process alive through the retry delay, requiring a post-logger settled check and regression test.
No open issues 🎉
1 previously missed issue
In code that hasn't changed since last review
Prevent retry scheduling after logger-triggered cancellation
packages/jsapi-nodejs/src/serverUtils.ts:264
If a custom logger synchronously calls controller.abort() while logging a retry, this code still schedules another request after cancellation and can keep the process alive for the retry delay. Recheck settled after the logger call before scheduling the timer, and add a test for synchronous logger-triggered cancellation.
The reason will be displayed to describe this comment to others. Learn more.
🟢 Approval recommended
No active review issues remain for the shared download and authentication utility changes.
No open issues 🎉
Review effort: Balanced
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR addresses some gaps identified during CLI work that allow less custom code in downstream consumers
@deephaven/jsapi-nodejs: features the CLI needed, so it can drop its own download
code
on every redirect. The CLI uses this to allow only HTTPS, or plain HTTP to a local
server.
was saved as the module.
DownloadTimeoutError instead of saving an error page as the module, or rejecting
with undefined.
5s was too short.
checks, timeout, cancellation and a custom logger through to each download.
Before, they always used the defaults and logged to console.
@deephaven/jsapi-utils: auth handler helpers that work in Node
no longer needs its own copies. Before, they lived in React/app packages.
listed as a, b are no longer misread.