Skip to content

Support for binary and JSON response data (responseType other than 'text') #9

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

Open
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

tchakabam
Copy link

@tchakabam tchakabam commented Oct 10, 2018

Please let me know if this needs any explanation!

Cheers and thanks for the great prior work 👍

lib/index.js Outdated
} else {
this._response = chunk;
}
// binary data usually comes in one chunk (no chunky transfer-encoding)
Copy link
Author

Choose a reason for hiding this comment

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

note to self: this comment is confusing. transfer-encoding is unrelated to the chunks of data delivered by this callback (which is reading from net socket)

Copy link
Owner

@aspyrx aspyrx left a comment

Choose a reason for hiding this comment

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

Thank you very much for the contribution! Most of it looks great. See comments for further details.

Re: the tests failing, I may deprecate support for [email protected] and/or [email protected], since nock<=8.x doesn't support those anymore. As for the latest node/npm, I will look into those, since it's been ages since I last updated this package.

@@ -0,0 +1,9 @@
# http://editorconfig.org
Copy link
Owner

Choose a reason for hiding this comment

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

As much as I like having standardized editor configurations, I'd prefer if this file were not included.

Copy link
Author

Choose a reason for hiding this comment

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

any specific reason?

Copy link
Owner

Choose a reason for hiding this comment

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

If I remember correctly, the eslint configuration already enforces a lot of these upon linting, and having fewer files is nice.

On the other hand, it's not really a big deal, so feel free to leave it in - I believe the package.json is already set up to only include stuff in lib/ upon publish.

Copy link
Author

@tchakabam tchakabam Oct 12, 2018

Choose a reason for hiding this comment

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

yes, eslint is an automated tool to check/fix/ensure these rules.

editorconfig is configuration for your editor, making it easier to observe the rules: https://editorconfig.org/

I agree that too much tooling and config files isn't desirable, but then again, it's just a bunch of template files that you can just copy from one project to another :) but maybe we just need a more integrated toolchain in the first place in javascript hehe?

@@ -413,6 +413,31 @@ function describeXHRProps() {
});

describe('#responseType', function () {

it('supports binary data (arraybuffer responseType)', function (done) {
Copy link
Owner

Choose a reason for hiding this comment

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

Thanks for adding a test!

Copy link
Author

Choose a reason for hiding this comment

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

let's say that at first i was so lost in here, that i wouldn't have been able to implement without it :)

Copy link
Author

Choose a reason for hiding this comment

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

a test for json could be added as well

@tchakabam
Copy link
Author

@aspyrx The tests were running perfectly fine on my machine. Except one which was stuck pending (probably missing call to async done()). The CI failures are probably due to CI env mismatch indeed, but no idea of the details. My local node version is v8.10.0.

get: function getResponseText() {

// @see https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseText#Exceptions
if (this._responseType !== 'text' && this._responseType !== '') {
Copy link
Author

Choose a reason for hiding this comment

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

we could write a private method to check this, since it is done below as well

Copy link
Owner

Choose a reason for hiding this comment

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

Seems like a good idea 👍

// TODO: adjust responseType from content-type header if applicable

// from Node API docs: The encoding argument is optional and only applies when chunk is a string. Defaults to 'utf8'.
if (this._responseType === 'text' || this._responseType === '') {
Copy link
Author

Choose a reason for hiding this comment

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

use private method for checl

if (typeof chunk === 'string') {
this._responseText += chunk;
} else if (typeof chunk === 'object') {
if (!(chunk instanceof Buffer)) {
Copy link
Author

Choose a reason for hiding this comment

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

i am not even sure we need this check, was more of a dev-time tool

Copy link
Owner

Choose a reason for hiding this comment

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

I suppose it's good to have the assertion there, for sanity's sake. Maybe we want to have a catch-all, since there are only 2 possibilities (if I'm reading it correctly)?

} else if (chunk instanceof Buffer) {
  // as before
} else {
  throw new Error('Assertion failed: Response-data should be either a string or Buffer');
}

Copy link
Author

Choose a reason for hiding this comment

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

that's a good one. i am actually always recommending run-time assertions that slam into devs face when they break stuff, or even at runtime, instead of hiding away unexpected behavior :)


// from Node API docs: The encoding argument is optional and only applies when chunk is a string. Defaults to 'utf8'.
if (this._responseType === 'text' || this._responseType === '') {
resp.setEncoding('utf8');
Copy link
Author

Choose a reason for hiding this comment

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

we may need to set this for json case as well to actually get a string in on-data.

Copy link
Author

Choose a reason for hiding this comment

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

or decode the buffer ourself but that seems more elegant

Copy link
Owner

Choose a reason for hiding this comment

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

Agreed - the encoding should definitely by UTF-8 for JSON.

@tchakabam
Copy link
Author

tchakabam commented Oct 15, 2018

@aspyrx We also need to be able to follow redirects. One possibility without having to change too much here would be using this drop-in replacement for http/https modules: https://www.npmjs.com/package/follow-redirects

But in a general way it seems that re-implementing HTTP-client-functionnality properly here with Node at the high-level API that XHR requires it, using a solution like provided by https://github.com/request/request would be better? The built-in Node stuff comes pretty much without batteries it seems, and many problems one would typically need to solve are taken care off here ^

It requires a few subtle changes but can be more or less used the same way. However that module lacks abort method.

@tchakabam
Copy link
Author

see tchakabam@4785a4b

@aspyrx
Copy link
Owner

aspyrx commented Oct 16, 2018

@aspyrx We also need to be able to follow redirects. One possibility without having to change too much here would be using this drop-in replacement for http/https modules: https://www.npmjs.com/package/follow-redirects

But in a general way it seems that re-implementing HTTP-client-functionnality properly here with Node at the high-level API that XHR requires it, using a solution like provided by https://github.com/request/request would be better? The built-in Node stuff comes pretty much without batteries it seems, and many problems one would typically need to solve are taken care off here ^

It requires a few subtle changes but can be more or less used the same way. However that module lacks abort method.

I agree that redirects need to be handled.

I'd prefer to use a drop-in replacement if possible - follow-redirects seems like a good solution. However, this discussion should probably happen in a new PR/issue.

@tchakabam
Copy link
Author

However, this discussion should probably happen in a new PR/issue.

Totally agree.

@tchakabam
Copy link
Author

I am also more critical the more I look at https://github.com/request/request . It takes care of many things, but has a very large baggage of dependencies it seems + the API isn't clear in all parts and it seems there is a bug related to aborting requests - which I consider being a critical issue and which would be a regression with the existing functionnality here.

The reason I looked at it was that I had a problem facing that was maybe related to redirects, but also encoding of data, but it turns out it may not have been caused by this lib, nor actually solved by lib request.

If we can make redirects work, and I can test and validate all my cases here, we should rather put efforts in building it properly but lean&mean right on top of nodes http/s.

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.

2 participants