Converting "RDAP" to "gRPC"

hello everyone,
hope you all are doing well,
can anyone help me to converting github.com/openrdap/rdap code to gRPC,
I am using this code for extracting data from network using RDAP, now I want to do same but using gRPC, but don’t have any idea to get start with gRPC.
just give me demo about how to covert this RDAP code to 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
}

As it is your question has some problems.

  • This forum can automatically format Go code. Select all your code and hit the </> button at the top of the edit window.
  • You won’t get much help if you just dump your complete code here without adding any explanation what the code does, how it does it, what you want it to do after the converstion to gRPC.

@lutzhorn thanks for guiding me, actually I am using this code for extracting data from network using RDAP, now I want to do same but using gRPC, but don’t have any idea to get start with gRPC.
Kindly help me if you can.

This is very vague. What kind of data? From what network?

I am scraping LinkedIn data,this code is a part of scraping Project

As far as I can tell from your code, RDAP is used to read the WHOIS information for an IP.

// read whois information
c := &rdap.Client{}
rs, e := c.QueryIP(ip)
// use data from `rs` ...

gRPC has nothing to do with WHOIS. You can’t replace RDAP with gRPC.

okey, Thanks for the answer bro

@lutzhorn bro,can I convert this whole code in gRPC scenario? It is just a simple rest api code to save the blockedIP and extract data from those IPs. Can I do this in other way?