5 ways to make an http request

The need for HTTP requests

Evolution of HTTP requests in browsers

Netscape communicator loading screen

GPF-JS

How to test HTTP request

  • cache: introduced with version 0.1.7, it is leveraged by the command line used to test browsers when Selenium is not available. It implements a data storing service like Redis.
  • fs: a file access service used to read, create and delete files within the project storage. For instance, it is used by the sources tile to check if a source has a corresponding test file.
  • grunt: a wrapper used to execute and format the log of grunt tasks.
echo GET
echo GET 500
echo POST

One API to rule them all

Input

  • The Uniform Resource Locator which determines the web address you want to send the request to. There are several ways to specify this location: NodeJS offers an URL class which exposes the different parts of it (host, port …). However, the simplest representation remains the one everybody is used to: the string you can read inside the browser location bar.
  • The request method (also known as verb) which specifies the kind of action you want to execute.
  • An optional list of header fields meant to configure the request processing (such as specifying the expected answer type…). The simplest way to provide this list is to use a key/value dictionary, meaning an object.
  • The request body, mostly used for POST and PUT actions, which contains that data to upload to the server. Even if the library supports the concept of streams, most of the expected use cases imply sending an envelope that is synchronously built (text, JSON, XML…). Also, JavaScript (in general) is not good at handling binary data, hence a simple string is expected as a request body.

Output

  • A status code that provides feedback about how the server processed the request. Typically, 200 means everything went well. On the contrary, 4xx messages signal an error and 500 is a critical server error.
  • A list of response headers. For instance, this is how cookies are transmitted by the server to the client (and, actually, they are also sent back by the client to the server through headers).
  • The response body: depending on what has been requested, it will contain the server answer. This response could be deserialized using a readable stream. But, for the same reasons, a simple string containing the whole response text will be returned.

Waiting for the completion

Shortcuts

gpf.http.get(baseUrl)
.then(function (response) {
process(response.responseText);
}, handleError);

Handling different environments

  • Inside the request API, create an if / else condition that checks every possibility
gpf.http.request = function (/*...*/) {
if (_GPF_HOST.NODEJS === _gpfHost) {
// call NodeJS implementation
} else if (_GPF_HOST.BROWSER === _gpfHost) {
// call Browser implementation
} else /* ... */
};
  • Have a global variable receiving the proper implementation, using an if condition inside each implementation file
// Inside src/host/nodejs.js
if (_GPF_HOST.NODEJS === _gpfHost) {
_gpfHttpRequestImpl = function (/*...*/) {
/* ... NodeJS implementation ... */
};
}
// Inside src/http.js
gpf.http.request = function (/*...*/) {
_gpfHttpRequestImpl(/*...*/);
};
  • Create a dictionary indexing all implementations per host and then fetch the proper one on call
// Inside src/host/nodejs.js
_gpfHttpRequestImplByHost[_GPF_HOST.NODEJS] = function () {
/* ... NodeJS implementation ... */
};
// Inside src/http.js
gpf.http.request = function (/*...*/) {
_gpfHttpRequestImplByHost[_gpfHost](/*...*/);
};
  • if / else conditions generate cyclomatic complexity. In general, the less if the better. In this case, they are useless because used to compare a variable (here the current host) with a list of predefined values (the list of host names). A dictionary is more efficient.
  • It is simpler to manipulate a dictionary to dynamically declare a new host or even update an existing implementation. Indeed, we could imagine a plugin mechanism that would change the way requests are working by replacing the default handler.

Browsers

Test preview

NodeJS

Test preview

WScript

  • WScript.exe which is showing outputs in dialog boxes
  • cscript.exe which is the command line counter part
Test preview

Rhino

Test preview

PhantomJS

  • On one hand, it browses a website and simulates what would happen in a browser
  • On the other hand, it is a command line executing some JavaScript code
  • mocha is used to automate browser testing with PhantomJS
  • a dedicated command line runs the test suite without any web page
Test preview

Conclusion

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store