Search code examples
javascriptnode.jshttpprototypemiddleware

Addition of new methods to node.js http.ServerResponse.prototype not working


As part of my learning of Node internals, I'm trying to add some basic functions to the Node response prototype without requiring some external libraries. It shouldn't be a difficult task, however, the response is never passed to the new functions and can never be retrieved through the this statement. This is an example to bind a template render function to the server response.

const http = require('http');

const newMethods = Object.create(http.ServerResponse.prototype);

newMethods.render = async (view, data) => {
    const renderResult = await aTemplateLibray(view, data);
    this.writeHead(200, {'Content-Type': 'text/html'});
    this.end(renderResult);
}
// Other methods here...

// Then
Object.assign(http.ServerResponse.prototype, newMethods);

module.exports = http;

Once I use this http server, I can use the new render function, but the response is not passed to it, so an error message is thrown, something like this.writeHead is not a function.

I also tried with the Object.defineProperty method.

Object.defineProperty(http.ServerResponse.prototype, 'render', 
    {writable: true,
     enumerable: true,
     get: return this.socket.parser.incoming
    });

I found some old library that returned that socket with the old __defineGetter__ method and I test it with the new form, but it doesn't work either.


Solution

  • The main issue is your use of the arrow function expression (=>), which has particular consequences with regards to what this points to inside the function (more on that here).

    In your case, you want to use async function(...):

    newMethods.render = async function(view, data) {
        const renderResult = await aTemplateLibray(view, data);
        this.writeHead(200, {'Content-Type': 'text/html'});
        this.end(renderResult);
    }