PhoenixKit.Utils.IpAddress (phoenix_kit v2.22.0)

Copy Markdown View Source

Utilities for extracting and formatting IP addresses.

Supports both IPv4 and IPv6 addresses with proper error handling. Prevents Protocol.UndefinedError when working with IPv6 tuples.

Usage

Extract from LiveView socket:

ip = PhoenixKit.Utils.IpAddress.extract_from_socket(socket)

Extract from Plug.Conn:

ip = PhoenixKit.Utils.IpAddress.extract_from_conn(conn)

Extract from peer_data directly:

ip = PhoenixKit.Utils.IpAddress.extract_ip_address(%{address: {192, 168, 1, 1}})

Examples

iex> PhoenixKit.Utils.IpAddress.extract_ip_address(%{address: {192, 168, 1, 1}})
"192.168.1.1"

iex> PhoenixKit.Utils.IpAddress.extract_ip_address(%{address: {8193, 3512, 1, 0, 0, 0, 0, 1}})
"8193:3512:1:0:0:0:0:1"

iex> PhoenixKit.Utils.IpAddress.extract_ip_address(nil)
"unknown"

iex> PhoenixKit.Utils.IpAddress.extract_ip_address(%{})
"unknown"

Summary

Functions

The visitor's address as best a site behind a reverse proxy can tell.

The visitor's address as a LiveView socket knows it — or nil when the socket cannot tell.

Extracts IP address from Plug.Conn using get_peer_data.

Extracts IP address from Phoenix.LiveView socket using get_connect_info.

Extracts IP address from peer_data map.

Functions

client_address(conn)

@spec client_address(Plug.Conn.t()) :: String.t() | nil

The visitor's address as best a site behind a reverse proxy can tell.

extract_from_conn/1 answers the TCP peer, which behind nginx (or in a container) is the proxy's own address for every visitor. This one takes conn.remote_ip (which a host's RemoteIp plug already rewrites) and, when that is a loopback or private address — a proxy on the same box or the same network — the LAST entry of x-forwarded-for, the one that proxy appended (a visitor can send their own header; they cannot control what nginx appends after it), then x-real-ip. A public remote_ip is trusted as is. Returns nil when nothing is known.

iex> conn = %Plug.Conn{remote_ip: {127, 0, 0, 1}, req_headers: [{"x-forwarded-for", "9.9.9.9, 203.0.113.7"}]}
iex> PhoenixKit.Utils.IpAddress.client_address(conn)
"203.0.113.7"

client_address_from_socket(socket)

@spec client_address_from_socket(Phoenix.LiveView.Socket.t()) :: String.t() | nil

The visitor's address as a LiveView socket knows it — or nil when the socket cannot tell.

From the connect info the endpoint passes: a public :peer_data address is the visitor; a loopback or private one is a proxy, and only the forwarded address in :x_headers (x-forwarded-for, x-real-ip) names the visitor then. An endpoint that passes no :x_headers — core's installed endpoint passes :peer_data only — leaves a proxied socket with no answer, and nil is that answer: the caller must not treat the proxy as the visitor.

extract_from_conn(conn)

Extracts IP address from Plug.Conn using get_peer_data.

Convenience function that extracts peer_data and formats the IP.

Parameters

  • conn: Plug.Conn struct

Returns

  • IP address string or "unknown"

extract_from_socket(socket)

Extracts IP address from Phoenix.LiveView socket using get_connect_info.

Convenience function that extracts peer_data from socket and formats the IP.

Parameters

  • socket: Phoenix.LiveView.Socket struct

Returns

  • IP address string or "unknown"

extract_ip_address(arg1)

Extracts IP address from peer_data map.

Handles both IPv4 (4-tuple) and IPv6 (8-tuple) addresses. Returns "unknown" for nil, invalid, or missing data.

Parameters

  • peer_data: Map with :address key containing IP tuple, or nil

Returns

  • IPv4 as "a.b.c.d" string
  • IPv6 as "a:b:c:d:e:f:g:h" string
  • "unknown" for invalid or missing data