fix(response): correct response.writable logic (#781)
This commit is contained in:
parent
0590430d7b
commit
83d480efdf
3 changed files with 102 additions and 12 deletions
|
@ -478,16 +478,19 @@ module.exports = {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the request is writable.
|
* Checks if the request is writable.
|
||||||
* Tests for the existence of the socket
|
|
||||||
* as node sometimes does not set it.
|
|
||||||
*
|
*
|
||||||
* @return {Boolean}
|
* @return {Boolean}
|
||||||
* @api private
|
* @api private
|
||||||
*/
|
*/
|
||||||
|
|
||||||
get writable() {
|
get writable() {
|
||||||
|
// can't write any more after response finished
|
||||||
|
if (this.res.finished) return false;
|
||||||
|
|
||||||
var socket = this.res.socket;
|
var socket = this.res.socket;
|
||||||
if (!socket) return false;
|
// There are already pending outgoing res, but still writable
|
||||||
|
// https://github.com/nodejs/node/blob/v4.4.7/lib/_http_server.js#L486
|
||||||
|
if (!socket) return true;
|
||||||
return socket.writable;
|
return socket.writable;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ var request = require('supertest');
|
||||||
var statuses = require('statuses');
|
var statuses = require('statuses');
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
var http = require('http');
|
var http = require('http');
|
||||||
|
var net = require('net');
|
||||||
var koa = require('..');
|
var koa = require('..');
|
||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
var AssertionError = assert.AssertionError;
|
var AssertionError = assert.AssertionError;
|
||||||
|
|
|
@ -1,19 +1,105 @@
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var response = require('../context').response;
|
var should = require('should');
|
||||||
|
var koa = require('../../');
|
||||||
|
var net = require('net');
|
||||||
|
|
||||||
describe('res.writable', function(){
|
describe('res.writable', function(){
|
||||||
it('should return the request is writable', function(){
|
describe('when continuous requests in one persistent connection', function() {
|
||||||
var res = response();
|
function requestTwice(server, done) {
|
||||||
res.writable.should.be.ok;
|
let port = server.address().port;
|
||||||
|
var buf = new Buffer('GET / HTTP/1.1\r\nHost: localhost:' + port + '\r\nConnection: keep-alive\r\n\r\n');
|
||||||
|
var client = net.connect(port);
|
||||||
|
var datas = [];
|
||||||
|
client
|
||||||
|
.on('error', done)
|
||||||
|
.on('data', function(data) {
|
||||||
|
datas.push(data);
|
||||||
|
})
|
||||||
|
.on('end', function() {
|
||||||
|
done(null, datas);
|
||||||
|
});
|
||||||
|
setImmediate(function() {
|
||||||
|
client.write(buf);
|
||||||
|
});
|
||||||
|
setImmediate(function() {
|
||||||
|
client.write(buf);
|
||||||
|
});
|
||||||
|
setTimeout(function() {
|
||||||
|
client.end();
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
it('should always writable and response all requests', function(done) {
|
||||||
|
var app = koa();
|
||||||
|
var count = 0;
|
||||||
|
app.use(function*() {
|
||||||
|
count++;
|
||||||
|
this.body = 'request ' + count + ', writable: ' + this.writable;
|
||||||
|
});
|
||||||
|
|
||||||
|
var server = app.listen();
|
||||||
|
requestTwice(server, function(err, datas) {
|
||||||
|
var responses = Buffer.concat(datas).toString();
|
||||||
|
responses.should.match(/request 1, writable: true/);
|
||||||
|
responses.should.match(/request 2, writable: true/);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('when res.socket not present', function (){
|
describe('when socket closed before response sent', function() {
|
||||||
it('should return the request is not writable', function (){
|
function requsetClosed(server) {
|
||||||
var res = response();
|
let port = server.address().port;
|
||||||
res.res.socket = null;
|
var buf = new Buffer('GET / HTTP/1.1\r\nHost: localhost:' + port + '\r\nConnection: keep-alive\r\n\r\n');
|
||||||
res.writable.should.not.be.ok;
|
var client = net.connect(port);
|
||||||
|
setImmediate(function() {
|
||||||
|
client.write(buf);
|
||||||
|
client.end();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
it('should not writable', function(done) {
|
||||||
|
var app = koa();
|
||||||
|
app.use(function*() {
|
||||||
|
yield sleep(1000);
|
||||||
|
if (this.writable) return done(new Error('this.writable should not be true'));
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
var server = app.listen();
|
||||||
|
requsetClosed(server);
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('when resposne finished', function() {
|
||||||
|
function request(server) {
|
||||||
|
let port = server.address().port;
|
||||||
|
var buf = new Buffer('GET / HTTP/1.1\r\nHost: localhost:' + port + '\r\nConnection: keep-alive\r\n\r\n');
|
||||||
|
var client = net.connect(port);
|
||||||
|
setImmediate(function() {
|
||||||
|
client.write(buf);
|
||||||
|
});
|
||||||
|
setTimeout(function() {
|
||||||
|
client.end();
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
it('should not writable', function(done) {
|
||||||
|
var app = koa();
|
||||||
|
app.use(function*() {
|
||||||
|
this.res.end();
|
||||||
|
if (this.writable) return done(new Error('this.writable should not be true'));
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
var server = app.listen();
|
||||||
|
request(server);
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
function sleep(time) {
|
||||||
|
return new Promise(function(resolve) {
|
||||||
|
setTimeout(resolve, time);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue