如何验证 Elixir 中的 url?

问题描述 投票:0回答:3

我想验证 uri,例如:

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

但还没有找到它的任何本机代码实现包。

我该怎么做?

elixir
3个回答
14
投票

根据规范,所有这些在技术上都是有效的 URL,因此

URI.parse/1
为所有内容返回一个
%URI{}
结构,但如果您想拒绝没有
scheme
host
中没有点的域,您可以这样做:

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

测试:

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

输出:

[true, true, true, false, false, false]

4
投票

这个解决方案更完整:

  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

摘自https://gist.github.com/atomkirk/74b39b5b09c7d0f21763dd55b877f998


1
投票

自从 elixir

1.13.0
以来,验证 url 的方法是使用
URI.new/1
。它将获取 url 字符串,对其进行解析和验证,如果有效则返回
%{:ok, url}
,否则返回
%{:error, invalid_part_of_the_url}
表示无效 url。然后,可以使用结果
{:ok, struct}
的模式匹配在更细粒度的级别进行验证。有关更多信息,请在 IEx 中运行
h URI.new

注意:URI.new/1 在编码不良或未编码的 url 上失败,例如未编码且包含空格的 url,并返回错误。

# Without encoding, notice the space in the url
iex(1)> URI.new("https://testdomain/Teams/Odense Boldklub.png")
{:error, ":"}

# After encoding URL
iex(9)> URI.encode("https://testdomain/Teams/Odense Boldklub.png") |> URI.new
{:ok,
 %URI{
   scheme: "https",
   userinfo: nil,
   host: "testdomain",
   port: 443,
   path: "/Teams/Odense%20Boldklub.png",
   query: nil,
   fragment: nil
 }}

© www.soinside.com 2019 - 2024. All rights reserved.