-
Notifications
You must be signed in to change notification settings - Fork 60
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: handle application/x-www-form-urlencoded/Buffer #374
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -40,6 +40,19 @@ function hasFetch() { | |
return hasWindow() && !!window.fetch; | ||
} | ||
|
||
function hasBuffer() { | ||
return typeof Buffer !== 'undefined'; | ||
} | ||
|
||
function hasHeader(options: GaxiosOptions, headerCheck: string) { | ||
headerCheck = headerCheck.toLowerCase(); | ||
for (let header of Object.keys(options?.headers || {})) { | ||
header = header.toLowerCase(); | ||
if (header === headerCheck) return true; | ||
} | ||
return false; | ||
} | ||
|
||
let HttpsProxyAgent: any; | ||
|
||
function loadProxy() { | ||
|
@@ -219,21 +232,25 @@ export class Gaxios { | |
if (opts.data) { | ||
if (isStream.readable(opts.data)) { | ||
opts.body = opts.data; | ||
} else if (hasBuffer() && Buffer.isBuffer(opts.data)) { | ||
// Do not attempt to JSON.stringify() a Buffer: | ||
opts.body = opts.data; | ||
if (!hasHeader(opts, 'Content-Type')) { | ||
opts.headers['Content-Type'] = 'application/json'; | ||
JustinBeckwith marked this conversation as resolved.
Show resolved
Hide resolved
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this also should be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This doesn't need to be, because we already know it doesn't have the header There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. oh, for clarification |
||
} | ||
} else if (typeof opts.data === 'object') { | ||
opts.body = JSON.stringify(opts.data); | ||
// Allow the user to specifiy their own content type, | ||
// such as application/json-patch+json; for historical reasons this | ||
// content type must currently be a json type, as we are relying on | ||
// application/x-www-form-urlencoded (which is incompatible with | ||
// upstream GCP APIs) being rewritten to application/json. | ||
// | ||
// TODO: refactor upstream dependencies to stop relying on this | ||
// side-effect. | ||
// If www-form-urlencoded content type has been set, but data is | ||
// provided as an object, serialize the content using querystring: | ||
if ( | ||
!opts.headers['Content-Type'] || | ||
!opts.headers['Content-Type'].includes('json') | ||
opts.headers['Content-Type'] && | ||
bcoe marked this conversation as resolved.
Show resolved
Hide resolved
|
||
opts.headers['Content-Type'] === 'application/x-www-form-urlencoded' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If someone has explicitly asked for
bcoe marked this conversation as resolved.
Show resolved
Hide resolved
|
||
) { | ||
opts.headers['Content-Type'] = 'application/json'; | ||
opts.body = opts.paramsSerializer(opts.data); | ||
bcoe marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} else { | ||
if (!hasHeader(opts, 'Content-Type')) { | ||
opts.headers['Content-Type'] = 'application/json'; | ||
} | ||
opts.body = JSON.stringify(opts.data); | ||
} | ||
} else { | ||
opts.body = opts.data; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -449,11 +449,11 @@ describe('🎏 data handling', () => { | |
assert.deepStrictEqual(res.data, {}); | ||
}); | ||
|
||
it('replaces application/x-www-form-urlencoded with application/json', async () => { | ||
it('application/x-www-form-urlencoded with object data should stringify with qs', async () => { | ||
bcoe marked this conversation as resolved.
Show resolved
Hide resolved
|
||
const body = {hello: '🌎'}; | ||
const scope = nock(url) | ||
.matchHeader('Content-Type', 'application/json') | ||
.post('/', JSON.stringify(body)) | ||
.matchHeader('Content-Type', 'application/x-www-form-urlencoded') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This test was for the old behavior where |
||
.post('/', qs.stringify(body)) | ||
.reply(200, {}); | ||
const res = await request({ | ||
url, | ||
|
@@ -530,4 +530,37 @@ describe('🍂 defaults & instances', () => { | |
scope.done(); | ||
assert.deepStrictEqual(res.data, body); | ||
}); | ||
|
||
it('should allow buffer to be posted', async () => { | ||
const pkg = fs.readFileSync('./package.json'); | ||
const pkgJson = JSON.parse(pkg.toString('utf8')); | ||
const scope = nock(url) | ||
.matchHeader('content-type', 'application/dicom') | ||
.post('/', pkgJson) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. once in transport, the Buffer is properly handled by There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sick |
||
.reply(200, {}); | ||
const res = await request({ | ||
url, | ||
method: 'POST', | ||
data: pkg, | ||
headers: {'content-type': 'application/dicom'}, | ||
}); | ||
scope.done(); | ||
assert.deepStrictEqual(res.data, {}); | ||
}); | ||
|
||
it('should set content-type to application/json by default, for buffer', async () => { | ||
const pkg = fs.readFileSync('./package.json'); | ||
const pkgJson = JSON.parse(pkg.toString('utf8')); | ||
const scope = nock(url) | ||
.matchHeader('content-type', 'application/json') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Default to |
||
.post('/', pkgJson) | ||
.reply(200, {}); | ||
const res = await request({ | ||
url, | ||
method: 'POST', | ||
data: pkg, | ||
}); | ||
scope.done(); | ||
assert.deepStrictEqual(res.data, {}); | ||
}); | ||
}); |
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.
Support
content-type
, andContent-Type
, andcontent-Type
, when deciding whether to reset header.