在 Go 語言內的 URL RawQuery 的改變

栏目: Go · 发布时间: 5年前

内容简介:url.Values{“k”:[]string{“v”}, “id”:[]string{“main”, “omit”}, “array[]”:[]string{“first”, “second”}, “idsurl.Values{“k=v&id=main&id=omit&array[]=first&array[]=second&ids
在  <a href='https://www.codercto.com/topics/6127.html'>Go</a>  語言內的 URL RawQuery 的改變 Go 語言 內的 net/url 函式庫讓開發者可以簡單的 Parse 指定的 URL,最近 Google 上了這個 Patch ,這個 Patch 讓原本的 RawQuery 值產生了變化,原先沒有驗證 RawQuery 是否包含了不合法的字元,現在只要 RawQuesy 內含有任意的不合法字元,就會直接被 QueryEscape 函式轉換,這個 Patch 不影響這次 Go 1.11 版本 ,會影響的是明年 2019 年釋出的 Go 1.12 版本,但是大家都知道在 GitHub 上面有在寫測試的話,都會在 Travis 內加入 master 版本當作驗證,如果有用到 RawQuery 的話,肯定會遇到這問題,底下來描述為什麼會出現這問題。

RawQuery 含有不合法字元

首先來看看在 Go 1.11 版本時本來應該輸出什麼,請直接線上看 例子
package main

import (
    "log"
    "net/url"
)

func main() {
    u, err := url.Parse("http://bing.com/search?k=v&id=main&id=omit&array[]=first&array[]=second&ids<em></em>=111&ids[j]=3.14")
    if err != nil {
        log.Fatal(err)
    }

    if u.RawQuery != "k=v&id=main&id=omit&array[]=first&array[]=second&ids<em></em>=111&ids[j]=3.14" {
        log.Fatal("RawQuery error")
    }

    log.Printf("%#v", u.Query())
}
在 Go 1.11 以前,你會直接看到底下輸出:

url.Values{“k”:[]string{“v”}, “id”:[]string{“main”, “omit”}, “array[]”:[]string{“first”, “second”}, “ids “:[]string{“111”}, “ids[j]”:[]string{“3.14”}}

url 函式庫 幫忙把 RawQuery 整理成 map[string][]string 格式,所以在 URL 內可以直接 Parse array[]=first&array[]=second 多個 Array 值。這個預設行為在最新的 Go 語言被換掉了,現在執行 u.Query() 你會看到變成底下,整串的 Raw Query String 被當長一個 Key 值了。

url.Values{“k=v&id=main&id=omit&array[]=first&array[]=second&ids =111&ids[j]=3.14″: []string{“”}}

這就是最大的改變,造成在 Travis 執行錯誤。

如何修正

修正方式其實很簡單,自己在寫個小型 Parser 把原本的格式在轉換就好,請參考 線上解法
package main

import (
    "log"
    "net/url"
    "strings"
)

func main() {
    u, err := url.Parse("http://bing.com/search?k=v&id=main&id=omit&array[]=first&array[]=second&ids<em></em>=111&ids[j]=3.14")
    if err != nil {
        log.Fatal(err)
    }

    if u.RawQuery != "k=v&id=main&id=omit&array[]=first&array[]=second&ids<em></em>=111&ids[j]=3.14" {
        log.Fatal("RawQuery error")
    }

    log.Printf("%#v", u.Query())

    query := resetQuery(map[string][]string{"k=v&id=main&id=omit&array[]=first&array[]=second&ids<em></em>=111&ids[j]=3.14": []string{""}})
    log.Printf("%#v", query)
}

func resetQuery(m map[string][]string) map[string][]string {
    dicts := make(map[string][]string)
    for k, v := range m {
        lists := strings.Split(k, "&")
        if len(lists) == 1 {
            dicts[k] = v
            continue
        }
        for _, vv := range lists {
            p := strings.Split(vv, "=")
            dicts[p[0]] = append(dicts[p[0]], p[1])
        }
    }
    return dicts
}
只要 RawQuery 裡面有包含底下字元,就會被 escape 掉
// validQuery reports whether s is a valid query string per RFC 3986
// Section 3.4:
//     query       = *( pchar / "/" / "?" )
//     pchar       = unreserved / pct-encoded / sub-delims / ":" / "@"
//     unreserved  = ALPHA / DIGIT / "-" / "." / "_" / "~"
//     sub-delims  = "!" / "$" / "&" / "'" / "(" / ")"
//                   / "*" / "+" / "," / ";" / "="

後記

現在含以前的版本都不會遇到這問題,如果你有用一些 Framework 請務必在明年釋出下一版後,一起跟著升級, Gin 現在已經發 Patch 修正了。

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

电商产品经理宝典:电商后台系统产品逻辑全解析

电商产品经理宝典:电商后台系统产品逻辑全解析

刘志远 / 电子工业出版社 / 2017-10-1 / 49.00元

时至今日,对于产品经理的要求趋向业务型、平台型,甚至产生了细分领域专家。纯粹的前端产品经理(页面、交互)逐渐失去竞争力。而当后台产品经理的视野开始从功能延伸到模块,再延伸到子系统,最后关注整体系统时,就有了把控平台型产品的能力。 《电商产品经理宝典:电商后台系统产品逻辑全解析》围绕“电商后台产品”,从电商的整体产品架构入手,逐步剖析各支撑子系统。通过学习电商产品后台的架构和逻辑,可以让读者从......一起来看看 《电商产品经理宝典:电商后台系统产品逻辑全解析》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具