package main
import (
"context"
"fmt"
"io"
"net"
"strings"
"net/url"
"strconv"
"github.com/fastly/compute-sdk-go/fsthttp"
"github.com/fastly/compute-sdk-go/configstore"
"github.com/fastly/compute-sdk-go/geo"
)
const BackendName = "http_me"
func main() {
fsthttp.ServeFunc(func(ctx context.Context, w fsthttp.ResponseWriter, r *fsthttp.Request) {
clientIP := net.ParseIP(r.RemoteAddr)
geo, err := geo.Lookup(clientIP)
if err != nil {returnErrorResponse(w, fsthttp.StatusInternalServerError, err)}
countryCode := geo.CountryCode
regionDefs, err := configstore.Open("region_defs")
if err != nil {returnErrorResponse(w, fsthttp.StatusInternalServerError, err)}
regionVal, err := regionDefs.Get(countryCode)
if err != nil {returnErrorResponse(w, fsthttp.StatusInternalServerError, err)}
fmt.Println("Country:", countryCode, ", Region:", regionVal)
if regionVal == "blocked" {
w.WriteHeader(fsthttp.StatusForbidden)
io.Copy(w, strings.NewReader("Sorry, our service is currently not available in your region."))
return
}
r.Header.Add("client-geo-country", countryCode)
r.Header.Add("client-geo-region", regionVal)
r.Header.Add("client-geo-continent", geo.ContinentCode)
fmt.Println("Continent:", geo.ContinentCode)
lat := geo.Latitude
long := geo.Longitude
geoCookie, err := r.Cookie("client-geo-latlng")
if err != nil {
if err == fsthttp.ErrNoCookie {
} else {
returnErrorResponse(w, fsthttp.StatusInternalServerError, err)
}
}
if len(geoCookie.String()) > 0 {
decodeGeoCookie, err := url.QueryUnescape(geoCookie.Value)
if err != nil {returnErrorResponse(w, fsthttp.StatusInternalServerError, err)}
decodeGeoCookie = strings.ReplaceAll(decodeGeoCookie, " ", "")
s := strings.Split(decodeGeoCookie, ",")
if lat, err = strconv.ParseFloat(s[0], 64); err != nil {returnErrorResponse(w, fsthttp.StatusInternalServerError, err)}
if long, err = strconv.ParseFloat(s[1], 64); err != nil {returnErrorResponse(w, fsthttp.StatusInternalServerError, err)}
}
r.Header.Add("client-geo-latlng", fmt.Sprintf("%.1f, %.1f", lat, long))
fmt.Println("Lat:", lat, "Lng:", long)
resp, err := r.Send(ctx, BackendName)
if err != nil {returnErrorResponse(w, fsthttp.StatusBadGateway, err)}
w.Header().Reset(resp.Header)
w.WriteHeader(resp.StatusCode)
io.Copy(w, resp.Body)
})
}
func returnErrorResponse(w fsthttp.ResponseWriter, code int, err error) {
w.WriteHeader(code)
fmt.Fprintln(w, err.Error())
return
}