Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F114226
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Size
5 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/lib/remote_ip/headers/forwarded.ex b/lib/remote_ip/headers/forwarded.ex
index 2e8388f..263362a 100644
--- a/lib/remote_ip/headers/forwarded.ex
+++ b/lib/remote_ip/headers/forwarded.ex
@@ -1,166 +1,166 @@
defmodule RemoteIp.Headers.Forwarded do
@moduledoc """
[RFC 7239](https://tools.ietf.org/html/rfc7239) compliant parser for
`Forwarded` headers.
"""
use Combine
@doc """
Given a `Forwarded` header's string value, parses out IP addresses from the
`for=` parameter.
## Examples
iex> RemoteIp.Headers.Forwarded.parse("for=1.2.3.4;by=2.3.4.5")
[{1, 2, 3, 4}]
iex> RemoteIp.Headers.Forwarded.parse("for=\\"[::1]\\", for=\\"[::2]\\"")
[{0, 0, 0, 0, 0, 0, 0, 1}, {0, 0, 0, 0, 0, 0, 0, 2}]
iex> RemoteIp.Headers.Forwarded.parse("invalid")
[]
"""
@type header :: String.t
@type ip :: :inet.ip_address
@spec parse(header) :: [ip]
def parse(header) when is_binary(header) do
- case Combine.parse(header, forwarded) do
+ case Combine.parse(header, forwarded()) do
[elements] -> Enum.flat_map(elements, &parse_forwarded_for/1)
_ -> []
end
end
defp parse_forwarded_for(pairs) do
case pairs |> fors do
[string] -> parse_ip(string)
_ -> [] # no `for=`s or multiple `for=`s
end
end
defp fors(pairs) do
for {key, val} <- pairs, String.downcase(key) == "for", do: val
end
defp parse_ip(string) do
- case Combine.parse(string, ip_address) do
+ case Combine.parse(string, ip_address()) do
[ip] -> [ip]
_ -> []
end
end
# https://tools.ietf.org/html/rfc7239#section-4
defp forwarded do
- sep_by(forwarded_element, comma) |> eof
+ sep_by(forwarded_element(), comma()) |> eof
end
defp forwarded_element do
- sep_by1(forwarded_pair, char(";"))
+ sep_by1(forwarded_pair(), char(";"))
end
defp forwarded_pair do
- pair = [token, ignore(char("=")), value]
+ pair = [token(), ignore(char("=")), value()]
pipe(pair, &List.to_tuple/1)
end
defp value do
- either(token, quoted_string)
+ either(token(), quoted_string())
end
# https://tools.ietf.org/html/rfc7230#section-3.2.6
defp token do
word_of(~r/[!#$%&'*+\-.^_`|~0-9a-zA-Z]/)
end
defp quoted_string do
- quoted(string_of(either(qdtext, quoted_pair)))
+ quoted(string_of(either(qdtext(), quoted_pair())))
end
defp quoted(parser) do
between(char("\""), parser, char("\""))
end
defp string_of(parser) do
map(many(parser), &Enum.join/1)
end
defp qdtext do
word_of(~r/[\t \x21\x23-\x5B\x5D-\x7E\x80-\xFF]/)
end
@quotable [?\t]
++ Enum.to_list(0x21..0x7E)
++ Enum.to_list(0x80..0xFF)
|> Enum.map(&<<&1::utf8>>)
defp quoted_pair do
- ignore(char("\\")) |> one_of(char, @quotable)
+ ignore(char("\\")) |> one_of(char(), @quotable)
end
# https://tools.ietf.org/html/rfc7230#section-7
defp comma do
- skip(many(either(space, tab)))
+ skip(many(either(space(), tab())))
|> char(",")
- |> skip(many(either(space, tab)))
+ |> skip(many(either(space(), tab())))
end
# https://tools.ietf.org/html/rfc7239#section-6
defp ip_address do
- node_name
+ node_name()
|> ignore(option(ignore(char(":")) |> node_port))
|> eof
end
defp node_name do
choice [
- ipv4_address,
- between(char("["), ipv6_address, char("]")),
+ ipv4_address(),
+ between(char("["), ipv6_address(), char("]")),
ignore(string("unknown")),
- ignore(obfuscated),
+ ignore(obfuscated()),
]
end
defp node_port(previous) do
- previous |> either(port, obfuscated)
+ previous |> either(port(), obfuscated())
end
defp port do
# Have to try to parse the wider integers first due to greediness. For
# example, the port "12345" would be matched by fixed_integer(1) and the
# remaining "2345" would cause a parse error for the eof in ip_address/0.
choice(Enum.map(5..1, &fixed_integer/1))
end
defp obfuscated do
word_of(~r/^_[a-zA-Z0-9._\-]+/)
end
# Could follow the ABNF described in
# https://tools.ietf.org/html/rfc3986#section-3.2.2, but prefer to lean on
# the existing :inet parser - we want its output anyway.
defp ipv4_address do
map(word_of(~r/[0-9.]/), fn string ->
case :inet.parse_ipv4strict_address(string |> to_char_list) do
{:ok, ip} -> ip
{:error, :einval} -> {:error, "Invalid IPv4 address"}
end
end)
end
defp ipv6_address do
map(word_of(~r/[0-9a-f:.]/i), fn string ->
case :inet.parse_ipv6strict_address(string |> to_char_list) do
{:ok, ip} -> ip
{:error, :einval} -> {:error, "Invalid IPv6 address"}
end
end)
end
end
diff --git a/mix.exs b/mix.exs
index 2f6cd82..b84797f 100644
--- a/mix.exs
+++ b/mix.exs
@@ -1,37 +1,37 @@
defmodule RemoteIp.Mixfile do
use Mix.Project
def project do
[app: :remote_ip,
version: "0.1.2",
elixir: "~> 1.3",
- package: package,
- description: description,
- deps: deps,
+ package: package(),
+ description: description(),
+ deps: deps(),
docs: [source_url: "https://github.com/ajvondrak/remote_ip"]]
end
def application do
[applications: [:plug],
included_applications: [:combine, :inet_cidr]]
end
defp description do
"A plug to overwrite the Conn's remote_ip based on headers such as " <>
"X-Forwarded-For."
end
defp package do
%{files: ~w[lib mix.exs README.md LICENSE],
maintainers: ["Alex Vondrak"],
licenses: ["MIT"],
links: %{"GitHub" => "https://github.com/ajvondrak/remote_ip"}}
end
defp deps do
[{:combine, "~> 0.9.2"},
{:plug, "~> 1.2"},
{:inet_cidr, "~> 1.0"},
{:ex_doc, "~> 0.14", only: :dev}]
end
end
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Tue, Nov 26, 12:01 AM (1 d, 8 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
40119
Default Alt Text
(5 KB)
Attached To
Mode
R27 remote_ip
Attached
Detach File
Event Timeline
Log In to Comment