diff --git a/app/extend/context.js b/app/extend/context.js index 51d41756c..0f9d5c9e0 100644 --- a/app/extend/context.js +++ b/app/extend/context.js @@ -398,4 +398,5 @@ delegate(proto, 'request') .getter('isAjax') .getter('acceptJSON') .getter('queries') - .getter('accept'); + .getter('accept') + .access('ip'); diff --git a/app/extend/request.js b/app/extend/request.js index 15fed41ff..74d5b7097 100644 --- a/app/extend/request.js +++ b/app/extend/request.js @@ -71,12 +71,13 @@ module.exports = { }, /** - * 返回远程 ip 地址,总是返回 ipv4 + * Request remote IPv4 address * @member {String} Request#ip * @example * ```js * this.request.ip * => '127.0.0.1' + * => '111.10.2.1' * ``` */ get ip() { @@ -84,13 +85,20 @@ module.exports = { return this._ip; } const ip = this.ips[0] || this.socket.remoteAddress; - // ::ffff:x.x.x.x/96 是用于IPv4映射地址 - // 如果是 IPV6 也不会做处理,现在还未遇到 IPV6 的场景 + // will be '::ffff:x.x.x.x', should conver to standard IPv4 format // https://zh.wikipedia.org/wiki/IPv6 this._ip = ip && ip.indexOf('::ffff:') > -1 ? ip.substring(7) : ip; return this._ip; }, + /** + * Set the remote address + * @param {String} ip - IPv4 address + */ + set ip(ip) { + this._ip = ip; + }, + /** * 从请求头获取所有 ip * 1. 先从 `X-Forwarded-For` 获取,这个值是从 spanner 传递过来的,如果前置没有 spanner 返回为空 diff --git a/test/app/extend/context.test.js b/test/app/extend/context.test.js index bf840cbad..59297778c 100644 --- a/test/app/extend/context.test.js +++ b/test/app/extend/context.test.js @@ -5,8 +5,6 @@ const path = require('path'); const mm = require('egg-mock'); const request = require('supertest'); const sleep = require('ko-sleep'); - - const utils = require('../../utils'); describe('test/app/extend/context.test.js', () => { @@ -389,4 +387,32 @@ describe('test/app/extend/context.test.js', () => { .should.match(/\[egg:background] task:mockError fail \(\d+ms\)/); }); }); + + describe('ctx.ip', () => { + let app; + before(() => { + app = utils.app('apps/demo'); + return app.ready(); + }); + after(() => app.close()); + afterEach(mm.restore); + + it('should get current request ip', () => { + return request(app.callback()) + .get('/ip') + .expect(200) + .expect({ + ip: '127.0.0.1', + }); + }); + + it('should set current request ip', () => { + return request(app.callback()) + .get('/ip?set_ip=10.2.2.2') + .expect(200) + .expect({ + ip: '10.2.2.2', + }); + }); + }); }); diff --git a/test/fixtures/apps/demo/app/controller/ip.js b/test/fixtures/apps/demo/app/controller/ip.js new file mode 100644 index 000000000..8b3fe6df6 --- /dev/null +++ b/test/fixtures/apps/demo/app/controller/ip.js @@ -0,0 +1,10 @@ +'use strict'; + +module.exports = function* () { + if (this.query.set_ip) { + this.ip = this.query.set_ip; + } + this.body = { + ip: this.ip, + }; +}; diff --git a/test/fixtures/apps/demo/app/router.js b/test/fixtures/apps/demo/app/router.js index ae6b82530..f2dfcb77b 100644 --- a/test/fixtures/apps/demo/app/router.js +++ b/test/fixtures/apps/demo/app/router.js @@ -9,4 +9,5 @@ module.exports = app => { app.get('/user.json', function*() { this.jsonp = { name: 'fengmk2' }; }); + app.get('/ip', app.controller.ip); };