Skip to content
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

doc: better example for http.get #9065

Closed
wants to merge 4 commits into from
Closed

doc: better example for http.get #9065

wants to merge 4 commits into from

Conversation

marzelin
Copy link
Contributor

Checklist
  • documentation is changed or added
  • commit message follows commit guidelines
Affected core subsystem(s)

doc

Description of change

I wanted to get some JSON data using Node.js, so I searched the documentation and found http.get method that looked like a proper tool for that. But the example was confusing because of res.resume() method. My first thought was that it needs to be at the end of every http.get callback after the code for consuming the response body. But after some research I found (in the http.ClientRequest section) that it should be there only if the body won't be consumed in any other manner. But I still didn't know what the resume() method does exactly. So I search further and found that res is an instance of IncomingMessage which implements readable stream. And that's where I found description of readable.resume().

I've learnt a lot from this experience, but what I really wanted was get things done and fetch JSON.

I propose replacing current example with the one that presents the most common use of that method: getting data. Also, I added information about the type of object being passed to the callback and necessity of consuming response data in it.

I wanted to get some JSON data using Node.js, so I searched the documentation and found `http.get` method that looked like a proper tool for that. But the example was confusing because of `res.resume()` method. My first thought was that it needs to be at the end of  every http.get callback after the code for consuming the response body. But after some research I found (in the `http.ClientRequest` section) that it should be there only if the body won't be consumed in any other manner.  But I still didn't know what the `resume()` method does exactly. So I search further and found that `res` is an instance of `IncomingMessage` which implements readable stream. And that's where I found description of `readable.resume()`.

I've learnt a lot from this experience, but what I really wanted was get things done and fetch JSON.

I propose replacing current example with the one that presents the most common use of that method: getting data. Also, I added information about the type of object being passed to the callback and necessity of consuming response data in it.
@nodejs-github-bot nodejs-github-bot added doc Issues and PRs related to the documentations. http Issues or PRs related to the http subsystem. labels Oct 12, 2016
console.log(`STATUS: ${res.statusCode}`);
res.setEncoding('utf8');
let aggregatedData = '';
res.on('data', (chunk) => aggregatedData += chunk);
Copy link
Member

Choose a reason for hiding this comment

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

Concatenating strings isn't a good method of getting the response body.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@ChALkeR what's wrong with concatenating strings, and how it should be done then?

Copy link
Contributor

@mscdex mscdex Oct 12, 2016

Choose a reason for hiding this comment

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

Concatenating strings is fine if the response is text, but for binary it wouldn't work. Using binary from the get-go would work for both cases (e.g. pushing Buffers to an array, keeping a total byte count, and calling Buffer.concat() at the end) but still you'd have to know what to do with the end result (either converting to string or whatever), so it's kind of tricky for a generic example.

If we want to make it more concrete, we could turn it into a JSON fetching example. That way we could show checking the response code for 200, checking that the Content-Type starts with 'application/json', and then concatenating and parsing the response?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

JSON fetching example sound good.

As proposed in the comments, I've changed the example to present how `http.get` can be used to fetch JSON data. It also shows the use of `res.resume()` stream method.
@marzelin
Copy link
Contributor Author

As proposed in the comments, I've changed the example to present how http.get can be used to fetch JSON data. It also shows the use of res.resume() stream method.

res.resume();
http.get('http://jsonplaceholder.typicode.com/posts/1', (res) => {
const statusCode = res.statusCode;
const contentType = res.headers && res.headers['content-type'];
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this can just be const contentType = res.headers['content-type'];.

Copy link
Contributor

Choose a reason for hiding this comment

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

Also, minor nit: 2 space indent instead of 4

const contentType = res.headers && res.headers['content-type'];

let error;
if (statusCode !== 200)
Copy link
Contributor

Choose a reason for hiding this comment

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

These if/else-ifs might look better with braces since they span multiple lines.

res.on('data', (chunk) => rawData += chunk);
res.on('end', () => {
const parsedData = JSON.parse(rawData);
console.log('Title: ' + parsedData.title);
Copy link
Contributor

Choose a reason for hiding this comment

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

Perhaps just log the parsed value? Also, might surround JSON.parse() with a try-catch in case of parse errors.


Example:
`callback` takes one argument which is an instance of [`http.IncomingMessage`][]
Copy link
Member

Choose a reason for hiding this comment

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

Please make this a proper sentence, e.g.:

The `callback` is invoked with a single argument that is an instance of
[`http.IncomingMessage`][]

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Great sentence. Thanks.

`Status Code: ${statusCode}`);
else if (!/^application\/json/.test(contentType))
error = new Error(`Invalid content-type.\n` +
`Expected application/json but received ${contentType}`);
Copy link
Member

Choose a reason for hiding this comment

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

alignment...

        error = new Error(`Invalid content-type.\n` +
                          `Expected application/json but received ${contentType}`);

I've fixed spacing, corrected the callback sentence and added `try...catch` block around JSON.parse as suggested. This example is becoming more about catching errors than fetching data.
@marzelin
Copy link
Contributor Author

I've fixed spacing, corrected the callback sentence and added try...catch block around JSON.parse as suggested.

Copy link
Member

@jasnell jasnell left a comment

Choose a reason for hiding this comment

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

LGTM

console.log(`Got response: ${res.statusCode}`);
// consume response body
res.resume();
http.get('http://jsonplaceholder.typicode.com/posts/1', (res) => {
Copy link
Contributor

@mscdex mscdex Oct 14, 2016

Choose a reason for hiding this comment

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

I wonder if we should just use a fake URL, like 'http://example.org/posts/1.json' or something? That way we have more consistency/reliability (e.g. example.org is always a reserved domain name and will never go away). The example.org url won't actually work of course, but I'm not sure that's important.

Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fetching data from nodejs.org would be great but it has to be through http. I'd prefer having a working example. jsonplaceholder.typicode.com is quite reliable and commonly used for testing and prototyping, so I'd rather keep it.

Copy link
Member

Choose a reason for hiding this comment

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

Note that plain http also works for nodejs.org: http://nodejs.org/dist/index.json.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It does work. Great 👍

Copy link
Contributor

Choose a reason for hiding this comment

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

Let's hope that nodejs.org never forces https via redirect or similar ;-)

Copy link
Member

@lpinca lpinca left a comment

Choose a reason for hiding this comment

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

LGTM

@jasnell jasnell self-assigned this Oct 17, 2016
jasnell pushed a commit that referenced this pull request Oct 17, 2016
PR-URL: #9065
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
@jasnell
Copy link
Member

jasnell commented Oct 17, 2016

Landed in cb87748. Thank you!

@jasnell jasnell closed this Oct 17, 2016
jasnell pushed a commit that referenced this pull request Oct 17, 2016
PR-URL: #9065
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
MylesBorins pushed a commit that referenced this pull request Nov 11, 2016
PR-URL: #9065
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
@MylesBorins MylesBorins mentioned this pull request Nov 22, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
doc Issues and PRs related to the documentations. http Issues or PRs related to the http subsystem.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants