Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to validate url in elixir?

Tags:

elixir

I want to validate uris like:

http://vk.com
http://semantic-ui.com/collections/menu.html
https://translate.yandex.ru/?text=poll&lang=en-ru

and not

www.vk.com
abdeeej
http://vk

but haven't found either package of native code implementation for it.

How can I do that?

like image 864
asiniy Avatar asked Dec 06 '22 17:12

asiniy


2 Answers

All of those are technically valid URLs according to the spec so URI.parse/1 returns a %URI{} struct for all, but if you want to reject domains without a scheme and a dot in the host, you can do:

valid? = fn url ->
  uri = URI.parse(url)
  uri.scheme != nil && uri.host =~ "."
end

Test:

urls = [
  "http://vk.com",
  "http://semantic-ui.com/collections/menu.html",
  "https://translate.yandex.ru/?text=poll&lang=en-ru",
  "www.vk.com",
  "abdeeej",
  "http://vk"
]

urls |> Enum.map(valid?) |> IO.inspect

Output:

[true, true, true, false, false, false]
like image 103
Dogbert Avatar answered Dec 08 '22 07:12

Dogbert


This solution is more complete:

  def validate_url(changeset, field, opts \\ []) do
    validate_change(changeset, field, fn _, value ->
      case URI.parse(value) do
        val(%URI{scheme: nil}) ->
          "is missing a scheme (e.g. https)"

        %URI{host: nil} ->
          "is missing a host"

        %URI{host: host} ->
          case :inet.gethostbyname(Kernel.to_charlist(host)) do
            {:ok, _} -> nil
            {:error, _} -> "invalid host"
          end
      end
      |> case do
        error when is_binary(error) -> [{field, Keyword.get(opts, :message, error)}]
        _ -> []
      end
    end)
  end

Cribbed from https://gist.github.com/atomkirk/74b39b5b09c7d0f21763dd55b877f998

like image 32
Tronathan Avatar answered Dec 08 '22 06:12

Tronathan