Skip to content

Commit

Permalink
Fix inheritance should not overwrite the methods of http.ServerRespon…
Browse files Browse the repository at this point in the history
…se and http.IncomingMessage
  • Loading branch information
Tofandel committed Oct 13, 2024
1 parent a46cfdc commit 1847da8
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 6 deletions.
13 changes: 7 additions & 6 deletions lib/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ var merge = require('utils-merge');
var resolve = require('path').resolve;
var once = require('once')
var Router = require('router');
var setPrototypeUntil = require('./setPrototypeUntil')
var setPrototypeOf = require('setprototypeof')
var resProto = require('./response')
var reqProto = require('./request')

/**
* Module variables.
Expand Down Expand Up @@ -117,8 +120,6 @@ app.defaultConfiguration = function defaultConfiguration() {
}

// inherit protos
setPrototypeOf(this.request, parent.request)
setPrototypeOf(this.response, parent.response)
setPrototypeOf(this.engines, parent.engines)
setPrototypeOf(this.settings, parent.settings)
});
Expand Down Expand Up @@ -168,8 +169,8 @@ app.handle = function handle(req, res, callback) {
res.req = req;

// alter the prototypes
setPrototypeOf(req, this.request)
setPrototypeOf(res, this.response)
setPrototypeUntil(req, this.request, reqProto)
setPrototypeUntil(res, this.response, resProto)

// setup locals
if (!res.locals) {
Expand Down Expand Up @@ -232,8 +233,8 @@ app.use = function use(fn) {
router.use(path, function mounted_app(req, res, next) {
var orig = req.app;
fn.handle(req, res, function (err) {
setPrototypeOf(req, orig.request)
setPrototypeOf(res, orig.response)
setPrototypeUntil(req, orig.request)
setPrototypeUntil(res, orig.response)
next(err);
});
});
Expand Down
32 changes: 32 additions & 0 deletions lib/setPrototypeUntil.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@

function setPrototypeUntil(obj, proto, until) {
var currentProto = proto;
until = until || proto;
var last = Object.getPrototypeOf(until);
while (currentProto && currentProto !== last) {
Object.keys(currentProto).forEach(function (key) {
setPrototypeKey(obj, proto, key, until)
});
currentProto = Object.getPrototypeOf(currentProto)
}
}

function setPrototypeKey(obj, proto, key, until) {
Object.defineProperty(obj, key, {
configurable: true,
enumerable: proto.propertyIsEnumerable(key),
get: function () {
var desc = Object.getOwnPropertyDescriptor(until, key)
if (desc && typeof desc.get === 'function') {
// property defined with defineGetter, we need to change the `this` of the getter accordingly
return desc.get.call(obj)
}
return proto[key]
},
set: function (v) {
proto[key] = v
}
})
}

module.exports = setPrototypeUntil
23 changes: 23 additions & 0 deletions test/app.response.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,5 +139,28 @@ describe('app', function(){
.get('/sub/foo')
.expect(200, 'FOO', cb)
})

it('should inherit parent app', function (done) {
var app1 = express()
var app2 = express()
var cb = after(1, done)

app2.request.foo = 'bar';
app1.response.shout = function (str) {
this.setHeader('foo', this.req.foo)
this.send(str.toUpperCase())
}

app1.use('/sub', app2)

app2.get('/', function (req, res) {
res.shout('foo')
})

request(app1)
.get('/sub')
.expect('foo', 'bar')
.expect(200, 'FOO', cb)
})
})
})

0 comments on commit 1847da8

Please sign in to comment.