Skip to content

Commit

Permalink
Autodetect client location if we didn't passed it
Browse files Browse the repository at this point in the history
  • Loading branch information
soffokl committed Nov 5, 2021
1 parent 2eee180 commit 55146a8
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 9 deletions.
16 changes: 9 additions & 7 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,24 @@ import (

"github.com/gin-gonic/gin"
"github.com/go-redis/redis/v8"
"github.com/rs/zerolog/log"
swaggerFiles "github.com/swaggo/files"
ginSwagger "github.com/swaggo/gin-swagger"
_ "go.uber.org/automaxprocs"

"github.com/mysteriumnetwork/discovery/config"
"github.com/mysteriumnetwork/discovery/db"
_ "github.com/mysteriumnetwork/discovery/docs"
"github.com/mysteriumnetwork/discovery/health"
"github.com/mysteriumnetwork/discovery/listener"
"github.com/mysteriumnetwork/discovery/location"
"github.com/mysteriumnetwork/discovery/price"
"github.com/mysteriumnetwork/discovery/price/pricing"
"github.com/mysteriumnetwork/discovery/proposal"
"github.com/mysteriumnetwork/discovery/quality"
"github.com/mysteriumnetwork/discovery/quality/oracleapi"
"github.com/mysteriumnetwork/discovery/tags"
mlog "github.com/mysteriumnetwork/logger"
"github.com/rs/zerolog/log"
swaggerFiles "github.com/swaggo/files"
ginSwagger "github.com/swaggo/gin-swagger"

// unconfuse the number of cores go can use in k8s
_ "go.uber.org/automaxprocs"
)

var Version = "<dev>"
Expand Down Expand Up @@ -83,8 +83,10 @@ func main() {
go proposalService.StartExpirationJob()
defer proposalService.Shutdown()

locationProvider := location.NewLocationProvider(cfg.LocationAddress.String(), cfg.LocationUser, cfg.LocationPass)

v3 := r.Group("/api/v3")
proposal.NewAPI(proposalService, proposalRepo).RegisterRoutes(v3)
proposal.NewAPI(proposalService, proposalRepo, locationProvider).RegisterRoutes(v3)
health.NewAPI(rdb, database).RegisterRoutes(v3)

cfger := pricing.NewConfigProviderDB(rdb)
Expand Down
13 changes: 13 additions & 0 deletions config/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ type Options struct {
RedisPass string
RedisDB int
BadgerAddress url.URL
LocationAddress url.URL
LocationUser string
LocationPass string
}

func Read() (*Options, error) {
Expand Down Expand Up @@ -48,6 +51,13 @@ func Read() (*Options, error) {
return nil, err
}

locationUser := OptionalEnv("LOCATION_USER", "")
locationPass := OptionalEnv("LOCATION_PASS", "")
locationAddress, err := RequiredEnvURL("LOCATION_ADDRESS")
if err != nil {
return nil, err
}

redisPass := OptionalEnv("REDIS_PASS", "")

redisDBint := 0
Expand All @@ -68,6 +78,9 @@ func Read() (*Options, error) {
RedisPass: redisPass,
RedisDB: redisDBint,
BadgerAddress: *badgerAddress,
LocationAddress: *locationAddress,
LocationUser: locationUser,
LocationPass: locationPass,
}, nil
}

Expand Down
59 changes: 59 additions & 0 deletions location/location.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright (c) 2021 BlockDev AG
// This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree.

package location

import (
"context"
"encoding/json"
"fmt"
"net/http"
"time"
)

type locationProvider struct {
address string
user string
pass string
}

// NewLocationProvider create a new location provider instance.
func NewLocationProvider(address, user, pass string) *locationProvider {
return &locationProvider{
address: address,
user: user,
pass: pass,
}
}

// Country returns a country code for the provided IP-address.
func (lp *locationProvider) Country(ip string) (countryCode string, err error) {
url := fmt.Sprintf("%s/%s", lp.address, ip)

req, err := http.NewRequest("GET", url, nil)
req.SetBasicAuth(lp.user, lp.pass)

ctx, cancel := context.WithTimeout(req.Context(), 5*time.Second)
defer cancel()

req = req.WithContext(ctx)

resp, err := http.DefaultClient.Do(req)
if err != nil {
return "", err
}

defer resp.Body.Close()

var country struct {
Country string `json:"country"`
}

err = json.NewDecoder(resp.Body).Decode(&country)
if err != nil {
return "", err
}

return country.Country, nil
}
22 changes: 20 additions & 2 deletions proposal/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,19 @@ import (
type API struct {
service *Service
repository *Repository
location locationProvider
}

func NewAPI(service *Service, repository *Repository) *API {
return &API{service: service, repository: repository}
type locationProvider interface {
Country(ip string) (countryCode string, err error)
}

func NewAPI(service *Service, repository *Repository, location locationProvider) *API {
return &API{
service: service,
repository: repository,
location: location,
}
}

// Proposals list proposals.
Expand Down Expand Up @@ -52,6 +61,15 @@ func (a *API) Proposals(c *gin.Context) {
tags: c.Query("tags"),
}

if len(opts.from) != 2 {
country, err := a.location.Country(c.ClientIP())
if err != nil {
log.Warn().Err(err).Msg("Failed to autodetect client country")
} else {
opts.from = country
}
}

pids, _ := c.GetQueryArray("provider_id")
opts.providerIDS = pids

Expand Down

0 comments on commit 55146a8

Please sign in to comment.