Skip to content

Commit 37b4aff

Browse files
authored
fix: redefine ip decorator when trustProxy option is set to true (#51)
1 parent ab112e7 commit 37b4aff

File tree

3 files changed

+59
-5
lines changed

3 files changed

+59
-5
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ The plugin will make a best-effort to infer the request's IP based on a subset o
2727

2828
The plugin will use a FIFO strategy to infer the right IP. This can be customised by passing a custom order property that includes your custom headers.
2929

30-
>Note: It is important to remark that this does not alters the `Request#ips` behaviour for inferring IPs when setting the `FastifyOptions#trustProxy` to `true`. It rather allows you to infer the IP of a given request by headers out of the common spec or standard.
30+
>Note: It is important to remark that this does not alters the `Request#ips` behavior for inferring IPs when setting the `FastifyOptions#trustProxy` to `true`. It rather allows you to infer the IP of a given request by headers out of the common spec or standard. However, the `ip` decorator may be updated by fastify-ip, depending on the order of priority in which the above-mentioned headers are processed.
3131
3232
## Setup
3333

index.js

+24-3
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,8 @@ function fastifyIp (
6161
instance.decorateRequest('inferIPVersion', inferIPVersion)
6262
instance.decorateRequest('_fastifyip', '')
6363

64-
// Core method
65-
instance.decorateRequest('ip', {
64+
const ipDecorator = {
65+
// Core method
6666
getter: function () {
6767
let ip = this._fastifyip
6868
if (ip !== '') return ip
@@ -90,7 +90,28 @@ function fastifyIp (
9090

9191
return ip
9292
}
93-
})
93+
}
94+
95+
const isTrustProxyOn = [
96+
'ip',
97+
'ips',
98+
'hostname',
99+
'protocol'
100+
].every((key) => instance.hasRequestDecorator(key))
101+
102+
if (isTrustProxyOn) {
103+
function redefineIpDecorator (request, unusedReply, done) {
104+
Object.defineProperty(request, 'ip', {
105+
get: ipDecorator.getter.bind(request)
106+
})
107+
108+
done()
109+
}
110+
111+
instance.addHook('preHandler', redefineIpDecorator)
112+
} else {
113+
instance.decorateRequest('ip', ipDecorator)
114+
}
94115

95116
done()
96117

test/index.test.js

+34-1
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ tap.test('Plugin#Decoration', scope => {
112112
})
113113

114114
tap.test('Plugin#Request IP', scope => {
115-
scope.plan(8)
115+
scope.plan(9)
116116

117117
scope.test('Should infer the header based on default priority', async t => {
118118
const app = fastify()
@@ -475,4 +475,37 @@ tap.test('Plugin#Request IP', scope => {
475475
})
476476
}
477477
)
478+
479+
scope.test('Should replace the IP even if trustProxy option is set to true', async t => {
480+
const app = fastify({ trustProxy: true })
481+
const localIP = '127.0.0.1'
482+
const expectedIP = faker.internet.ip()
483+
484+
async function withoutPlugin (instance) {
485+
instance.get('/withoutPlugin', async (req) => {
486+
t.equal(req.ip, localIP)
487+
})
488+
}
489+
490+
async function withPlugin (instance) {
491+
instance.register(plugin)
492+
instance.get('/withPlugin', async (req) => {
493+
t.equal(req.ip, expectedIP)
494+
t.equal(req._fastifyip, expectedIP)
495+
})
496+
}
497+
498+
app.register(withoutPlugin)
499+
app.register(withPlugin)
500+
501+
t.plan(3)
502+
503+
await app.inject('/withoutPlugin')
504+
await app.inject({
505+
path: '/withPlugin',
506+
headers: {
507+
'x-client-ip': expectedIP
508+
}
509+
})
510+
})
478511
})

0 commit comments

Comments
 (0)