Ryan Monreal
Ryan Monreal

Reputation: 597

Yesod get client Ipv4/Ipv6 address

I want to get the user IPv4 and/or IPv6 to use on GeoIp2.

How to get it?

----- EDIT --------

Like if the user access my site i want to check what is their IP Address once i get that I want to use the GeoIp2 to locate them.

the example below has a default IPv4 and IPv6 address:

{-# LANGUAGE OverloadedStrings #-}
import Data.GeoIP2
import Data.IP (IP(..))

main = do
  geodb <- openGeoDB "GeoLite2-City.mmdb"
  let ip = IPv4 "23.253.242.70"
  print $ (findGeoData geodb "en" ip :: Maybe GeoResult)

  let ip2 = IPv6 "2001:4800:7817:104:be76:4eff:fe04:f608"
  print $ (findGeoData geodb "en" ip2 :: Maybe GeoResult)

hope that helps

Upvotes: 2

Views: 521

Answers (1)

MaxGabriel
MaxGabriel

Reputation: 7707

This should work:

import Network.Wai (remoteHost) -- From the wai package
import Data.IP -- From the iproute package
import Network.Socket.Internal (SockAddr(..)) -- From the network package

sockAddrToIP :: SockAddr -> IP
sockAddrToIP sockAddr = case sockAddr of
    SockAddrInet _port hostAddress -> IPv4 $ fromHostAddress hostAddress
    SockAddrInet6 _port _flowInfo hostAddress6 _scopeID -> IPv6 $ fromHostAddress6 hostAddress6
    -- I don't know how to handle these, they might not apply to the web?
    SockAddrUnix _ -> error "Couldn't get IP address"
    SockAddrCan _ -> error "Couldn't get IP address"

getHomeR :: Handler Html
getHomeR = do
    host <- remoteHost <$> waiRequest
    let ip = sockAddrToIP host

    traceShowM $ "Remote host is " ++ show host
    traceShowM $ "IP is " ++ show ip
    -- (Finish implementing the handler here)

When I run this locally, I get:

"Remote host is 127.0.0.1:54575"
"IP is 127.0.0.1"

I actually don't know much about networking or IP addresses or anything, but the types line up and the code appears to be working. If someone could verify that SockAddrUnix and SockAddrCan can be ignored, that'd be good.

Upvotes: 4

Related Questions