package router import ( "fmt" "net" "net/http" "sort" "strings" "github.com/dcarrillo/whatismyip/models" "github.com/dcarrillo/whatismyip/service" "github.com/gin-gonic/gin" ) type geoDataFormatter struct { title string format func(*models.GeoRecord) string } type asnDataFormatter struct { title string format func(*models.ASNRecord) string } var geoOutput = map[string]geoDataFormatter{ "country": { title: "Country", format: func(record *models.GeoRecord) string { return record.Country.Names["en"] }, }, "country_code": { title: "Country Code", format: func(record *models.GeoRecord) string { return record.Country.ISOCode }, }, "city": { title: "City", format: func(record *models.GeoRecord) string { return record.City.Names["en"] }, }, "latitude": { title: "Latitude", format: func(record *models.GeoRecord) string { return fmt.Sprintf("%f", record.Location.Latitude) }, }, "longitude": { title: "Longitude", format: func(record *models.GeoRecord) string { return fmt.Sprintf("%f", record.Location.Longitude) }, }, "postal_code": { title: "Postal Code", format: func(record *models.GeoRecord) string { return record.Postal.Code }, }, "time_zone": { title: "Time Zone", format: func(record *models.GeoRecord) string { return record.Location.TimeZone }, }, } var asnOutput = map[string]asnDataFormatter{ "number": { title: "ASN Number", format: func(record *models.ASNRecord) string { return fmt.Sprintf("%d", record.AutonomousSystemNumber) }, }, "organization": { title: "ASN Organization", format: func(record *models.ASNRecord) string { return record.AutonomousSystemOrganization }, }, } func getGeoAsString(ctx *gin.Context) { field := strings.ToLower(ctx.Params.ByName("field")) ip := service.Geo{IP: net.ParseIP(ctx.ClientIP())} record := ip.LookUpCity() if field == "" { ctx.String(http.StatusOK, geoCityRecordToString(record)) } else if g, ok := geoOutput[field]; ok { ctx.String(http.StatusOK, g.format(record)) } else { ctx.String(http.StatusNotFound, http.StatusText(http.StatusNotFound)) } } func getASNAsString(ctx *gin.Context) { field := strings.ToLower(ctx.Params.ByName("field")) ip := service.Geo{IP: net.ParseIP(ctx.ClientIP())} record := ip.LookUpASN() if field == "" { ctx.String(http.StatusOK, geoASNRecordToString(record)) } else if g, ok := asnOutput[field]; ok { ctx.String(http.StatusOK, g.format(record)) } else { ctx.String(http.StatusNotFound, http.StatusText(http.StatusNotFound)) } } func geoCityRecordToString(record *models.GeoRecord) string { var output string keys := make([]string, 0, len(geoOutput)) for k := range geoOutput { keys = append(keys, k) } sort.Strings(keys) for _, k := range keys { output += fmt.Sprintf("%s: %v\n", geoOutput[k].title, geoOutput[k].format(record)) } return output } func geoASNRecordToString(record *models.ASNRecord) string { var output string keys := make([]string, 0, len(asnOutput)) for k := range asnOutput { keys = append(keys, k) } sort.Strings(keys) for _, k := range keys { output += fmt.Sprintf("%s: %v\n", asnOutput[k].title, asnOutput[k].format(record)) } return output }