Using freegeoip for a list of IPs

851 views Asked by At

Please give me a simple tip where to dig!

I have multiple IP's and need to display the location next to each of them.

I have a list of IPS in array via

var table = document.createElement('table');
table.innerHTML = forext;
var ips = [].slice.call(table.querySelectorAll('a[href*="?ip="]')).map(anchor => anchor.textContent).join("\n");

8.8.8.8
8.8.4.4 
...

I can get the location of each of them via input box

$('.send').on('click', function(){

  $.getJSON('https://ipapi.co/'+$('.ip').val()+'/json', function(data){
      $('.city').text(data.city);
      $('.country').text(data.country);
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<input class="ip" value="8.8.8.8">
<button class="send">Go</button>
<br><br>
<span class="city"></span>, 
<span class="country"></span>

BUT what I need is to print the IPs and the location next to it:

So, I have this:

8.8.8.8
8.8.8.8

BUT I need this

8.8.8.8 -Mountain View, US
8.8.8.8 -Mountain View, US
...

How can I proceed the whole array via http://freegeoip.net/json/? Thank you.

Update 1: Trying to make it using: ips[i]

var ipText='Lookup...';
var table = document.createElement('table');
table.innerHTML = forext;
var ips = [].slice.call(table.querySelectorAll('a[href*="?ip="]')).map(anchor => anchor.textContent).join("\n");

var ipLocations = [];

for(i=0;i<ips.length;i++){

 $.getJSON('https:/freegeoip.net/json/' + ips[i], function(data) {
    // could also use data.country_name, or any other property in the returned JSON
    var outputString = data.ips[i] + ' - ' + data.city + ', ' + data.country_code; 
    ipLocations.push(outputString);

  });

}

ipText = ipLocations.join('\n');
message.innerText = ipText;
1

There are 1 answers

12
endemic On

First of all, you really want your IPs to be an array of strings, not a single string. As such, you should change your declaration for var ips = ... and delete the .join("\n") from the end--that turns your convenient list of IP strings into a single string with the IPs separated by newline characters, which you don't want.

Then, when you have an array of IP addresses of a form something like ips = ['8.8.8.8', '8.8.4.4', ... ];

...then you can get the output you described in the following way:

var ipLocations = [];
for (var ip of ips) {
  $.getJSON('https://freegeoip.net/json/' + ip, function(data) {
    // could also use data.country_name, or any other property in the returned JSON
    var outputString = data.ip + ' - ' + data.city + ', ' + data.country_code; 
    ipLocations.push(outputString);
  });
}

Now you have an array of strings with IP address + location, as you described. If you now want to turn THAT into a single string, you can do ipText = ipLocations.join('\n'); to get the output lines separated by newline characters.

If you're going to be outputting this text into an HTML document though, you might want to join on <br> instead of \n, there are many contexts in which whitespace characters like \n will be ignored and you would end up with all your output on one line.

UPDATE:

There were some very silly mistakes in my original answer, chief among them being that I mixed Python and JavaScript syntax (facepalm). Having fixed them, this code does work. That being said, there are some caveats that need to be mentioned, as well as some errors in your Update 1 code that you should really try to understand.

First, the issues in your code:

  • You never got rid of the .join("\n") from line 4 where you define ips, so it's still just a string instead of an array of strings. This means that your for-loop is actually looping over each individual character in the ips string, instead of complete IP addresses.
  • You try to access data.ips[i] inside of the loop. The data variable contains the JSON response to your AJAX request, but automatically converted from a JSON string into an actual JavaScript object by jQuery. It only has the properties that are included in the response. In this case, the response always has an ip property, so you can access data.ip. However, ips is a variable that YOU created--data.ips doesn't exist, so you can't access its indices.
    • As a side note, if you used the for...of syntax, you would also have a loop variable called ip that you can use instead. However, you need to understand that ip and data.ip are not the same variable, even if they will always have the same value in this case.
  • The URL starts with "https:/" instead of "https://". This one is actually my fault, I typo'd it in my original answer >_>;

With that out of the way, you brought up a very important point in your comment-- the function $.getJSON() is asynchronous, so (ignoring the other issues) the code as you wrote it in Update 1 will probably not do what you expect. The code after the call to getJSON will keep running even if your AJAX request doesn't have a response yet, so if you immediately access the ipLocs array it might only have some of the output strings yet, or even be empty.

I'm not going to explain how to wait on non-blocking code to you, because that's a completely different question. I'm also worried that it will only make things more confusing, given your apparent level of familiarity with JavaScript. But if you just want a quick solution that gives you the results that you expect, even if it's not at all best practice, then you can use the ajax function instead of getJSON. This allows you to explicitly tell jQuery to send your AJAX request synchronously, meaning it will wait for a response before continuing to run your code. However, you need to be aware that synchronous requests may temporarily lock your browser, preventing any other actions until the request is completed. That version would look like this:

var ipLocations = [];
for (var ip of ips) {
  $.ajax({
    url: 'https://freegeoip.net/json/' + ip,
    async: false,
    success: function(data) {
      var outputString = data.ip + ' - ' + data.city + ', ' + data.country_code; 
      ipLocations.push(outputString);
    }
  });
}