Skip to content

Commit

Permalink
feat: supports http2
Browse files Browse the repository at this point in the history
  • Loading branch information
lamweili committed Oct 3, 2022
1 parent e064b5a commit da57804
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 6 deletions.
31 changes: 31 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,37 @@ request(app)
});
```

To enable http2 protocol, simply append an options to `request` or `request.agent`:

```js
const request = require('supertest');
const express = require('express');

const app = express();

app.get('/user', function(req, res) {
res.status(200).json({ name: 'john' });
});

request(app, { http2: true })
.get('/user')
.expect('Content-Type', /json/)
.expect('Content-Length', '15')
.expect(200)
.end(function(err, res) {
if (err) throw err;
});

request.agent(app, { http2: true })
.get('/user')
.expect('Content-Type', /json/)
.expect('Content-Length', '15')
.expect(200)
.end(function(err, res) {
if (err) throw err;
});
```

Here's an example with mocha, note how you can pass `done` straight to any of the `.expect()` calls:

```js
Expand Down
25 changes: 22 additions & 3 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@
*/
const methods = require('methods');
const http = require('http');
let http2;
try {
http2 = require('http2'); // eslint-disable-line global-require
} catch (_) {
// eslint-disable-line no-empty
}
const Test = require('./lib/test.js');
const agent = require('./lib/agent.js');

Expand All @@ -16,16 +22,29 @@ const agent = require('./lib/agent.js');
* @return {Test}
* @api public
*/
module.exports = function(app) {
module.exports = function(app, options = {}) {
const obj = {};

if (typeof app === 'function') {
app = http.createServer(app); // eslint-disable-line no-param-reassign
if (options.http2) {
if (!http2) {
throw new Error(
'supertest: this version of Node.js does not support http2'
);
}
app = http2.createServer(app); // eslint-disable-line no-param-reassign
} else {
app = http.createServer(app); // eslint-disable-line no-param-reassign
}
}

methods.forEach(function(method) {
obj[method] = function(url) {
return new Test(app, method, url);
var test = new Test(app, method, url);
if (options.http2) {
test.http2();
}
return test;
};
});

Expand Down
27 changes: 25 additions & 2 deletions lib/agent.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@
const { agent: Agent } = require('superagent');
const methods = require('methods');
const http = require('http');
let http2;
try {
http2 = require('http2'); // eslint-disable-line global-require
} catch (_) {
// eslint-disable-line no-empty
}
const Test = require('./test.js');

/**
Expand All @@ -17,10 +23,24 @@ const Test = require('./test.js');
* @api public
*/

function TestAgent(app, options) {
function TestAgent(app, options = {}) {
if (!(this instanceof TestAgent)) return new TestAgent(app, options);
if (typeof app === 'function') app = http.createServer(app); // eslint-disable-line no-param-reassign

Agent.call(this, options);
this._options = options;

if (typeof app === 'function') {
if (options.http2) {
if (!http2) {
throw new Error(
'supertest: this version of Node.js does not support http2'
);
}
app = http2.createServer(app); // eslint-disable-line no-param-reassign
} else {
app = http.createServer(app); // eslint-disable-line no-param-reassign
}
}
this.app = app;
}

Expand All @@ -40,6 +60,9 @@ TestAgent.prototype.host = function(host) {
methods.forEach(function(method) {
TestAgent.prototype[method] = function(url, fn) { // eslint-disable-line no-unused-vars
const req = new Test(this.app, method.toUpperCase(), url);
if (this._options.http2) {
req.http2();
}

if (this._host) {
req.set('host', this._host);
Expand Down
2 changes: 1 addition & 1 deletion lib/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

const { inspect } = require('util');
const { STATUS_CODES } = require('http');
const { Server } = require('https');
const { Server } = require('tls');
const { deepStrictEqual } = require('assert');
const { Request } = require('superagent');

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
"mocha": "^10.0.0",
"nock": "^13.2.8",
"nyc": "^15.1.0",
"proxyquire": "^2.1.3",
"should": "^13.2.3"
}
}
65 changes: 65 additions & 0 deletions test/supertest.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
'use strict';

const https = require('https');
let http2;
try {
http2 = require('http2'); // eslint-disable-line global-require
} catch (_) {
// eslint-disable-line no-empty
}
const fs = require('fs');
const path = require('path');
const should = require('should');
Expand Down Expand Up @@ -1340,3 +1346,62 @@ describe('request.get(url).query(vals) works as expected', function () {
});
});
});

const describeHttp2 = (http2) ? describe : describe.skip;
describeHttp2('http2', function() {
// eslint-disable-next-line global-require
const proxyquire = require('proxyquire');

const tests = [
{
title: 'request(app)',
api: request,
mockApi: proxyquire('../index.js', { http2: null })
},
{
title: 'request.agent(app)',
api: request.agent,
mockApi: proxyquire('../lib/agent.js', { http2: null })
}
];

tests.forEach(({ title, api, mockApi }) => {
describe(title, function () {
const app = function(req, res) {
res.end('hey');
};

it('should fire up the app on an ephemeral port', function (done) {
api(app, { http2: true })
.get('/')
.end(function (err, res) {
res.status.should.equal(200);
res.text.should.equal('hey');
done();
});
});

it('should work with an active server', function (done) {
const server = http2.createServer(app);

server.listen(function () {
api(server)
.get('/')
.http2()
.end(function (err, res) {
res.status.should.equal(200);
res.text.should.equal('hey');
// close the external server explictly
server.close(done);
});
});
});

it('should throw error if http2 is not supported', function() {
(function() {
mockApi(app, { http2: true });
}).should.throw('supertest: this version of Node.js does not support http2');
});
});
});
});

0 comments on commit da57804

Please sign in to comment.