In this blog we’ll be developing a CLI tool, This tool will be designed to handle user input through command-line arguments and we will be using IPinfo.io API to gather comprehensive geolocation information .
This information will encompass crucial details such as the city, region, country, latitude, longitude, timezone, and more. feel free to refer the code:
github.com/sujay2306/IP-Lookup
Setting Up the Project
To start, let’s set up the basic project structure and install any necessary dependencies. We’ll use the Cobra library to create our CLI app.
- Create a new Go project directory and navigate into it:
mkdir IP-Lookup
cd IP-Lookup
mkdir IP-Lookup
cd IP-Lookup
2, Lets initialize a Go module:
go mod init IP-Lookup
3. We will be using cobra, so lets get it install
go get -u github.com/spf13/cobra@latest
4. Now, create a cmd
directory within your project directory to organize your CLI-related code:
mkdir cmd
Designing the Command Structure
Our CLI app will have a root command and a subcommand named “trace” that will allow us to trace IP addresses. Let’s set up the command structure using Cobra.
cmd/root.go
package cmd
import (
"github.com/spf13/cobra"
)
var (
rootCmd = &cobra.Command{
Use: "IPLookup-CLI",
Short: "A CLI for tracking IP",
Long: `IPLookup-cli is a CLI application which gives info about the user provided IP Address.`,
}
)
// Execute executes the root command.
func Execute() error {
return rootCmd.Execute()
}
cmd/trace.go
Now, let's dive into the heart of our CLI app – fetching and displaying IP geolocation data. We'll use the IPinfo.io API to retrieve the data. Here's how we do it:
package cmd
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"github.com/fatih/color"
"github.com/spf13/cobra"
)
// traceCmd represents the trace command
var traceCmd = &cobra.Command{
Use: "trace",
Short: "Trace the IP",
Long: `Trace the IP.`,
Run: func(cmd *cobra.Command, args []string) {
if len(args) > 0 {
for _, ip := range args {
showData(ip)
}
} else {
fmt.Println("Please provide IP to trace.")
}
},
}
func init() {
rootCmd.AddCommand(traceCmd)
}
// {
// "ip": "1.1.1.1",
// "hostname": "one.one.one.one",
// "anycast": true,
// "city": "Miami",
// "region": "Florida",
// "country": "US",
// "loc": "25.7867,-80.1800",
// "org": "AS13335 Cloudflare, Inc.",
// "postal": "33132",
// "timezone": "America/New_York",
// "readme": "https://ipinfo.io/missingauth"
// }
type Ip struct {
IP string `json:"ip"`
City string `json:"city"`
Region string `json:"region"`
Country string `json:"country"`
Loc string `json:"loc"`
Timezone string `json:"timezone"`
Postal string `json:"postal"`
}
func showData(ip string) {
url := "http://ipinfo.io/" + ip + "/geo"
responseByte := getData(url)
data := Ip{}
err := json.Unmarshal(responseByte, &data)
if err != nil {
log.Println("Unable to unmarshal the response")
}
c := color.New(color.FgRed).Add(color.Underline).Add(color.Bold)
c.Println("DATA FOUND :")
fmt.Printf("IP :%s\nCITY :%s\nREGION :%s\nCOUNTRY :%s\nLOCATION :%s\nTIMEZONE:%s\nPOSTAL :%s\n", data.IP, data.City, data.Region, data.Country, data.Loc, data.Timezone, data.Postal)
}
func getData(url string) []byte {
response, err := http.Get(url)
if err != nil {
log.Println("Unable to get the response")
}
responseByte, err := ioutil.ReadAll(response.Body)
if err != nil {
log.Println("Unable to read the response")
}
return responseByte
}
To make our CLI app more visually appealing, we’ll use the github.com/fatih/color
package to add color, underline, and bold formatting to our output.
Lets try out our application:
Hurray 🥂 ✨ , here we have the info about the given IP
Wrapping Up
Feel free to explore the complete code on github.com/sujay2306/IP-Lookup and make further enhancements. If you found this tutorial helpful, don’t hesitate to share your feedback and experiences in the comments.
Happy coding!