1
// Copyright 2015 Canonical Ltd.
2
// Licensed under the LGPLv3, see LICENSE file for details.
13
// Remove the standard ports from the URL.
14
func normalizeHost(scheme, hostSpec string) string {
15
standardPorts := map[string]string{
19
hostParts := strings.Split(hostSpec, ":")
20
if len(hostParts) == 2 && hostParts[1] == standardPorts[scheme] {
21
// There's a port, but it's the default one. Leave it out.
27
// Normalize the URL according to OAuth specs.
28
func NormalizeURL(inputUrl string) (string, error) {
29
parsedUrl, err := url.Parse(inputUrl)
34
host := normalizeHost(parsedUrl.Scheme, parsedUrl.Host)
35
normalizedUrl := fmt.Sprintf(
36
"%v://%v%v", parsedUrl.Scheme, host, parsedUrl.Path)
37
return normalizedUrl, nil
40
type parameterSlice []parameter
42
func (p parameterSlice) Len() int {
46
func (p parameterSlice) Less(i, j int) bool {
47
if p[i].key < p[j].key {
50
if p[i].key == p[j].key {
51
return p[i].value < p[j].value
56
func (p parameterSlice) Swap(i, j int) {
57
p[i], p[j] = p[j], p[i]
60
func (p parameterSlice) String() string {
61
ss := make([]string, len(p))
62
for i, param := range p {
63
ss[i] = param.String()
65
return strings.Join(ss, "&")
68
type parameter struct {
72
func (p parameter) String() string {
73
return fmt.Sprintf("%s=%s", p.key, p.value)
76
// Normalize the parameters in the query string according to
77
// http://tools.ietf.org/html/rfc5849#section-3.4.1.3.2.
78
// url.Values.Encode encoded the GET parameters in a consistent order we
79
// do the encoding ourselves.
80
func NormalizeParameters(parameters url.Values) (string, error) {
82
for k, vs := range parameters {
83
if k == "oauth_signature" {
87
for _, v := range vs {
89
ps = append(ps, parameter{k, v})
93
return ps.String(), nil
96
var escaped = [4]uint64{
103
// escape percent encodes s as defined in
104
// http://tools.ietf.org/html/rfc5849#section-3.6.
106
// Note: this is slightly different from the output of url.QueryEscape.
107
func escape(s string) string {
109
for i := 0; i < len(s); i++ {
110
if (escaped[s[i]>>6]>>(s[i]&0x3f))&1 == 1 {
117
buf := make([]byte, len(s)+2*count)
119
for i := 0; i < len(s); i++ {
120
if (escaped[s[i]>>6]>>(s[i]&0x3f))&1 == 1 {
122
buf[j+1] = "0123456789ABCDEF"[s[i]>>4]
123
buf[j+2] = "0123456789ABCDEF"[s[i]&0xf]