Golang实现RDAP到gRPC的协议转换
Golang实现RDAP到gRPC的协议转换 大家好, 希望大家都一切顺利。 有人能帮我将 github.com/openrdap/rdap 代码转换为 gRPC 吗? 我目前使用这段代码通过 RDAP 从网络中提取数据,现在我想做同样的事情,但使用 gRPC,但我对如何开始使用 gRPC 没有任何头绪。 请给我一个关于如何将此 RDAP 代码转换为 gRPC 的演示。
package main
import (
"encoding/json"
"errors"
"io"
"log"
"net"
"net/http"
"os"
"strings"
"github.com/openrdap/rdap"
)
const IPSET_FILE = "output.json"
var blockips BlockIP
// var blockips = NewBlockIP(IPSET_INTVAL)
type AnaylsisResult map[string]bool
type BlockIP map[string][]string
type NetworkInfo struct {
Ip string `json:"ip"`
Hostname string `json:"hostname"`
Reverse string `json:"reverse"`
}
//ArinInfo data
type ArinInfo struct {
Name string `json:"name,omitempty"`
Handle string `json:"handle,omitempty"`
Parent string `json:"parent,omitempty"`
Type string `json:"type,omitempty"`
Range string `json:"range,omitempty"`
Cidr string `json:"cidr,omitempty"`
Status []string `json:"status,omitempty"`
Registration string `json:"registration,omitempty"`
Updated string `json:"updated,omitempty"`
}
//OrgnizationInfo data
type OrgnizationInfo struct {
Name string `json:"name,omitempty"`
Handle string `json:"handle,omitempty"`
Street string `json:"street,omitempty"`
City string `json:"city,omitempty"`
Province string `json:"province,omitempty"`
Postal string `json:"postal,omitempty"`
Country string `json:"country,omitempty"`
Registration string `json:"registration,omitempty"`
Updated string `json:"updated,omitempty"`
}
//ContactInfo data
type ContactInfo struct {
Name string `json:"name,omitempty"`
Handle string `json:"handle,omitempty"`
Company string `json:"company,omitempty"`
Street string `json:"street,omitempty"`
City string `json:"city,omitempty"`
Province string `json:"province,omitempty"`
Postal string `json:"postal,omitempty"`
Country string `json:"country,omitempty"`
Registration string `json:"registration,omitempty"`
Updated string `json:"updated,omitempty"`
Phone string `json:"phone,omitempty"`
Email string `json:"email,omitempty"`
}
//Response data
type Response struct {
Network NetworkInfo `json:"network,omitempty"`
Arin ArinInfo `json:"arin,omitempty"`
Orgnization OrgnizationInfo `json:"orgnization,omitempty"`
Contact ContactInfo `json:"contact,omitempty"`
Abuse ContactInfo `json:"abuse,omitempty"`
Anaylsis AnaylsisResult `json:"anaylsis,omitempty"`
}
func init() {
log.SetFlags(log.Lshortfile)
// init blockip datasource
// open blockip file
f, e := os.OpenFile(IPSET_FILE, os.O_RDONLY, 0666)
if e != nil {
log.Println(e)
return
}
blockips = NewBlockIP(f)
}
func main() {
//router
r := http.NewServeMux()
//routes
r.HandleFunc("/", reverseIpHandler)
r.HandleFunc("/ip/", ipHandler)
//http server
http.ListenAndServe(":8080", r)
}
func NewResponse(ip string) (rsp *Response) {
rsp = new(Response)
// process
rsp.parseNetWork(ip)
rsp.Parse(ip)
return
}
func (rsp *Response) parseNetWork(ip string) {
// set default value
rsp.Network = NetworkInfo{}
rsp.Network.Ip = ip
host, err := net.LookupAddr(ip)
if err != nil || len(host) == 0 {
log.Println(err, ip)
return
}
revIP, err := net.LookupIP(host[0])
if err != nil || len(revIP) == 0 {
return
}
// update network value
rsp.Network.Hostname = host[0]
rsp.Network.Reverse = revIP[0].String()
}
func (rsp *Response) Parse(ip string) {
// read whois information
c := &rdap.Client{}
rs, e := c.QueryIP(ip)
if e != nil {
log.Println(e)
return
}
// arinfo
rsp.Arin.Name = rs.Name
rsp.Arin.Cidr = rs.Handle
rsp.Arin.Handle = rs.Handle
rsp.Arin.Parent = rs.ParentHandle
rsp.Arin.Range = rs.StartAddress + "-" + rs.EndAddress
rsp.Arin.Type = rs.Type
// update registration and updated
for _, v := range rs.Events {
switch v.Action {
case "registration":
rsp.Arin.Registration = v.Date
case "last changed":
rsp.Arin.Updated = v.Date
}
}
for _, ett := range rs.Entities {
if ett.VCard == nil {
continue
}
switch {
// orgnization infomation
case isExists(ett.Roles, "registrant"):
rsp.Orgnization.Country = ett.VCard.Country()
rsp.Orgnization.City = ett.VCard.ExtendedAddress()
rsp.Orgnization.Handle = ett.Handle
rsp.Orgnization.Name = ett.VCard.Name()
rsp.Orgnization.Postal = ett.VCard.PostalCode()
rsp.Orgnization.Province = ett.VCard.Region()
for _, v := range ett.Events {
switch v.Action {
case "registration":
rsp.Orgnization.Registration = v.Date
case "last changed":
rsp.Orgnization.Updated = v.Date
}
}
rsp.Orgnization.Street = ett.VCard.StreetAddress()
// abuse information
case isExists(ett.Roles, "abuse"):
rsp.Abuse.Country = ett.VCard.Country()
rsp.Abuse.City = ett.VCard.ExtendedAddress()
rsp.Abuse.Email = ett.VCard.Email()
rsp.Abuse.Handle = ett.Handle
rsp.Abuse.Name = ett.VCard.Name()
rsp.Abuse.Phone = ett.VCard.Tel()
rsp.Abuse.Postal = ett.VCard.PostalCode()
rsp.Abuse.Province = ett.VCard.Region()
for _, v := range ett.Events {
switch v.Action {
case "registration":
rsp.Abuse.Registration = v.Date
case "last changed":
rsp.Abuse.Updated = v.Date
}
}
rsp.Abuse.Street = ett.VCard.StreetAddress()
fallthrough
// contact
case isExists(ett.Roles, "administrative"):
rsp.Contact.City = ett.VCard.ExtendedAddress()
rsp.Contact.Country = ett.VCard.Country()
rsp.Contact.Email = ett.VCard.Email()
rsp.Contact.Handle = ett.Handle
rsp.Contact.Name = ett.VCard.Name()
rsp.Contact.Phone = ett.VCard.Tel()
rsp.Contact.Postal = ett.VCard.PostalCode()
rsp.Contact.Province = ett.VCard.Region()
for _, v := range ett.Events {
switch v.Action {
case "registration":
rsp.Contact.Registration = v.Date
case "last changed":
rsp.Contact.Updated = v.Date
}
}
rsp.Contact.Street = ett.VCard.StreetAddress()
}
}
}
func isExists(src []string, item string) (r bool) {
for _, v := range src {
if v == item {
r = true
break
}
}
return
}
func getContent(ct string) (r string) {
idx := strings.Index(ct, ":")
r = strings.Trim(ct[idx+1:], " ")
r = strings.Trim(r, "\n")
return
}
func reverseIpHandler(w http.ResponseWriter, r *http.Request) {
//reverse ip
rip := getReverseIp(r)
rsp := NewResponse(rip)
e := json.NewEncoder(w).Encode(rsp)
if e != nil {
log.Println(e)
}
}
func getReverseIp(r *http.Request) string {
ff := r.Header.Get("CF-Connecting-IP")
if ff != "" {
return ff
}
//fall back to request's remote address
ip := getIp(r.RemoteAddr)
return ip
}
func getIp(remoteAddress string) string {
i := strings.Index(remoteAddress, ":")
return remoteAddress[0:i]
}
func ipHandler(w http.ResponseWriter, r *http.Request) {
//ip
ip, err := getIpParam(r)
if err != nil {
log.Println(err)
http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
return
}
rsp := NewResponse(ip)
// anaylsis
rsp.Anaylsis = blockips.Anaylsis(ip)
e := json.NewEncoder(w).Encode(rsp)
if e != nil {
log.Println(e)
}
}
func getIpParam(r *http.Request) (string, error) {
//url path: /ip/:ip
ip := r.URL.Path[4:]
i := strings.Index(ip, "/")
if i == -1 {
return ip, nil
} else {
return "", errors.New("Failed to get ip parameter!")
}
}
func NewBlockIP(f io.Reader) (bip BlockIP) {
bip = make(BlockIP)
bip.load(f)
return
}
func (bip *BlockIP) load(f io.Reader) {
dc := json.NewDecoder(f)
e := dc.Decode(bip)
if e != nil {
log.Println(e)
return
}
}
func (bip BlockIP) Anaylsis(ip string) (rs AnaylsisResult) {
rs = make(AnaylsisResult)
for k, v := range bip {
// detect if ip in v
rs[k] = false
for _, va := range v {
if va == ip {
rs[k] = true
break
}
// if v contains "/" in the last 3 pst
if strings.Contains(va, "/") {
if ipinet(ip, va) {
rs[k] = true
break
}
va = va[:len(va)-3]
}
// compare the ip value
// when va greate than ip then break
ipi, e := IPString2Long(ip)
if e != nil {
log.Println(ip, e)
}
ipv, e := IPString2Long(va)
if e != nil {
log.Println(va, e)
}
// log.Println(ipi, ipv, va)
if ipv > ipi {
break
}
}
}
return
}
func ipinet(ip string, cidr string) (r bool) {
ipx, subnet, _ := net.ParseCIDR(cidr)
ipa := net.ParseIP(ip)
// if netip eq ip then check ip existing
if subnet.IP.Equal(ipx) {
r = subnet.Contains(ipa)
return
}
r = ipa.Equal(ipx)
return
}
func IPString2Long(ip string) (uint, error) {
b := net.ParseIP(ip).To4()
if b == nil {
return 0, errors.New("invalid ipv4 format")
}
return uint(b[3]) | uint(b[2])<<8 | uint(b[1])<<16 | uint(b[0])<<24, nil
}
更多关于Golang实现RDAP到gRPC的协议转换的实战教程也可以访问 https://www.itying.com/category-94-b0.html
好的,明白了。
好的,谢谢你的回答,兄弟。
更多关于Golang实现RDAP到gRPC的协议转换的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
我正在抓取领英数据,这段代码是抓取项目的一部分。
从网络中提取数据
这非常模糊。什么样的数据?从什么网络?
@lutzhorn 兄弟,我能在 gRPC 场景下转换整个代码吗?这只是一个简单的 REST API 代码,用于保存被阻止的 IP 地址并从这些 IP 中提取数据。我可以用其他方式实现吗?
你的问题存在一些问题。
- 本论坛可以自动格式化 Go 代码。请选中你的所有代码,然后点击编辑窗口顶部的
</>按钮。 - 如果你只是在这里倾倒你的完整代码,而不添加任何关于代码功能、实现方式以及你希望在转换为 gRPC 后实现什么目标的解释,你将不会得到太多帮助。
func main() {
fmt.Println("hello world")
}
感谢您的指导。实际上,我正在使用这段代码通过RDAP从网络中提取数据。现在我想做同样的事情,但使用gRPC,不过我对如何开始使用gRPC毫无头绪。 如果您能帮忙,请不吝赐教。
根据您的代码来看,RDAP 用于读取 IP 的 WHOIS 信息。
// read whois information
c := &rdap.Client{}
rs, e := c.QueryIP(ip)
// use data from `rs` ...
gRPC 与 WHOIS 无关。您无法用 gRPC 替换 RDAP。
以下是使用gRPC实现RDAP协议转换的完整示例:
1. 首先定义protobuf协议文件 rdap.proto:
syntax = "proto3";
package rdap;
option go_package = "./rdappb";
service RdapService {
rpc GetIPInfo(IPRequest) returns (Response) {}
rpc GetReverseIP(ReverseIPRequest) returns (Response) {}
}
message IPRequest {
string ip = 1;
}
message ReverseIPRequest {
// 空消息,从请求头获取IP
}
message NetworkInfo {
string ip = 1;
string hostname = 2;
string reverse = 3;
}
message ArinInfo {
string name = 1;
string handle = 2;
string parent = 3;
string type = 4;
string range = 5;
string cidr = 6;
repeated string status = 7;
string registration = 8;
string updated = 9;
}
message OrganizationInfo {
string name = 1;
string handle = 2;
string street = 3;
string city = 4;
string province = 5;
string postal = 6;
string country = 7;
string registration = 8;
string updated = 9;
}
message ContactInfo {
string name = 1;
string handle = 2;
string company = 3;
string street = 4;
string city = 5;
string province = 6;
string postal = 7;
string country = 8;
string registration = 9;
string updated = 10;
string phone = 11;
string email = 12;
}
message AnalysisResult {
map<string, bool> results = 1;
}
message Response {
NetworkInfo network = 1;
ArinInfo arin = 2;
OrganizationInfo organization = 3;
ContactInfo contact = 4;
ContactInfo abuse = 5;
AnalysisResult analysis = 6;
}
2. 生成gRPC代码:
protoc --go_out=. --go-grpc_out=. rdap.proto
3. gRPC服务器实现 server.go:
package main
import (
"context"
"encoding/json"
"errors"
"io"
"log"
"net"
"net/http"
"os"
"strings"
"github.com/openrdap/rdap"
"google.golang.org/grpc"
"google.golang.org/grpc/metadata"
pb "your_module_path/rdappb"
)
const IPSET_FILE = "output.json"
var blockips BlockIP
type AnaylsisResult map[string]bool
type BlockIP map[string][]string
type RdapServer struct {
pb.UnimplementedRdapServiceServer
}
func (s *RdapServer) GetIPInfo(ctx context.Context, req *pb.IPRequest) (*pb.Response, error) {
ip := req.GetIp()
if ip == "" {
return nil, errors.New("IP address is required")
}
rsp := NewResponse(ip)
return convertToGRPCResponse(rsp), nil
}
func (s *RdapServer) GetReverseIP(ctx context.Context, req *pb.ReverseIPRequest) (*pb.Response, error) {
md, ok := metadata.FromIncomingContext(ctx)
if !ok {
return nil, errors.New("no metadata found")
}
var ip string
if cfIPs := md.Get("cf-connecting-ip"); len(cfIPs) > 0 {
ip = cfIPs[0]
} else {
peer, ok := peer.FromContext(ctx)
if !ok {
return nil, errors.New("cannot get peer info")
}
addr := peer.Addr.String()
if idx := strings.Index(addr, ":"); idx != -1 {
ip = addr[:idx]
}
}
if ip == "" {
return nil, errors.New("cannot determine IP address")
}
rsp := NewResponse(ip)
return convertToGRPCResponse(rsp), nil
}
func convertToGRPCResponse(rsp *Response) *pb.Response {
grpcRsp := &pb.Response{
Network: &pb.NetworkInfo{
Ip: rsp.Network.Ip,
Hostname: rsp.Network.Hostname,
Reverse: rsp.Network.Reverse,
},
Arin: &pb.ArinInfo{
Name: rsp.Arin.Name,
Handle: rsp.Arin.Handle,
Parent: rsp.Arin.Parent,
Type: rsp.Arin.Type,
Range: rsp.Arin.Range,
Cidr: rsp.Arin.Cidr,
Status: rsp.Arin.Status,
Registration: rsp.Arin.Registration,
Updated: rsp.Arin.Updated,
},
Organization: &pb.OrganizationInfo{
Name: rsp.Orgnization.Name,
Handle: rsp.Orgnization.Handle,
Street: rsp.Orgnization.Street,
City: rsp.Orgnization.City,
Province: rsp.Orgnization.Province,
Postal: rsp.Orgnization.Postal,
Country: rsp.Orgnization.Country,
Registration: rsp.Orgnization.Registration,
Updated: rsp.Orgnization.Updated,
},
Contact: &pb.ContactInfo{
Name: rsp.Contact.Name,
Handle: rsp.Contact.Handle,
Company: rsp.Contact.Company,
Street: rsp.Contact.Street,
City: rsp.Contact.City,
Province: rsp.Contact.Province,
Postal: rsp.Contact.Postal,
Country: rsp.Contact.Country,
Registration: rsp.Contact.Registration,
Updated: rsp.Contact.Updated,
Phone: rsp.Contact.Phone,
Email: rsp.Contact.Email,
},
Abuse: &pb.ContactInfo{
Name: rsp.Abuse.Name,
Handle: rsp.Abuse.Handle,
Company: rsp.Abuse.Company,
Street: rsp.Abuse.Street,
City: rsp.Abuse.City,
Province: rsp.Abuse.Province,
Postal: rsp.Abuse.Postal,
Country: rsp.Abuse.Country,
Registration: rsp.Abuse.Registration,
Updated: rsp.Abuse.Updated,
Phone: rsp.Abuse.Phone,
Email: rsp.Abuse.Email,
},
Analysis: &pb.AnalysisResult{
Results: rsp.Anaylsis,
},
}
return grpcRsp
}
func main() {
initBlockIP()
lis, err := net.Listen("tcp", ":50051")
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
s := grpc.NewServer()
pb.RegisterRdapServiceServer(s, &RdapServer{})
log.Printf("gRPC server listening at %v", lis.Addr())
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}
func initBlockIP() {
f, err := os.OpenFile(IPSET_FILE, os.O_RDONLY, 0666)
if err != nil {
log.Println(err)
return
}
blockips = NewBlockIP(f)
}
// 保留原有的 Response 结构体和相关方法
type Response struct {
Network NetworkInfo `json:"network,omitempty"`
Arin ArinInfo `json:"arin,omitempty"`
Orgnization OrgnizationInfo `json:"orgnization,omitempty"`
Contact ContactInfo `json:"contact,omitempty"`
Abuse ContactInfo `json:"abuse,omitempty"`
Anaylsis AnaylsisResult `json:"anaylsis,omitempty"`
}
type NetworkInfo struct {
Ip string `json:"ip"`
Hostname string `json:"hostname"`
Reverse string `json:"reverse"`
}
type ArinInfo struct {
Name string `json:"name,omitempty"`
Handle string `json:"handle,omitempty"`
Parent string `json:"parent,omitempty"`
Type string `json:"type,omitempty"`
Range string `json:"range,omitempty"`
Cidr string `json:"cidr,omitempty"`
Status []string `json:"status,omitempty"`
Registration string `json:"registration,omitempty"`
Updated string `json:"updated,omitempty"`
}
type OrgnizationInfo struct {
Name string `json:"name,omitempty"`
Handle string `json:"handle,omitempty"`
Street string `json:"street,omitempty"`
City string `json:"city,omitempty"`
Province string `json:"province,omitempty"`
Postal string `json:"postal,omitempty"`
Country string `json:"country,omitempty"`
Registration string `json:"registration,omitempty"`
Updated string `json:"updated,omitempty"`
}
type ContactInfo struct {
Name string `json:"name,omitempty"`
Handle string `json:"handle,omitempty"`
Company string `json:"company,omitempty"`
Street string `json:"street,omitempty"`
City string `json:"city,omitempty"`
Province string `json:"province,omitempty"`
Postal string `json:"postal,omitempty"`
Country string `json:"country,omitempty"`
Registration string `json:"registration,omitempty"`
Updated string `json:"updated,omitempty"`
Phone string `json:"phone,omitempty"`
Email string `json:"email,omitempty"`
}
func NewResponse(ip string) *Response {
rsp := &Response{}
rsp.parseNetWork(ip)
rsp.Parse(ip)
rsp.Anaylsis = blockips.Anaylsis(ip)
return rsp
}
func (rsp *Response) parseNetWork(ip string) {
rsp.Network = NetworkInfo{}
rsp.Network.Ip = ip
host, err := net.LookupAddr(ip)
if err != nil || len(host) == 0 {
log.Println(err, ip)
return
}
revIP, err := net.LookupIP(host[0])
if err != nil || len(revIP) == 0 {
return
}
rsp.Network.Hostname = host[0]
rsp.Network.Reverse = revIP[0].String()
}
func (rsp *Response) Parse(ip string) {
c := &rdap.Client{}
rs, err := c.QueryIP(ip)
if err != nil {
log.Println(err)
return
}
rsp.Arin.Name = rs.Name
rsp.Arin.Cidr = rs.Handle
rsp.Arin.Handle = rs.Handle
rsp.Arin.Parent = rs.ParentHandle
rsp.Arin.Range = rs.StartAddress + "-" + rs.EndAddress
rsp.Arin.Type = rs.Type
for _, v := range rs.Events {
switch v.Action {
case "registration":
rsp.Arin.Registration = v.Date
case "last changed":
rsp.Arin.Updated = v.Date
}
}
for _, ett := range rs.Entities {
if ett.VCard == nil {
continue
}
switch {
case isExists(ett.Roles, "registrant"):
rsp.Orgnization.Country = ett.VCard.Country()
rsp.Orgnization.City = ett.VCard.ExtendedAddress()
rsp.Orgnization.Handle = ett.Handle
rsp.Orgnization.Name = ett.VCard.Name()
rsp.Orgnization.Postal = ett.VCard.PostalCode()
rsp.Orgnization.Province = ett.VCard.Region()
for _, v := range ett.Events {
switch v.Action {
case "registration":
rsp.Orgnization.Registration = v.Date
case "last changed":
rsp.Orgnization.Updated = v.Date
}
}
rsp.Orgnization.Street = ett.VCard.StreetAddress()
case isExists(ett.Roles, "abuse"):
rsp.Abuse.Country = ett.VCard.Country()
rsp.Abuse.City = ett.VCard.ExtendedAddress()
rsp.Abuse.Email = ett.VCard.Email()
rsp.Abuse.Handle = ett.Handle
rsp.Abuse.Name = ett.VCard.Name()
rsp.Abuse.Phone = ett.VCard.Tel()
rsp.Abuse.Postal = ett.VCard.PostalCode()
rsp.Abuse.Province = ett.VCard.Region()
for _, v := range ett.Events {
switch v.Action {
case "registration":
rsp.Abuse.Registration = v.Date
case "last changed":
rsp.Abuse.Updated = v.Date
}
}
rsp.Abuse.Street = ett.VCard.StreetAddress()
fallthrough
case isExists(ett.Roles, "administrative"):
rsp.Contact.City = ett.VCard.ExtendedAddress()
rsp.Contact.Country = ett.VCard.Country()
rsp.Contact.Email = ett.VCard.Email()
rsp.Contact.Handle = ett.Handle
rsp.Contact.Name = ett.VCard.Name()
rsp.Contact.Phone = ett.VCard.Tel()
rsp.Contact.Postal = ett.VCard.PostalCode()
rsp.Contact.Province = ett.VCard.Region()
for _, v := range ett.Events {
switch v.Action {
case "registration":
rsp.Contact.Registration = v.Date
case "last changed":
rsp.Contact.Updated = v.Date
}
}
rsp.Contact.Street = ett.VCard.StreetAddress()
}
}
}
func isExists(src []string, item string) bool {
for _, v := range src {
if v == item {
return true
}
}
return false
}
func NewBlockIP(f io.Reader) BlockIP {
bip := make(BlockIP)
dc := json.NewDecoder(f)
if err := dc.Decode(&bip); err != nil {
log.Println(err)
}
return bip
}
func (bip BlockIP) Anaylsis(ip string) AnaylsisResult {
rs := make(AnaylsisResult)
for k, v := range bip {
rs[k] = false
for _, va := range v {
if va == ip {
rs[k] = true
break
}
if strings.Contains(va, "/") {
if ipinet(ip, va) {
rs[k] = true
break
}
va = va[:len(va)-3]
}
ipi, e := IPString2Long(ip)
if e != nil {
log.Println(ip, e)
}
ipv, e := IPString2Long(va)
if e != nil {
log.Println(va, e)
}
if ipv > ipi {
break
}
}
}
return rs
}
func ipinet(ip string, cidr string) bool {
ipx, subnet, _ := net.ParseCIDR(cidr)
ipa := net.ParseIP(ip)
if subnet.IP.Equal(ipx) {
return subnet.Contains(ipa)
}
return ipa.Equal(ipx)
}
func IPString2Long(ip string) (uint, error) {
b := net.ParseIP(ip).To4()
if b == nil {
return 0, errors.New("invalid ipv4 format")
}
return uint(b[3]) | uint(b[2])<<8 | uint(b[1])<<16 | uint(b[0])<<24, nil
}
4. gRPC客户端示例 client.go:
package main
import (
"context"
"fmt"
"log"
"time"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
pb "your_module_path/rdappb"
)
func main() {
conn, err := grpc.Dial("localhost:50051",
grpc.WithTransportCredentials(insecure.NewCredentials()),
grpc.WithBlock(),
grpc.WithTimeout(5*time.Second))
if err != nil {
log.Fatalf("did not connect: %v", err)
}
defer conn.Close()
client := pb.NewRdapServiceClient(conn)
// 示例1: 查询特定IP
ctx1 := context.Background()
ipReq := &pb.IPRequest{Ip: "8.8.8.8"}
resp1, err := client.GetIPInfo(ctx1, ipReq)
if err != nil {
log.Fatalf("GetIPInfo failed: %v", err)
}
fmt.Printf("IP Info for %s:\n", ipReq.Ip)
fmt.Printf("Hostname: %s\n", resp1.Network.Hostname)
fmt.Printf("Organization: %s\n", resp1.Organization.Name)
// 示例2: 获取反向IP(需要设置metadata)
ctx2 := metadata.NewOutgoingContext(context.Background(),
metadata.Pairs("cf-connecting-ip", "8.8.4.4"))
reverseReq := &pb.ReverseIPRequest{}
resp2, err

