Skip to content

Commit

Permalink
Delete dependency on git repo
Browse files Browse the repository at this point in the history
  • Loading branch information
sogaani committed Sep 17, 2018
1 parent b4f3652 commit 832cc03
Show file tree
Hide file tree
Showing 6 changed files with 224 additions and 7 deletions.
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
coverage
node_modules
/test/support/supertest/http2wrapper.js
5 changes: 1 addition & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ before_install:
# Setup Node.js version-specific dependencies
- "test $TRAVIS_NODE_VERSION != '0.8' || npm rm --save-dev istanbul"
- "test $(echo $TRAVIS_NODE_VERSION | cut -d. -f1) -ge 4 || npm rm --save-dev $(grep -E '\"eslint\\S*\"' package.json | cut -d'\"' -f2)"
- "test -z $(echo $HTTP2_TEST) || npm install --only=dev https://github.com/sogaani/supertest.git#http2"

# Update Node.js modules
- "test ! -d node_modules || npm prune"
Expand All @@ -38,7 +37,5 @@ after_script:
- "test -e ./coverage/lcov.info && npm install coveralls@2 && cat ./coverage/lcov.info | coveralls"
matrix:
include:
- node_js: "8.11"
env: HTTP2_TEST=1
- node_js: "10.7"
- node_js: "10"
env: HTTP2_TEST=1
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"eslint-plugin-standard": "3.0.1",
"istanbul": "0.4.5",
"mocha": "2.5.3",
"supertest": "1.1.0"
"supertest": "2.0"
},
"files": [
"LICENSE",
Expand Down
188 changes: 188 additions & 0 deletions test/support/supertest/http2wrapper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
'use strict';

const http2 = require('http2');
const Stream = require('stream');
const util = require('util');
const net = require('net');
const tls = require('tls');
const parse = require('url').parse;

const {
HTTP2_HEADER_PATH,
HTTP2_HEADER_STATUS,
HTTP2_HEADER_METHOD,
HTTP2_HEADER_AUTHORITY,
HTTP2_HEADER_HOST,
HTTP2_HEADER_SET_COOKIE,
NGHTTP2_CANCEL,
} = http2.constants;


function setProtocol(protocol) {
return {
request: function (options) {
return new Request(protocol, options);
}
}
}

function Request(protocol, options) {
Stream.call(this);
const defaultPort = protocol === 'https:' ? 443 : 80;
const defaultHost = 'localhost'
const port = options.port || defaultPort;
const host = options.host || defaultHost;

delete options.port
delete options.host

this.method = options.method.toUpperCase();
this.path = options.path;
this.protocol = protocol;
this.host = host;

delete options.method
delete options.path

const sessionOptions = Object.assign({}, options);
if (options.socketPath) {
sessionOptions.socketPath = options.socketPath;
sessionOptions.createConnection = this.createUnixConnection.bind(this);
}

this._headers = {};

const session = http2.connect(`${protocol}//${host}:${port}`, sessionOptions);
this.setHeader('host', `${host}:${port}`)

session.on('error', (err) => this.emit('error', err));

this.session = session;
}

/**
* Inherit from `Stream` (which inherits from `EventEmitter`).
*/
util.inherits(Request, Stream);

Request.prototype.createUnixConnection = function (authority, options) {
switch (this.protocol) {
case 'http:':
return net.connect(options.socketPath);
case 'https:':
options.ALPNProtocols = ['h2'];
options.servername = this.host;
options.allowHalfOpen = true;
return tls.connect(options.socketPath, options);
default:
throw new Error('Unsupported protocol', this.protocol);
}
}

Request.prototype.setNoDelay = function (bool) {
// We can not use setNoDelay with HTTP/2.
// Node 10 limits http2session.socket methods to ones safe to use with HTTP/2.
// See also https://nodejs.org/api/http2.html#http2_http2session_socket
}

Request.prototype.getFrame = function () {
if (this.frame) {
return this.frame;
}

const method = {
[HTTP2_HEADER_PATH]: this.path,
[HTTP2_HEADER_METHOD]: this.method,
}

let headers = this.mapToHttp2Header(this._headers);

headers = Object.assign(headers, method);

const frame = this.session.request(headers);
frame.once('response', (headers, flags) => {
headers = this.mapToHttpHeader(headers);
frame.headers = headers;
frame.status = frame.statusCode = headers[HTTP2_HEADER_STATUS];
this.emit('response', frame);
});

this._headerSent = true;

frame.once('drain', () => this.emit('drain'));
frame.on('error', (err) => this.emit('error', err));
frame.on('close', () => this.session.close());

this.frame = frame;
return frame;
}

Request.prototype.mapToHttpHeader = function (headers) {
const keys = Object.keys(headers);
const http2Headers = {};
for (var i = 0; i < keys.length; i++) {
let key = keys[i];
let value = headers[key];
key = key.toLowerCase();
switch (key) {
case HTTP2_HEADER_SET_COOKIE:
value = Array.isArray(value) ? value : [value];
break;
default:
break;
}
http2Headers[key] = value;
}
return http2Headers;
}

Request.prototype.mapToHttp2Header = function (headers) {
const keys = Object.keys(headers);
const http2Headers = {};
for (var i = 0; i < keys.length; i++) {
let key = keys[i];
let value = headers[key];
key = key.toLowerCase();
switch (key) {
case HTTP2_HEADER_HOST:
key = HTTP2_HEADER_AUTHORITY;
value = /^http\:\/\/|^https\:\/\//.test(value) ? parse(value).host : value;
break;
default:
break;
}
http2Headers[key] = value;
}
return http2Headers;
}

Request.prototype.setHeader = function (name, value) {
this._headers[name.toLowerCase()] = value;
}

Request.prototype.getHeader = function (name) {
return this._headers[name.toLowerCase()];
}

Request.prototype.write = function (data, encoding) {
const frame = this.getFrame();
return frame.write(data, encoding);
};

Request.prototype.pipe = function (stream, options) {
const frame = this.getFrame();
return frame.pipe(stream, options);
}

Request.prototype.end = function (data) {
const frame = this.getFrame();
frame.end(data);
}

Request.prototype.abort = function (data) {
const frame = this.getFrame();
frame.close(NGHTTP2_CANCEL);
this.session.destroy();
}

exports.setProtocol = setProtocol;
32 changes: 32 additions & 0 deletions test/support/supertest/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
var request = require('supertest')

if (process.env.HTTP2_TEST) {
var http2 = require('http2')
var http2wrapper = require('./http2wrapper')
var agent = require('superagent')
var tls = require('tls')
agent.protocols = {
'http:': http2wrapper.setProtocol('http:'),
'https:': http2wrapper.setProtocol('https:')
}
request.Test.prototype.serverAddress = function (app, path, host) {
var addr = app.address()
var port
var protocol

if (!addr) this._server = app.listen(0)
port = app.address().port

protocol = app instanceof tls.Server ? 'https' : 'http'
return protocol + '://' + (host || '127.0.0.1') + ':' + port + path
}
var originalRequest = request
request = function (app) {
if (typeof app === 'function') {
app = http2.createServer(app)
}
return originalRequest(app)
}
}

module.exports = request
3 changes: 1 addition & 2 deletions test/test.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@

var assert = require('assert')
var http = require('http')
var request = require('supertest')
var request = require('./support/supertest')
var vhost = require('..')

if (process.env.HTTP2_TEST) {
request.http2 = true
http = require('http2')
}

Expand Down

0 comments on commit 832cc03

Please sign in to comment.