Building Enterprise JavaScript Applications
上QQ阅读APP看书,第一时间看更新

Refactoring our application

Now that our tests have been refactored, we can now turn our focus to refactoring our application code. The great thing about having existing E2E tests is that if, during the refactoring, we break something, the tests will fail and we'd be able to fix them quickly.

As we did before, let's list out all the issues with our current code:

  • It is not very readable.
  • We have to work with quite low-level constructs, such as streams and buffers.
  • We have not taken into consideration performance and security implications. For example, we are not handling situations where the payload is extremely large (or even infinite). This is a dangerous situation to avoid if we want to ensure high-availability of our service.

For the last issue, we can add an additional if block inside the req.on('data') block to check whether the payload is getting too large; if it is, we can return a 413 Payload Too Large error. In the following example, we are using a limit of 1e6, which is one million, or 1,000,000, bytes:

const PAYLOAD_LIMIT = 1e6;
req.on('data', function (data) {
payloadData.push(data);
const bodyString = Buffer.concat(payloadData).toString();
if (bodyString.length > PAYLOAD_LIMIT) {
res.writeHead(413, { 'Content-Type': 'text/plain' });
res.end();
res.connection.destroy();
}
});

However, this makes the code even harder to understand. At the moment, there's not too much functionality behind our API, yet our code is already quite long and complex; imagine how much more obscure it will get when we have to implement the logic to parse URL paths, query parameters, and so on.

As you may expect, these problems have already been solved and optimized by frameworks. So, let's take a look at some libraries we can use and then pick the one that best fits our use case.