SK.
SK.

Reputation: 1510

Get local client ip address

After a lot of research/googling, I am able to get the local client IP address using JQuery and integrated with my Angular 6 project. Though I am getting what I want, I am getting below errors when I build the application. I think it is because of JQuery code (specially window.something) embedded in Angular.

Does anyone know how to achieve this using pure Angular. No JQuery and No 3rd party url (like https://www.whatismyip.com and so many other websites).

Code:

    ngOnInit() {
        var self = this;
        var localIp1 = ""; 
        $(document).ready(function(){
            window.RTCPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection;  
            var pc = new RTCPeerConnection({iceServers:[]}), 
            noop = function(){}; 

            pc.createDataChannel("");
            pc.createOffer(pc.setLocalDescription.bind(pc), noop);   
            pc.onicecandidate = function(ice){
                if(!ice || !ice.candidate || !ice.candidate.candidate)  return;

                var localIp = /([0-9]{1,3}(\.[0-9]{1,3}){3}|[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7})/.exec(ice.candidate.candidate)[1];
               // this.localIpAddress = myIP;
                localIp = localIp.replace(/\./g, '-');
                sessionStorage.setItem("LOCAL_IP", localIp);
                $.ajax({ 
                    type: "GET",
                    dataType: "json",
                    url: "http://localhost:8080/api/setLocalIpAddress/" + localIp,
                    success: function(data){        
                      console.log(data);
                    }
                 });
            };
        });
        this.localIp = sessionStorage.getItem("LOCAL_IP");
}

Error:

ERROR in src/app/selectline/select-line.component.ts(35,20): error TS2339: Property 'RTCPeerConnection' does not exist on type 'Window'.
src/app/selectline/select-line.component.ts(35,47): error TS2339: Property 'RTCPeerConnection' does not exist on type 'Window'.
src/app/selectline/select-line.component.ts(35,75): error TS2339: Property 'mozRTCPeerConnection' does not exist on type 'Window'.
src/app/selectline/select-line.component.ts(35,106): error TS2339: Property 'webkitRTCPeerConnection' does not exist on type 'Window'.
src/app/selectline/select-line.component.ts(39,16): error TS2339: Property 'createDataChannel' does not exist on type 'RTCPeerConnection'.

Thanks in Advance!!

Upvotes: 1

Views: 7267

Answers (2)

Prasad Patil
Prasad Patil

Reputation: 3

The sample on https://stackblitz.com/edit/angular-get-local-ip mentioned in the above answer was not working for me.

I have updated the lines in the sample

pc.createDataChannel(''); 

to

pc.createDataChannel("rtc");

Also, I updated the iceServers: [{ urls: "stun:stun.l.google.com:19302" }]

Upvotes: 0

Daniel W Strimpel
Daniel W Strimpel

Reputation: 8470

I was able to modify what you have above and create an example StackBlitz that does not use jQuery or external libraries. You can follow that link to see the code running.

As mentioned in my comment above, you will need to make use of the module augmentation documentation on the TypeScript handbook in order to do this. To augment the window object to recognize the global properties that you are accessing, I added the following code:

declare global {
  interface Window {
    RTCPeerConnection: RTCPeerConnection;
    mozRTCPeerConnection: RTCPeerConnection;
    webkitRTCPeerConnection: RTCPeerConnection;
  }
}

It seems that the current version of the spec for the RTCPeerConnection has changed versus the example that you were using in the code above. Modifying that to conform to the current spec, I ended up with the following code:

import { Component, NgZone } from '@angular/core';

declare global {
  interface Window {
    RTCPeerConnection: RTCPeerConnection;
    mozRTCPeerConnection: RTCPeerConnection;
    webkitRTCPeerConnection: RTCPeerConnection;
  }
}

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  name = 'Angular';
  localIp = sessionStorage.getItem('LOCAL_IP');

  private ipRegex = new RegExp(/([0-9]{1,3}(\.[0-9]{1,3}){3}|[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7})/);

  constructor (private zone: NgZone) {
  }

  ngOnInit() {
    this.determineLocalIp();
  }

  private determineLocalIp() {
    window.RTCPeerConnection = this.getRTCPeerConnection();

    const pc = new RTCPeerConnection({ iceServers: [] });
    pc.createDataChannel('');
    pc.createOffer().then(pc.setLocalDescription.bind(pc));

    pc.onicecandidate = (ice) => {
      this.zone.run(() => {
        if (!ice || !ice.candidate || !ice.candidate.candidate) {
          return;
        }

        this.localIp = this.ipRegex.exec(ice.candidate.candidate)[1];
        sessionStorage.setItem('LOCAL_IP', this.localIp);

        pc.onicecandidate = () => {};
        pc.close();
      });
    };
  }

  private getRTCPeerConnection() {
    return window.RTCPeerConnection ||
      window.mozRTCPeerConnection ||
      window.webkitRTCPeerConnection;
  }
}

As a note, the code that is executed within the onicecandidate method will run outside of the Angular zone, so that will not tell Angular to update the UI when properties on your component change within that code. In order to let Angular be aware of the changes, you need to get a reference to the Angular zone and run the code within it. This is accomplished with the this.zone.run(() => { ... }); syntax. Here is a good blog about zones in Angular if you would like to learn more about that.

Upvotes: 1

Related Questions