PHP与golang之urlencode空格加号踩坑

url中如果带有特殊字符,正常处理一般都是urlencode,但对于空格,会有些特别奇葩的情况。

  • PHP

    先看一下php的处理:

<?php
    $url = 'http://www.abc.com/apple iphone+ipad';
    $encode_url = urlencode($url);
    echo 'encode_url:'.$encode_url.PHP_EOL;
    $decode_url = urldecode($encode_url);
    echo 'decode_url:'.$decode_url.PHP_EOL;
?>

输出:

encode_url:http%3A%2F%2Fwww.abc.com%2Fapple+iphone%2Bipad
decode_url:http://www.abc.com/apple iphone+ipad

可以看到字符串中的空格urlencode后变成了+加号。

  • golang

    golang提供了两种escape标准实现方法,区别在于

url.PathEscape:空格会转为 %20
url.QueryEscape:空格会转为 +
url.Values.Encode:内部是QueryEscape

看下效果:

PathEscape:
    var str string = "http://www.abc.com/apple iphone+ipad"
    str = url.PathEscape(str)
    fmt.Println(str)
    str, err := url.PathUnescape(str)
    fmt.Println(str)
    fmt.Println(err)

输出:

apple%20iphone+ipad
apple iphone+ipad%android
<nil>
QueryEscape:
    var str string = "http://www.abc.com/apple iphone+ipad"
    str = url.QueryEscape(str)
    fmt.Println(str)
    str, err := url.QueryUnescape(str)
    fmt.Println(str)
    fmt.Println(err)

输出:

http%3A%2F%2Fwww.abc.com%2Fapple+iphone%2Bipad
http://www.abc.com/apple iphone+ipad
<nil>
注意点

PathUnescape、QueryUnescape解析不出时会报err,跟php不一样,比如

    str := "100%power"
    str, err := url.QueryUnescape(str)
    fmt.Println(str) //空字符串
    fmt.Println(err) //invalid URL escape "%po"

需要判断err不是nil是返回原字符串,不然str会变成空值了

    str := "100%power"
    if res, err := url.QueryUnescape(str); err == nil {
        str = res
    }
    fmt.Println(str) //100%power

踩坑坑坑坑

当php的urlencode后的字串,在golang中PathUnescape解析时,会出现偏差

    str := "http%3A%2F%2Fwww.abc.com%2Fapple+iphone%2Bipad" //php中urlencode后的地址
    str, err := url.PathUnescape(str)
    fmt.Println(str)
    fmt.Println(err)

输出:

http://www.abc.com/apple+iphone+ipad
<nil>

期望值是http://www.abc.com/apple iphone+ipad,结果空格没有解出来

建议

当与php互相传输的数据需要url处理时,建议都使用url.QueryEscape。

某些特殊情况,比如某些验签,需要空格号转为%20再加密时,就会用到url.PathEscape。