-
Notifications
You must be signed in to change notification settings - Fork 30k
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
Conversation
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.
console.log(`STATUS: ${res.statusCode}`); | ||
res.setEncoding('utf8'); | ||
let aggregatedData = ''; | ||
res.on('data', (chunk) => aggregatedData += chunk); |
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.
Concatenating strings isn't a good method of getting the response body.
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.
@ChALkeR what's wrong with concatenating strings, and how it should be done then?
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.
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?
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.
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.
As proposed in the comments, I've changed the example to present how |
res.resume(); | ||
http.get('http://jsonplaceholder.typicode.com/posts/1', (res) => { | ||
const statusCode = res.statusCode; | ||
const contentType = res.headers && res.headers['content-type']; |
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 think this can just be const contentType = res.headers['content-type'];
.
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.
Also, minor nit: 2 space indent instead of 4
const contentType = res.headers && res.headers['content-type']; | ||
|
||
let error; | ||
if (statusCode !== 200) |
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.
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); |
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.
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`][] |
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.
Please make this a proper sentence, e.g.:
The `callback` is invoked with a single argument that is an instance of
[`http.IncomingMessage`][]
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.
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}`); |
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.
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.
I've fixed spacing, corrected the callback sentence and added |
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.
LGTM
console.log(`Got response: ${res.statusCode}`); | ||
// consume response body | ||
res.resume(); | ||
http.get('http://jsonplaceholder.typicode.com/posts/1', (res) => { |
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 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.
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.
Could point to https://nodejs.org/dist/index.json
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.
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.
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.
Note that plain http also works for nodejs.org: http://nodejs.org/dist/index.json.
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.
It does work. Great 👍
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.
Let's hope that nodejs.org never forces https via redirect or similar ;-)
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.
LGTM
PR-URL: #9065 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Landed in cb87748. Thank you! |
PR-URL: #9065 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
PR-URL: #9065 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Checklist
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 ofres.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 thehttp.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 theresume()
method does exactly. So I search further and found thatres
is an instance ofIncomingMessage
which implements readable stream. And that's where I found description ofreadable.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.