You made a few flaws.
You must rewrite the extension to pass the URL and pass the callback. Any function that does something asynchronous usually has a signature (data, callback) in node. This basically lets you say that I want this function to do something, and then let me know when it will be done.
function expand(urlToParse, callback) {
Here it is expected that the callback will have a signature (err, data) , which has almost all the callbacks in the node. We also added error handling, which is mandatory.
Now we will change onRequest to actually expose normally
function onRequest(request, response) { // parse the incoming url. true flag unpacks the query string var parsedUrl = url.parse(request.url, true), // extract the querystring url. // http://localhost:8888/?url=http://t.co/wbDrgquZ urlToExpand = parsedUrl.query.url; // call expand with the url and a callback expand(urlToExpand, writeResponse); function writeResponse(error, newUrl) { // handle the error case properly if (error) { response.writeHead(500, { 'Content-Type': 'text/plain'}); // early return to avoid an else block return response.end(error.message); } response.writeHead(200, { 'Content-Type': 'text/plain'}); // write the new url to the response response.end(newUrl); } }
Here we added the error handling logic, and also unpacked the actual url for the extension from the query string.
Usually the doSomething<data, callback<err, result>> pattern works very well in node.js.
This is the same as let result = doSomething<data> mayThrow err , which you expect in your usual locking languages ββexcept asynchronous.
Note that an alternative way to pass a ServerResponse object to a function is not satisfied, thereby creating an unnecessary hard link between the extension function and the server response.
The extension function should only expand the URL and return the expanded URL; it does not have a business doing IO itself.
Full code