一、示例
import requests
def GetPublicIP():
rsp = requests.get(f'https://ipinfo.io/ip')
return rsp.text
print(GetPublicIP())
def GetIPLocation(ip):
response = requests.get(f'https://ipinfo.io/{ip}/json')
data = response.json()
return data
ip = '8.8.8.8' # 这是Google的公共DNS IP
print(GetIPLocation(ip))
二、用户端调用
如果在用户端调用,如客户端,app等,可以直接使用 ipinfo.io 的接口。因为 ipinfo.io 提供了免费套餐,一个帐户可以有 50,000次每个月。
就算不注册帐户,也有一定次数的免费额度。
It’s also possible to use the API without authentication in a more limited capacity.
# With Basic Auth
$ curl -u 048a85f6a2a791: ipinfo.io
# With Bearer token
$ curl -H "Authorization: Bearer 048a85f6a2a791" ipinfo.io
# With token query parameter
$ curl ipinfo.io?token=048a85f6a2a791
三、服务端调用
可以注册一批帐户池,来扩大免费套餐的限制
// 管理 API 令牌的轮询及统计
type TokenManager struct {
tokens []string // 50,000 requests per-month for each token
callCounts map[string]int // 统计次数
index int // token 数组的索引
mu sync.Mutex
}
func NewTokenManager(tokens []string) *TokenManager {
callCounts := make(map[string]int)
for _, token := range tokens {
callCounts[token] = 0
}
return &TokenManager{
tokens: tokens,
index: 0,
callCounts: callCounts,
}
}
// 轮询获取下一个令牌并更新调用次数
func (tm *TokenManager) GetNextToken() string {
tm.mu.Lock()
defer tm.mu.Unlock()
token := tm.tokens[tm.index]
tm.callCounts[token]++
tm.index = (tm.index + 1) % len(tm.tokens)
return token
}
// GetCallCounts 返回每个令牌的调用次数
func (tm *TokenManager) GetCallCounts() map[string]int {
tm.mu.Lock()
defer tm.mu.Unlock()
counts := make(map[string]int)
for token, count := range tm.callCounts {
counts[token] = count
}
return counts
}
var gTokenMgr = NewTokenManager([]string{
"......8978....",
"......7e70....",
"......7745....",
"......f6a2....",
})
func GetIpLocation(ctx iris.Context) {
defer func() {
if r := recover(); r != nil {
util.GLog().Error(r)
}
}()
remoteIP := ctx.RemoteAddr() // 获取 IP
ip := strings.Split(remoteIP, ":")[0] // 去掉端口号
url := "https://ipinfo.io/" + ip + "/json?token=" + gTokenMgr.GetNextToken()
rsp, err := http.Get(url)
if err != nil {
msg := "Error fetching IP info"
util.GLog().Error(ip, msg)
ctx.StatusCode(http.StatusInternalServerError)
ctx.Text(msg)
return
}
defer rsp.Body.Close()
body, err := io.ReadAll(rsp.Body)
if err != nil {
msg := "Error reading response body"
util.GLog().Error(ip, msg)
ctx.StatusCode(http.StatusInternalServerError)
ctx.Text(msg)
return
}
util.GLog().Info(string(body))
ctx.Text(string(body))
}
func Dump(ctx iris.Context) {
callCounts := gTokenMgr.GetCallCounts()
ctx.JSON(callCounts)
}