-
Notifications
You must be signed in to change notification settings - Fork 528
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: set content-length header #1381
Conversation
had to downgrade it because >= v5 is ESM and using dynamic imports causes webpack to create a new chunk just for this pkg.
// only retry on CI | ||
if (process.env.CI) { | ||
jest.retryTimes(3, {logErrorsBeforeRetry: true}) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
retries are annoying when working locally, should always be enabled on CI.
@@ -207,6 +209,7 @@ | |||
"dependencies": { | |||
"@babel/runtime": "^7.23.1", | |||
"@babel/runtime-corejs3": "^7.23.1", | |||
"@sindresorhus/is": "^4", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there's already a v6:
https://github.com/sindresorhus/is/releases
but had to use v4 because it's the latest CJS release.
When using ESM modules via await import
webpack creates a new chunk just for it instead of keeping it in the main bundle:
https://webpack.js.org/guides/code-splitting/#dynamic-imports
I spent a few hours trying to find some workarounds but couldn't get it to inline this into the main bundle so keeping it at v4 until I find a solution for this (will need to for node-fetch v3 (ESM): #1356)
`missing 'content-length' header, setting it to: ${bodySize}`, | ||
); | ||
headers['content-length'] = String(bodySize); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
`missing 'content-length' header, setting it to: ${bodySize}`, | ||
); | ||
request.headers['content-length'] = String(bodySize); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same as this but for SOAP requests:
https://github.com/jsforce/jsforce/pull/1381/files#r1412264591
one difference here is that this only checks if method is POST
while GET is possible, I haven't seen any examples of using non-POST in API docs. We can revert it later if it's not true.
type FormData = { | ||
getBoundary: () => string; | ||
getLength: (callback: (error: Error | null, length: number) => void) => void; | ||
} & Readable; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
): number | undefined { | ||
function isFormData(body: unknown): body is FormData { | ||
return is.nodeStream(body) && is.function_((body as FormData).getBoundary); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this looks specifically for this FormData
, not the web native or node native versions.
we use FormData
in jsforce.
} | ||
|
||
return undefined; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the only case not handled here is readable streams:
Line 17 in 5369d1d
| NodeJS.ReadableStream |
got stopped handling this in v12 too, see:
sindresorhus/got#1486
sindresorhus/got#1510
src/http-api.ts
Outdated
// remove the `content-length` header after token refresh | ||
// | ||
// SOAP requests include the access token their the body, | ||
// if the first req had an invalid token and jsforce successfully | ||
// refreshed it we need to remove the `content-length` header | ||
// so that it get's re-calculated again with the new body. | ||
// | ||
// REST request aren't affected by this because the access token | ||
// is sent via HTTP headers | ||
// | ||
// | ||
// `_message` is only present in SOAP requests |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
style nit: I prefer /**/
style for more than like 2 lines of comments
src/http-api.ts
Outdated
Object.hasOwn(request, '_message') && | ||
request.headers && | ||
request.headers['content-length'] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
'_message' in request && request.headers?.['content-length']
src/http-api.ts
Outdated
!cannotHaveBody && | ||
!!request.body && | ||
!headers['transfer-encoding'] && | ||
!headers['content-length'] && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if 'content-length' is set to 0, does this still do what you want?
src/soap.ts
Outdated
request.method === 'POST' && | ||
request.headers && | ||
!request.headers['transfer-encoding'] && | ||
!request.headers['content-length'] && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same question here about 0
import { HttpBody } from '../types'; | ||
import is from '@sindresorhus/is'; | ||
|
||
export function getBodySize( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 for using an exported function. It should be simple to write some true UT, which jsforce lacks, for this.
@@ -233,6 +234,21 @@ export class SOAP<S extends Schema> extends HttpApi<S> { | |||
/** @override */ | |||
beforeSend(request: HttpRequest & { _message: object }) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not a fan of this design (pass an object for mutation). I know you didn't start it.
But if http-api isn't exported and is only used via the 2 classes that extend it (soap and bulk?) maybe it's possible to fix it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or maybe that's too big and it's easier to stay in line with what jsforce is already doing?
QA: created a record via
Seems fine |
feat: automatically set
content-length
header on REST/SOAP requests.We've been getting a few reports that some internal envs started to enforce this header on requests, adding support in jsforce as a safety measure.
Tests
while working on this I found the HTTP module doesn't any UT, there's some coverage for session refresh in different e2e tests but we today we don't have an easy way to test this behavior, I'll add some tests for this when working on
[W-14580746: [jsforce]: increase HTTP module test coverage]
(https://gus.lightning.force.com/lightning/r/ADM_Work__c/a07EE00001fXgwbYAC/view)
QA
not really an easy way to QA this without getting one of those internal envs, but you can try running tests with this env var:
JSFORCE_LOG_LEVEL=DEBUG
to get the body size added in each request (I tried adding to mock the logger to grab the value and compare it in e2e tests but couldn't get it to work on browser/tests (you can't use jest specific stuff).@W-14177773@