perak
June 9, 2017, 11:30am
1
Method is defined inside server scope in /server/methods/mymethod.js
Meteor.methods({
myMethod: function() {
console.log(this.connection.clientAddress);
}
});
I call method from the client (file /client/myfile.js
) with Meteor.call("myMethod");
and it always returns the same - server’s IP address (tried app from mobile phone connected to different ISP etc.).
Am I doing something wrong or this is normal or … ?
perak
June 9, 2017, 11:36am
2
BTW, Meteor version is 1.5
perak
June 9, 2017, 11:40am
3
And console.log(this.connection)
looks like this:
I20170609-13:20:25.265(2)? { id: 'YFdpzhTj8TmbvAMP9',
I20170609-13:20:25.266(2)? close: [Function],
I20170609-13:20:25.267(2)? onClose: [Function],
I20170609-13:20:25.267(2)? clientAddress: '93.86.68.77',
I20170609-13:20:25.268(2)? httpHeaders:
I20170609-13:20:25.268(2)? { 'x-forwarded-for': '93.86.68.77',
I20170609-13:20:25.269(2)? 'x-forwarded-proto': 'ws',
I20170609-13:20:25.269(2)? host: '93.86.68.77:3000',
I20170609-13:20:25.269(2)? 'user-agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_2 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) CriOS/59.0.3071.84 Mobile/14F89 Safari/602.1' } }
(app executing on my machine, I accessesd app via my iPhone which is connected to different ISP… and clientAddress is the same as server address).
XTA
June 9, 2017, 12:00pm
4
Is there any proxy running, f.e. NGINX?
perak
June 9, 2017, 12:03pm
5
No proxy (nginx). I simply started meteor on port 3000 and make NAT on my home router to redirect port 3000 to my machine’s local IP.
perak
June 9, 2017, 12:06pm
6
And the same happens if I deploy app to the “real” server
Can you try setting HTTP_FORWARDED_COUNT
environment variable to 1
(or more) as described here and see if that helps?
perak
June 10, 2017, 9:00am
8
@serkandurusoy thanks for advice. I tried that but doesn’t help. Tried with different numbers 1, 2, 3… but still the same.
perak
June 10, 2017, 9:15am
9
By the way, when HTTP_FORWARDED_COUNT
is set, then clientAddress is null, but I solved the problem by reading x-forwarder-for http header:
I20170610-11:04:43.613(2)? { id: 'gYkA35SuTeauWpHdh',
I20170610-11:04:43.614(2)? close: [Function],
I20170610-11:04:43.614(2)? onClose: [Function],
I20170610-11:04:43.614(2)? clientAddress: null,
I20170610-11:04:43.615(2)? httpHeaders:
I20170610-11:04:43.618(2)? { 'x-forwarded-for': '192.168.1.11',
I20170610-11:04:43.619(2)? 'x-forwarded-proto': 'ws',
I20170610-11:04:43.619(2)? host: '192.168.1.2:3000',
I20170610-11:04:43.619(2)? 'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.86 Safari/537.36',
I20170610-11:04:43.620(2)? 'accept-language': 'en-US,en;q=0.8,hr;q=0.6,bs;q=0.4' } }
Now, problem is solved but … is this normal behavior or is bug in Meteor?
perak
June 10, 2017, 9:36am
10
No… doesn’t work in production. When deployed to server then this.connection
is undefined
.
@perak have you ever solved it am on same situation Thanks in advance
sbr464
April 22, 2018, 7:10pm
12
Make sure you aren’t using an arrow function for the server method. Did you check below? I would ensure you’re running it on the server and the client is making the request, it’s not a nested method called by the server.
connection.httpHeaders['x-forwarded-for'].split(',')
This code is old/unused (don’t judge me!) but it worked fine in dev way back, if it can be of assistance.
import AuditBase from '/imports/AuditBase'
import rlog from '/imports/rlog'
import analytics from '/imports/server/analytics'
function getTenantIdFromUserId (userId) {
if (typeof userId === 'string') {
const userDoc = Meteor.users.findOne({_id: userId})
if (userDoc && userDoc._id === userId && typeof userDoc.tenant === 'string') {
return userDoc.tenant
}
}
};
function makeAppTenantUserObj (userId, tenantId, connectionId) {
if (typeof userId === 'string' && typeof tenantId === 'string' && typeof connectionId === 'string') {
return {
_tenantId: tenantId,
_userId: userId,
_connectionId: connectionId
}
} else {
return null
}
};
function verifyAppTenantObj (appObj = {}, connectionId) {
const result = typeof connectionId === 'string' && Match.test(appObj, {
_userId: String,
_tenantId: String,
_connectionId: String
})
return result && appObj._connectionId === connectionId
}
Accounts.onLogin(function (user) {
const appObj = makeAppTenantUserObj(user.user._id, user.user.tenant || getTenantIdFromUserId(user.user._id), user.connection.id)
if (appObj && verifyAppTenantObj(appObj, user.connection.id)) {
user.connection._app = appObj
} else {
user.connection._app = null
console.log('err - appObj not valid, setting user tenant to null')
}
analytics.track({
userId: user.user._id,
event: 'App Login',
properties: {
allowed: user.allowed,
methodName: user.methodName,
connection: user.connection,
tenantId: user.user.tenant
}
})
})
Meteor.onConnection(function (res) {
try {
return new AuditBase('connection', res)
// base.insertEvent()
// res.onClose(function() {
// console.log('res in onClose', res)
// })
} catch (e) {
rlog(e, 'err in Meteor.onConnection Audit event')
}
})
Meteor.methods({
getUserTenant () {
check(this.userId, String)
check(this.connection.id, String)
this.unblock()
if (verifyAppTenantObj(this.connection._app, this.connection.id)) {
return this.connection._app
} else {
throw new Meteor.Error('err - invalid tenant for user:', this.userId)
}
}
})
Meteor.methods({
getCurrentDetails () {
this.unblock()
const sessions = []
_.each(Meteor.server.sessions, doc => {
doc._namedSubs && _.each(doc._namedSubs, sub => {
if (sub._ready) {
sessions.push({
name: sub._name,
userId: sub.userId,
connectionId: sub.connection.id,
subId: sub._subscriptionId,
params: sub._params,
documents: sub._documents
})
}
})
})
return sessions
}
})