All my trials to get to the client IP address are leading to undefined


#1

Hi,

I can’t manage to let the app (my first app ever) find out on the server what the client IP address is. I’ve tried a few things already and would be very glad if someone could point me into the right direction.

Background information: I am trying to add a reCaptcha to a form (autoform) and for this I need to pass the client IP address as an argument to a function called within the method called to submit the form.

The problem:

this.connection.clientAddress

gives this error message:

Error: Exception while simulating the effect of invoking …
TypeError: Cannot read property ‘clientAddress’ of undefined

So I tried the 2 solutions provided on stackoverflow to what seemed to be a similar problem - http://stackoverflow.com/questions/24032129/in-meteor-method-why-is-this-connection-clientaddress-undefined :

Sol. 1:

var ip = "0.0.0.0";
if(Meteor.isServer) {
    if(!this.connection.clientAddress)
       throw new Meteor.Error(403, "Server Error: You must be connected.");
    else
       ip = this.connection.clientAddress;
}

Sol. 2:

var ip = "0.0.0.0";
if (!this.isSimulation) { ip = this.connection.clientAddress; }

It didn’t solve the problem though. So I thought that adding mizzao:user-status to the app would provide me with a magic :star2: solution. I called:

var ip = UserStatus.connections.ipAddr;

and received the now familiar message:

Error: Exception while simulating the effect of invoking …
TypeError: Cannot read property ‘ipAddr’ of undefined

Is someone willing to help? :balloon:


#2

Here the code used to implement recaptcha.

Client side

<template name="signupForm">
    <form class="form-horizontal" id="loginForm">
        <div class="form-group input-group">
            <span class="input-group-addon">
                <span class="fa fa-user fa-lg fa-fw icon-grey"></span>
            </span>
            <input id="fullNameInput" type="text" class="form-control" placeholder="Full name">
        </div>
        <div class="form-group input-group">
            <span class="input-group-addon">
                <span class="fa fa-envelope-o fa-lg fa-fw icon-grey"></span>
            </span>
            <input id="emailInput" type="text" class="form-control" placeholder="Email">
        </div>        
        <div class="form-group input-group">
            <span class="input-group-addon">
                <span class="fa fa-key fa-lg fa-fw icon-grey"></span>
            </span>
            <input id="passwordInput" type="password" class="form-control" placeholder="Password">
        </div>
        <div class="form-group">
            {{> reCAPTCHA}} 
        </div>
        <div class="form-group">
            <button id="loginButton" type="submit" class="btn btn-success">Sign up</button>
        </div>
    </form>
</template>


reCAPTCHA.config({
    theme: 'light',  // 'light' (default) or 'dark'
    publickey: 'my-public-key'
});


Template.signup.events({

    'submit form': function (evt) {
        evt.preventDefault();

        var formData = {
            //get the data from your form fields
        };

        console.log('formdata', $('#g-recaptcha-response').val(), evt);

        Meteor.call('formSubmissionMethod', $('#g-recaptcha-response').val(), function (error, result) {
            console.log('result: ', error, result);

        });
    }
});

Server side:

reCAPTCHA.config({
    privatekey: 'my-private-key'
});

Meteor.methods({
    formSubmissionMethod: function (response) {

        var verifyCaptchaResponse = reCAPTCHA.verifyCaptcha(this.connection.clientAddress, response);

        //console.log('reCAPTCHA response', verifyCaptchaResponse.data);
        if( verifyCaptchaResponse.data.success === false ){
            return verifyCaptchaResponse.data;
        }
        //do stuff with your formData

        return true;
    }
});

#3

Thank you for the reply. I will see if it helps and post any finding here.


#4

I am using autoform for the form and

this.connection.clientAddress

is in the submit method just like in appshore’s server side example above.

I thought that the error I was receiving was making the reCAPTCHA verification fail but after fixing an issue I found related to the autoform, I am still getting the same error in the browser console but the reCAPTCHA verification passes. I still do not know why this.connection in the method is undefined though.


#5

Did you see these posts on the same subject? https://github.com/mizzao/meteor-user-status/issues/50


#6

Hi! Your issue is not with

this.connection.clientAddress

but rather with returning a call to the server. That’s why it return undefined. If you use it on the server it returns it just fine.
To get it in the client side, you’ll need to call it like this:

Server:

Meteor.methods({
    getIP: function(){
        var ip = this.connection.clientAddress;
        return ip;
    }
});

Client:

Meteor.call('getIP', function(error, result){
            if(error){
               //Error handling code
            }
            else {
                Session.set("ip", result);
            }
        });

var ip = Session.get("ip");

#7

Hi!

I made it!

@appshore: Thanks, I saw it, yes.
@mesosteros: Thank you for the bits of code.

I tried your solutions and it didn’t work though. Then the fact that mesosteros clearly stated that the method is on the server pointed into the right direction.

The method I defined was in the /lib/collections folder. I also read that methods are code that is executed on the server (but thought they can be declared outside of the /server folder) and can be called client side. Anyway I tried to put the method within a if ( Meteor.isServer ) block and it solved the issue.

If I may ask a question: I am a bit confused now. In the the Discover Meteor book the Method used to insert posts is in the /lib/collections folder and is not in a if ( Meteor.isServer ) block. Why?


#8

The lib folder runs both on the Client and Server. I never tried putting a method outside of a if ( Meteor.isServer ) block in there but I would assume it runs anyway because of having access to the server there.


#9

Meteor is teaching a lot of people how to return values from async functions, myself included :thumbsup:


#10

What about getting the client IP from a server-side only Iron Router route? I’m finding I need to do this to for a reCaptcha web form I have on my app’s landing page that’s not part of my Meteor app but that I process with my Meteor server.

In this scenario a user is not logged in. Do you just have to manually get them from the request headers?


#11
Meteor.onConnection(function (connection) {
    setClientIP(connection.clientAddress);
});