While working on a recent class project that involved MongoDB, Node and an external API, I tried creating HTTP request to an external API using just the built-in modules. I was thinking that this wouldn’t be too hard having done it before in Rails. As it turns out, I was going to have a bit of a harder time. I wasn’t getting my expected output: plain text. So, what was the problem?
First Problem
Instead of returning strings, the modules were returning streams. I’ll walk you through my thought process and, hopefully, you get something out of it.
My first instinct was to look for an HTTP module of some sort. I was thinking that this module would, hopefully, have some method implemented where I could create HTTP requests, not necessarily receive them. This didn’t present any problems because I was already using the HTTP module to create my server application. What I needed was to see the documentation for the module. I found it here.
The documentation told me that I needed an options
object to be passed as a parameter to the http.get()
function.
|
|
After doing so, I invoked the http.get()
function. In the callback function, I tried printing out the response to the console.
|
|
This got gave me an error saying that the string “https” wasn’t a supported value for the protocol key. Digging a little deeper, I found that Node had an HTTPS
module available. Using this, instead of the HTTP
module, I came out with the following parameters:
|
|
The output, this time, surprised me. It was a buffer with a bunch of HEX codes. It was in the format: <Buffer [hex code here] >
. Upon seeing this output, I had to go back to the Node v6.x Documentation and check the type of the returned value. As it turns out, the https.get()
function was returning a WritableStream
through the clientRequest
class. (This is also the case with the http.get()
function). Looking at the sample code again, I noticed that it uses a toString()
when writing out to console on the data event.
My code now looks like this:
Side Note: In the HTTPS module documentation, they used toString()
so that you could access the data. Meanwhile, in the HTTP module, their data
event handler used process.stdOut.write()
. These two methods seem to be the way to access the data output.
Another Problem
Now that I had my expected type, I went on to continue building the app logic. But, once I tried parsing the string to JSON, the string seemed to not hold all of the data. I was only returning one chunk of the data. If you haven’t worked with streams before, you’d definitely be surprised by this.
I was thinking that since I was being sent a buffer, maybe I wasn’t getting everything. Playing around with the code, I was able to come up with this:
What I am doing is appending the data to an accumulator. When Node emits the end
event, I will do what I want with the data, ie. returning from a Promise.
In doing this mental exercise of using the built-in modules of Node, I learned two things. First, the HTTP and HTTPS modules return a Stream. Second, one has to make sure that they have retrieved everything before parsing the string.
If that post was too long, here are my takeaways:
- There is an HTTPS module bundled with Node.
https.get()
andhttp.get()
both return a class using the Writable Stream interface.- If you know that you are only supposed to have a very short response body for your GET call, you can use
toString()
orprocess.stdOut.write()
to get to the data. - For longer responses, you might want to use the data event.