golang url encode

背景: net/url库没找到如何控制特殊字符不转码,自己实现

main:

package main

import (
    "ap/url_utils"
    "fmt"
)

func main() {
    // :/?~%&+=;,@()!*#$'
    url := "http://www.baidu.com/aaa/:/?~%&+=;,@()!*#$''/bbb/sdf/斯蒂芬.dill"
    r := url_utils.QueryEscape(url)
    fmt.Println(r)
}

 

utils:

package url_utils

const upperhex = "0123456789ABCDEF"

type encoding int

const (
    encodePath encoding = 1 + iota
    encodePathSegment
    encodeHost
    encodeZone
    encodeUserPassword
    encodeQueryComponent
    encodeFragment
    encodeURI
)

// QueryEscape escapes the string so it can be safely placed
// inside a URL query.
func QueryEscape(s string) string {
    return escape(s, encodeURI)
}

func escape(s string, mode encoding) string {
    spaceCount, hexCount := 0, 0
    for i := 0; i < len(s); i++ {
        c := s[i]
        if shouldEscape(c, mode) {
            if c == ' ' && mode == encodeQueryComponent {
                spaceCount++
            } else {
                hexCount++
            }
        }
    }

    if spaceCount == 0 && hexCount == 0 {
        return s
    }

    var buf [64]byte
    var t []byte

    required := len(s) + 2*hexCount
    if required <= len(buf) {
        t = buf[:required]
    } else {
        t = make([]byte, required)
    }

    if hexCount == 0 {
        copy(t, s)
        for i := 0; i < len(s); i++ {
            if s[i] == ' ' {
                t[i] = '+'
            }
        }
        return string(t)
    }

    j := 0
    for i := 0; i < len(s); i++ {
        switch c := s[i]; {
        case c == ' ' && mode == encodeQueryComponent:
            t[j] = '+'
            j++
        case shouldEscape(c, mode):
            t[j] = '%'
            t[j+1] = upperhex[c>>4]
            t[j+2] = upperhex[c&15]
            j += 3
        default:
            t[j] = s[i]
            j++
        }
    }
    return string(t)
}

// Return true if the specified character should be escaped when
// appearing in a URL string, according to RFC 3986.
//
// Please be informed that for now shouldEscape does not check all
// reserved characters correctly. See golang.org/issue/5684.


func shouldEscape(c byte, mode encoding) bool {
    // §2.3 Unreserved characters (alphanum)
    if 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || '0' <= c && c <= '9' {
        return false
    }

    //:/?~%&+=;,@()!*#$'
    switch c {
    case '-', '_', '.', '~':
        return false
    case '!', '$', '&', '\'', '(', ')', '*', '+', ',', ';', '=', ':', '/', '?', '%', '@', '#':
        return false
    }
    // Everything else must be escaped.
    return true
}

 

posted @ 2020-11-07 00:52  静静别跑  阅读(3483)  评论(0编辑  收藏  举报