URL验证似乎已损坏

时间:2018-06-27 18:41:57

标签: validation url go

我正在尝试使用Go的标准库来验证URL。这就是我的代码当前的样子。

import (
    "fmt"
    "net/url"
)

func isValidURL(tocheck string) bool {
    _, err := url.ParseRequestURI(tocheck)
    return err == nil
}

func main() {
    fmt.Println(isValidURL("google.com"))      //returns false, expected true
    fmt.Println(isValidURL("www.google.com"))  //returns false, expected true
    fmt.Println(isValidURL("google"))          //returns false, expected false
    fmt.Println(isValidURL("/google"))         //returns true, expected false
}

尽管前两个示例为true,但所有三个示例均打印为false。然后,我尝试将https://附加到不以它们开头的URL的开头,但是随后,像https://aaaa这样的所有内容都被解析为有效。我该怎么做才能确保仅在URL有效时才返回true?

2 个答案:

答案 0 :(得分:5)

其中大多数是域名。 https://aaaa是有效的网址。 /google不是URL,但ParseRequestURI可以接受,因为它也接受绝对路径。

  

原始网址仅解释为绝对URI 或绝对路径

当您询问ParseRequestURI时,您是在要求对绝对URL或绝对路径进行严格的语法检查。绝对路径类似于/foo/barRFC 3986涵盖了什么是绝对URL,什么不是绝对URL。 URI的基本语法是这样。

URI         = scheme ":" hier-part [ "?" query ] [ "#" fragment ]

hier-part   = "//" authority path-abempty
            / path-absolute
            / path-rootless
            / path-empty

“绝对URL”表示path部分是绝对路径或为空,因此上面的path-abemptypath-absolutehttphttps网址只能是绝对网址。 foo:bar/baz是相对URL的示例。

这是一个例子。

  foo://example.com:8042/over/there?name=ferret#nose
  \_/   \______________/\_________/ \_________/ \__/
   |           |            |            |        |
scheme     authority       path        query   fragment
   |   _____________________|__
  / \ /                        \
  urn:example:animal:ferret:nose

google.com没有scheme,因此它不是URL。 https://aaaa有一个方案https和一个hier-part//aaaa,因此它是一个URL。它没有queryfragement,但它们是可选的。

显然,这有点宽泛。在现实世界中,您需要缩小要求。通常就像...

  1. 验证它是一个URL,您无法通过调用ParseRequestURI来实现,因为它也可以是绝对路径。
  2. 检查其是否有可接受的方案url.Scheme。这将丢弃绝对路径。
  3. 检查其具有有效的域名url.Host

以及您可能要执行的其他任何检查,以限制您认为有效的URL。

因此您的完整支票可能看起来像...

package main

import (
    "fmt"
    "net"
    "net/url"
    "errors"
)

func isValidURL(tocheck string) (bool, error) {
    // Check it's an Absolute URL or absolute path
    uri, err := url.ParseRequestURI(tocheck)
    if err != nil {
        return false, err
    }

    // Check it's an acceptable scheme
    switch uri.Scheme {
        case "http":
        case "https":
        default:
            return false, errors.New("Invalid scheme")
    }

    // Check it's a valid domain name
    _,err = net.LookupHost(uri.Host)
    if err != nil {
        return false, err
    }

    return true, nil
}

func main() {
    // False, no scheme
    fmt.Println(isValidURL("/google"))
    // True, good scheme, good domain
    fmt.Println(isValidURL("https://google.com"))
    // False, bad domain
    fmt.Println(isValidURL("http://halghalghlakdjfl.blarg"))
}

答案 1 :(得分:3)

您将域名与URL混淆了,域名只是URL的一部分。

有效的域示例为:www.google.comlocalhosta.b.c.a.google.com

为了使URL有效,方案/协议部分(通常为https://)必须存在,请参阅syntax at Wikipedia for an easy explanation

http://aaa是有效网址,其规则与http://localhost有效