GO的URL合法性检查

打印 上一主题 下一主题

主题 893|帖子 893|积分 2679

原文连接:https://www.zhoubotong.site/post/67.html
Go 标准库的net/url包提供的两个函可以直接检查URL合法性,不需要手动去正则匹配校验。
  1. 下面可以直接使用ParseRequestURI()函数解析URL,当然这个只会验证url格式,至于域名是否存在或注册,不会检查的,举个例子:
复制代码
  1. package main
  2. import (
  3.     "fmt"
  4.     "net/url"
  5. )
  6. func main() {
  7.     url, err := url.ParseRequestURI("https://www.zhoubotong.site") // 注意这里必须带有http/https协议,
  8.     //否则会被认定非合法url,但是使用//www.zhoubotong.sit,被返回空,所以error哪里会被绕过,该示例代码不够严谨
  9.     if err != nil {
  10.         fmt.Println(err)
  11.         return
  12.     }
  13.     fmt.Println(url.Hostname())
  14. }
复制代码
  1. 输出:[www.zhoubotong.site](http://www.zhoubotong.site),下面整个错误的url:
复制代码
  1. func main() {
  2.     url, err := url.ParseRequestURI("www.zhoubotong.site") // www.zhoubotong.site" 或者zhoubotong.site"
  3.     if err != nil {
  4.         fmt.Println(err)
  5.         return
  6.     }
  7.     fmt.Println(url.Hostname())
  8. }
复制代码
  1. 输出:parse "www.zhoubotong.site": invalid URI for request,既然上面的代码不够严谨,如何改善呢?完整代码如下:
复制代码
  1. package main
  2. import (
  3.     "fmt"
  4.     "net/url"
  5. )
  6. func main() {
  7.     var u string = "https://www.zhoubotong.site"
  8.     _, err := url.ParseRequestURI(u)
  9.     if err != nil {
  10.         fmt.Println(err)
  11.         return
  12.     }
  13.     url, err := url.Parse(u)
  14.     if err != nil || url.Scheme == "" || url.Host == "" {
  15.         fmt.Println(err)
  16.         return
  17.     }
  18.     fmt.Println(url.Hostname(), "success")
  19. }
复制代码
  1. 通过上面的两个函数解析url链接,顺便唠叨介绍下这块http/post请求的示例,Get请求示例:
复制代码
  1. package main
  2. import (
  3.     "encoding/json"
  4.     "fmt"
  5.     "io/ioutil"
  6.     "net/http"
  7.     "net/url"
  8.     "time"
  9. )
  10. // 定义返回的响应体
  11. type Response struct {
  12.     Params  string            `json:"params"`
  13.     Headers map[string]string `json:"headers"`
  14.     Origin  string            `json:"origin"`
  15.     Url     string            `json:"url"`
  16. }
  17. var remoteUrl string = "https://www.baidu.com"
  18. // 获取带参数的http get请求响应数据
  19. func getUrlParse() {
  20.     data := url.Values{}
  21.     data.Set("username", "乔峰")
  22.     data.Set("sex", "male")
  23.     u, err := url.ParseRequestURI(remoteUrl)
  24.     if err != nil {
  25.         fmt.Println(err)
  26.     }
  27.     u.RawQuery = data.Encode()
  28.     fmt.Println(u.RawQuery)
  29.     resp, err := http.Get(u.String())
  30.     if err != nil {
  31.         fmt.Println(err)
  32.     }
  33.     defer resp.Body.Close() // 一定要关闭释放tcp连接
  34.     body, err := ioutil.ReadAll(resp.Body)
  35.     if err != nil {
  36.         fmt.Println(err)
  37.     }
  38.     fmt.Println(string(body))
  39. }
  40. // 解析get请求的返回的json结果到struct
  41. func getResultToStruct() {
  42.     resp, err := http.Get(remoteUrl)
  43.     if err != nil {
  44.         fmt.Println(err)
  45.         return
  46.     }
  47.     defer resp.Body.Close()
  48.     var res Response // 定义res为Responser结构体
  49.     body, err := ioutil.ReadAll(resp.Body)
  50.     if err != nil {
  51.         fmt.Println(err)
  52.         return
  53.     }
  54.     _ = json.Unmarshal(body, &res) // 注意这里是&res 地址引用
  55.     fmt.Printf("%#v\n", res)
  56. }
  57. //get 请求添加头消息
  58. func getHttpByHeader() {
  59.     param := url.Values{}
  60.     param.Set("username", "babala")
  61.     param.Set("sex", "female")
  62.     u, _ := url.ParseRequestURI(remoteUrl)
  63.     u.RawQuery = param.Encode() // 把参数转换成 sex=female&username=babala
  64.     fmt.Println(u)
  65.     //重点注意:如果我们直接使用默认的http,那么它是没有超时时间的。这样就会带来性能问题,具体稍后写一篇详细介绍这块
  66.     client := &http.Client{Timeout: 10 * time.Second}
  67.     req, err := http.NewRequest("GET", u.String(), nil)
  68.     if err != nil {
  69.         fmt.Println(err)
  70.     }
  71.     // 添加请求头header 参数
  72.     req.Header.Add("username2", "风清扬")
  73.     req.Header.Add("age1", "89")
  74.     resp, _ := client.Do(req)
  75.     defer resp.Body.Close()
  76.     body, err := ioutil.ReadAll(resp.Body)
  77.     if err != nil {
  78.         panic(err)
  79.     }
  80.     fmt.Println(string(body))
  81. }
  82. func main() {
  83.     getResultToStruct()
  84.     getHttpByHeader()
  85. }
复制代码
  1. 发送post请求示例:
复制代码
  1. package main
  2. import (
  3.     "bytes"
  4.     "encoding/json"
  5.     "fmt"
  6.     "io/ioutil"
  7.     "net/http"
  8.     "net/url"
  9.     "strings"
  10.     "time"
  11. )
  12. var remoteUrl = "https://www.zhoubotong.site"
  13. // 发送表单post请求
  14. func postByForm() {
  15.     param := url.Values{}
  16.     param.Add("username", "乔峰")
  17.     param.Add("sex", "male")
  18.     resp, _ := http.PostForm(remoteUrl, param) // 表单提交"Content-Type": "application/x-www-form-urlencoded"
  19.     defer resp.Body.Close()
  20.     body, _ := ioutil.ReadAll(resp.Body)
  21.     fmt.Println(string(body))
  22. }
  23. // 发送表单提交,可以对比上面的postByForm的实现差异
  24. func postByForm2() {
  25.     urlValue := url.Values{
  26.     "username": {"乔峰"},
  27.     "sex":      {"male"},
  28. }
  29.     respData := urlValue.Encode()
  30.     fmt.Println(respData) // encode转码:name=%E4%B9%94%E5%B3%B0&sex=male
  31.     resp, _ := http.Post(remoteUrl, "text/html", strings.NewReader(respData))
  32.     //注意接收数据类型为text/html,对应在postman中的x-www-form-urlencoded中的key value参数
  33.     defer resp.Body.Close()
  34.     body, _ := ioutil.ReadAll(resp.Body)
  35.     fmt.Println(string(body))
  36. }
  37. // 发送json数据
  38. func postJson() {
  39.     client := &http.Client{Timeout: time.Second * 10}
  40.     param := make(map[string]interface{})
  41.     param["username"] = "乔峰"
  42.     param["sex"] = "male"
  43.     respdata, _ := json.Marshal(param) // respdata[]byte类型,转化成string类型便于查看
  44.     req, _ := http.NewRequest("POST", remoteUrl, bytes.NewReader(respdata))
  45.     //http.NewRequest请求会自动发送header中的Content-Type为applcation/json,对应在postman中的body的raw的json参数
  46.     resp, _ := client.Do(req)
  47.     body, _ := ioutil.ReadAll(resp.Body)
  48.     fmt.Println(string(body))
  49. }
  50. // 发送json数据,注意和上面实现的区别
  51. func postJson2() {
  52.     param := make(map[string]interface{})
  53.     param["username"] = "乔峰"
  54.     param["sex"] = "male"
  55.     respdata, _ := json.Marshal(param) // respdata[]byte类型,转化成string类型便于查看
  56.     fmt.Println(string(respdata))
  57.     resp, _ := http.Post(remoteUrl, "application/json", bytes.NewReader(respdata))
  58.     defer resp.Body.Close()
  59.     body, _ := ioutil.ReadAll(resp.Body)
  60.     fmt.Println(string(body))
  61. }
  62. /*
  63. 对应的postman中params中的key value参数,我估计很多人都很迷惑postman工具的params和body两个地方传递参数的区别,
  64. 其实Params处设置的变量请求时会url后问号传参(?x=y)。而Body里设置的参数则是接口真正请求时发的参数,下面这个例子就是通过params传参
  65. */
  66. func postString() {
  67.     param := url.Values{}
  68.     param.Add("username", "babala")
  69.     param.Add("sex", "female")
  70.     u, _ := url.ParseRequestURI(remoteUrl)
  71.     u.RawQuery = param.Encode()
  72.     fmt.Println(u)
  73.     client := &http.Client{}
  74.     req, _ := http.NewRequest("POST", u.String(), nil) // 注意发送数据类似为string的post请求,对应的postman中params中的key value参数
  75.     resp, _ := client.Do(req)
  76.     defer resp.Body.Close()
  77.     body, _ := ioutil.ReadAll(resp.Body)
  78.     fmt.Println(string(body))
  79. }
  80. func main() {
  81.     //postByForm()
  82.     //postByForm2()
  83.     //postJson()
  84.     //postJson2()
  85.     postString()
  86. }
复制代码
  1. 通过上面的示例介绍,涉及了日常开发中各种场景的请求类型,基本满足了常规开发,以上只是示例,后端如何处理数据,大家可以自行解析参数返回试试。
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

怀念夏天

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表