• 前端获取ip地址判断国家请求不同baseUrl


    项目背景

    项目新需求:根据ip地址区分出国内外上网,axios 使用不同的baseurl,上传阿里oss不同bucket

    获取ip地址

    一、使用js自己获取

    使用 RTCPeerConnection.setLocalDescription()

    WebRTC API

    pc端没问题,移动端不好使

       //获取用户本地ip的方法
       export function getIPs(callback){
        var ip_dups = {};
        var RTCPeerConnection = window.RTCPeerConnection
          || window.mozRTCPeerConnection
          || window.webkitRTCPeerConnection;
        var useWebKit = !!window.webkitRTCPeerConnection;
        var mediaConstraints = {
          optional: [{ RtpDataChannels: true }]
        };
        // 这里就是需要的ICEServer了
        var servers = {
          iceServers: [
            { urls: "stun:stun.services.mozilla.com" },
            { urls: "stun:stun.l.google.com:19302" },
          ], 
        };
    
        var pc = new RTCPeerConnection(servers, mediaConstraints);
        function handleCandidate(candidate) {
          var ip_regex = /([0-9]{1,3}(\.[0-9]{1,3}){3}|[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7})/
          var hasIp = ip_regex.exec(candidate)
          if (hasIp) {
            var ip_addr = ip_regex.exec(candidate)[1];
            if (ip_dups[ip_addr] === undefined)
              callback(ip_addr);
              
            ip_dups[ip_addr] = true;
          }
        }
        // 网络协商的过程
        pc.onicecandidate = function (ice) {
          if (ice.candidate) {
            handleCandidate(ice.candidate.candidate);
          }
        };
        pc.createDataChannel("");
        //创建一个SDP(session description protocol)会话描述协议 是一个纯文本信息 包含了媒体和网络协商的信息
        // pc.createOffer().then((offer) => pc.setLocalDescription(offer));
        pc.createOffer().then((offer) => pc.setLocalDescription(new RTCSessionDescription(offer)));
        // pc.createOffer(function (result) {
        //   pc.setLocalDescription(result, function () { }, function () { });
        // }, function () { });
        setTimeout(function () {
          if(pc.localDescription){
            var lines = pc.localDescription.sdp.split('\n');
            lines.forEach(function (line) {
              if (line.indexOf('a=candidate:') === 0)
                handleCandidate(line);
            });
          }else{
            console.log('未获取到ip信息')
            // 未获取到信息就写死,360浏览器pc.localDescription=null
            callback('125.211.30.71');
          }
          
        }, 1000);
      }
    
    
      
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    // 使用方法
    getIPs(async (ip) => {
          console.log('获取到的ip', ip)
    })
    
    • 1
    • 2
    • 3
    • 4

    二、使用现成api调用

    第一种方法不兼容移动端,所以只能使用三方api

     axios.get('https://ipv4.icanhazip.com/').then(async res=>{
    	let ip = res.data
    	console.log('ipv4', ip)
    }
    • 1
    • 2
    • 3
    • 4

    更多的三方ip获取请参考这篇文章

    axios 设置:异步获取数据后导出

    本想根据三方接口请求获取ip后,再请求接口获取国家(后端写好的接口),以此设置baseUrl后导出,供axios使用;
    想的很美/(ㄒoㄒ)/~~,然而导出的常量或对象并不支持异步
    举个例子(以下代码是错误示范) :

    // config.js
    let config = {
    	development:{
    		baseurl:''
    	},
    	release:{
    		baseurl:''
    	}
    }
    function handleReq(){
    	axios.post('/getCountry').then(res=>{
    		if(res.code==0){
    			config[import.meta.env.MODE].baseurl = res.country == 'cn' ? 'http://cn-api.com':'http://us-api.com'
    			console.log('config', config[import.meta.env.MODE].baseurl) // *
    			// import.meta.env.MODE 是vite获取环境变量的写法
    		}
    	})
    }
    handleReq()
    export const baseurl = config[import.meta.env.MODE].baseurl
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    // axios.js中使用
    import { baseurl } from '@/config'
    axios.defaults.baseURL = baseurl 
    console.log('baseurl:', baseurl)  // *
    
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述

    所以只能改变策略,把异步请求回来的状态存储在localStorage里,然后在使用的地方,获取localStorage里的状态,从而进行判断

    // config.js
    export const baseurl_cn = 'http://cn-api.com'
    export const baseurl_us = 'http://us-api.com'
    
    function handleReq(){
    	axios.post('/getCountry').then(res=>{
    		if(res.code==0){
    			localstorage.setItem('country', res.country)
    		}
    	})
    }
    handleReq()
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    // axios.js
    import { baseurl_cn, baseurl_us } from '@/config'
    let country = localStorage.getItem('country')
    axios.defaults.baseURL = country == 'cn' ? baseurl_cn : baseurl_us 
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
  • 相关阅读:
    Docker 搭建 Gitlab(新手村试炼版)
    Fiddler抓包工具的使用
    Android Studio版本升级后的问题 gradle降级、jdk升级
    手把手带你用香橙派AIpro开发AI推理应用
    R语言caret机器学习(三):数据预处理下集
    协议的定义
    VUE+element可以为空不为空时只能为(正整数和0)的验证
    电子眼与无人机在城市安防中的协同应用研究
    dvwa靶场通关(十二)
    Helm & Kubernetes Offline Deploy Rancher v2.7.5 Demo (helm 离线部署 rancher 实践)
  • 原文地址:https://blog.csdn.net/thingir/article/details/127988882