Skip to content

Commit

Permalink
refactor: export app.HttpClient that can be overwritten (#1234)
Browse files Browse the repository at this point in the history
  • Loading branch information
popomore authored and atian25 committed Jul 26, 2017
1 parent 96b3786 commit e9f93cf
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 20 deletions.
10 changes: 4 additions & 6 deletions lib/core/dnscache_httpclient.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,14 @@
const dns = require('dns');
const LRU = require('ylru');
const urlparse = require('url').parse;
const urllib = require('urllib');
const HttpClient = require('./httpclient');
const utility = require('utility');

const IP_REGEX = /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/;

class DNSCacheHttpClient extends urllib.HttpClient {
constructor(options) {
super(options);

this.app = options.app;
class DNSCacheHttpClient extends HttpClient {
constructor(app) {
super(app);
this.dnsCacheLookupInterval = this.app.config.httpclient.dnsCacheLookupInterval;
this.dnsCache = new LRU(this.app.config.httpclient.dnsCacheMaxLength);
}
Expand Down
27 changes: 17 additions & 10 deletions lib/core/httpclient.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,22 @@ const HttpsAgent = require('agentkeepalive').HttpsAgent;
const urllib = require('urllib');
const ms = require('humanize-ms');

module.exports = app => {
const HttpClient = app.config.httpclient.enableDNSCache ?
require('./dnscache_httpclient') : urllib.HttpClient;

class HttpClient extends urllib.HttpClient {
constructor(app) {
const config = app.config.httpclient;
normalizeConfig(app);
super({
app,
defaultArgs: config.request,
agent: new Agent(config.httpAgent),
httpsAgent: new HttpsAgent(config.httpsAgent),
});
this.app = app;
}
}

function normalizeConfig(app) {
const config = app.config.httpclient;

// compatibility
Expand Down Expand Up @@ -49,11 +61,6 @@ module.exports = app => {
if (typeof config.request.timeout === 'string') {
config.request.timeout = ms(config.request.timeout);
}
}

return new HttpClient({
app,
defaultArgs: config.request,
agent: new Agent(config.httpAgent),
httpsAgent: new HttpsAgent(config.httpsAgent),
});
};
module.exports = HttpClient;
10 changes: 8 additions & 2 deletions lib/egg.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ const ContextLogger = require('egg-logger').EggContextLogger;
const ContextCookies = require('egg-cookies');
const ContextHttpClient = require('./core/context_httpclient');
const Messenger = require('./core/messenger');
const createHttpClient = require('./core/httpclient');
const DNSCacheHttpClient = require('./core/dnscache_httpclient');
const HttpClient = require('./core/httpclient');
const createLoggers = require('./core/logger');
const Singleton = require('./core/singleton');
const utils = require('./core/utils');
Expand Down Expand Up @@ -42,6 +43,7 @@ class EggApplication extends EggCore {
this.ContextCookies = ContextCookies;
this.ContextLogger = ContextLogger;
this.ContextHttpClient = ContextHttpClient;
this.HttpClient = HttpClient;

this.loader.loadConfig();

Expand Down Expand Up @@ -240,7 +242,11 @@ class EggApplication extends EggCore {
*/
get httpclient() {
if (!this[HTTPCLIENT]) {
this[HTTPCLIENT] = createHttpClient(this);
if (this.config.httpclient.enableDNSCache) {
this[HTTPCLIENT] = new DNSCacheHttpClient(this);
} else {
this[HTTPCLIENT] = new this.HttpClient(this);
}
}
return this[HTTPCLIENT];
}
Expand Down
21 changes: 21 additions & 0 deletions test/fixtures/apps/httpclient-overwrite/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
'use strict';

const assert = require('assert');

module.exports = app => {
class CustomHttpClient extends app.HttpClient {
request(url, opt) {
return new Promise(resolve => {
assert(/^http/.test(url), 'url should start with http, but got ' + url);
resolve();
}).then(() => {
return super.request(url, opt);
});
}

curl(url, opt) {
return this.request(url, opt);
}
}
app.HttpClient = CustomHttpClient;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
'use strict';

exports.httpclient = {
request: {
timeout: 100,
},
};
3 changes: 3 additions & 0 deletions test/fixtures/apps/httpclient-overwrite/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"name": "httpclient-overwrite"
}
30 changes: 28 additions & 2 deletions test/lib/core/httpclient.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@

const assert = require('assert');
const mm = require('egg-mock');
const createHttpclient = require('../../../lib/core/httpclient');
const Httpclient = require('../../../lib/core/httpclient');
const utils = require('../../utils');

describe('test/lib/core/httpclient.test.js', () => {
let client;
let url;

before(() => {
client = createHttpclient({
client = new Httpclient({
config: {
httpclient: {
request: {},
Expand Down Expand Up @@ -151,4 +151,30 @@ describe('test/lib/core/httpclient.test.js', () => {
});
});
});

describe('overwrite httpclient', () => {
let app;
before(() => {
app = utils.app('apps/httpclient-overwrite');
return app.ready();
});
after(() => app.close());

it('should set request default global timeout to 100ms', () => {
return app.httpclient.curl(`${url}/timeout`)
.catch(err => {
assert(err);
assert(err.name === 'ResponseTimeoutError');
assert(err.message.includes('Response timeout for 100ms'));
});
});

it('should assert url', () => {
return app.httpclient.curl('unknown url')
.catch(err => {
assert(err);
assert(err.message.includes('url should start with http, but got unknown url'));
});
});
});
});

0 comments on commit e9f93cf

Please sign in to comment.