66 lines
1.5 KiB
Go
66 lines
1.5 KiB
Go
|
package apiv1
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"errors"
|
||
|
"net/http"
|
||
|
|
||
|
"git.ar21.de/yolokube/country-geo-locations/internal/cache"
|
||
|
"git.ar21.de/yolokube/country-geo-locations/internal/database"
|
||
|
"git.ar21.de/yolokube/country-geo-locations/pkg/geoloc"
|
||
|
"github.com/go-chi/chi/v5"
|
||
|
)
|
||
|
|
||
|
type LocationHandler struct {
|
||
|
cache *cache.Cache
|
||
|
db *database.Database
|
||
|
}
|
||
|
|
||
|
func NewLocationHandler(cache *cache.Cache, db *database.Database) *LocationHandler {
|
||
|
return &LocationHandler{
|
||
|
cache: cache,
|
||
|
db: db,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (lh *LocationHandler) SearchIPHandlerFunc(w http.ResponseWriter, r *http.Request) {
|
||
|
ipinfo, ok := r.Context().Value(keyIPInfo).(*geoloc.IPInfo)
|
||
|
if !ok {
|
||
|
renderResponse(w, r, errRender(errors.New("could not get ipinfo object")))
|
||
|
return
|
||
|
}
|
||
|
|
||
|
renderResponse(w, r, newIPInfoResponse(ipinfo))
|
||
|
}
|
||
|
|
||
|
func (lh *LocationHandler) SearchIPHandler(next http.Handler) http.Handler {
|
||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||
|
var ipinfo *geoloc.IPInfo
|
||
|
|
||
|
if ipAddress := chi.URLParam(r, "ipAddress"); ipAddress != "" {
|
||
|
ipnetnum, err := geoloc.CalculateIPNum(ipAddress)
|
||
|
if err != nil {
|
||
|
renderResponse(w, r, errInvalidRequest(err))
|
||
|
return
|
||
|
}
|
||
|
|
||
|
newipnet, found := lh.cache.Get(ipnetnum)
|
||
|
if found {
|
||
|
ipnetnum = newipnet
|
||
|
}
|
||
|
|
||
|
ipinfo, err = lh.db.SearchIPNet(ipnetnum)
|
||
|
if err != nil {
|
||
|
renderResponse(w, r, errNotFound())
|
||
|
return
|
||
|
}
|
||
|
|
||
|
if !found {
|
||
|
lh.cache.Set(ipnetnum, ipinfo.IPNumFrom)
|
||
|
}
|
||
|
}
|
||
|
ctx := context.WithValue(r.Context(), keyIPInfo, ipinfo)
|
||
|
next.ServeHTTP(w, r.WithContext(ctx))
|
||
|
})
|
||
|
}
|