Skip to content

Commit 994f6f8

Browse files
committed
use go-querystring for constructing URLs
this only updates a few user and repo functions just to establish the calling pattern. closes #56 (which also includes a little more background)
1 parent aed46a3 commit 994f6f8

File tree

5 files changed

+68
-54
lines changed

5 files changed

+68
-54
lines changed

github/github.go

+27-2
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,12 @@ import (
1313
"io/ioutil"
1414
"net/http"
1515
"net/url"
16+
"reflect"
1617
"strconv"
1718
"strings"
1819
"time"
20+
21+
"github.com/google/go-querystring/query"
1922
)
2023

2124
const (
@@ -65,10 +68,32 @@ type Client struct {
6568
// support pagination.
6669
type ListOptions struct {
6770
// For paginated result sets, page of results to retrieve.
68-
Page int
71+
Page int `url:"page,omitempty"`
6972

7073
// For paginated result sets, the number of results to include per page.
71-
PerPage int
74+
PerPage int `url:"per_page,omitempty"`
75+
}
76+
77+
// addOptions adds the parameters in opt as URL query parameters to s. opt
78+
// must be a struct whose fields may contain "url" tags.
79+
func addOptions(s string, opt interface{}) (string, error) {
80+
v := reflect.ValueOf(opt)
81+
if v.Kind() == reflect.Ptr && v.IsNil() {
82+
return s, nil
83+
}
84+
85+
u, err := url.Parse(s)
86+
if err != nil {
87+
return s, err
88+
}
89+
90+
qs, err := query.Values(opt)
91+
if err != nil {
92+
return s, err
93+
}
94+
95+
u.RawQuery = qs.Encode()
96+
return u.String(), nil
7297
}
7398

7499
// NewClient returns a new GitHub API client. If a nil httpClient is

github/github_test.go

+8-4
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,14 @@ func testMethod(t *testing.T, r *http.Request, want string) {
5757
type values map[string]string
5858

5959
func testFormValues(t *testing.T, r *http.Request, values values) {
60-
for key, want := range values {
61-
if v := r.FormValue(key); v != want {
62-
t.Errorf("Request parameter %v = %v, want %v", key, v, want)
63-
}
60+
want := url.Values{}
61+
for k, v := range values {
62+
want.Add(k, v)
63+
}
64+
65+
r.ParseForm()
66+
if !reflect.DeepEqual(want, r.Form) {
67+
t.Errorf("Request parameters = %v, want %v", r.Form, want)
6468
}
6569
}
6670

github/repos.go

+20-35
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,7 @@
55

66
package github
77

8-
import (
9-
"fmt"
10-
"net/url"
11-
"strconv"
12-
)
8+
import "fmt"
139

1410
// RepositoriesService handles communication with the repository related
1511
// methods of the GitHub API.
@@ -59,18 +55,17 @@ func (r Repository) String() string {
5955
type RepositoryListOptions struct {
6056
// Type of repositories to list. Possible values are: all, owner, public,
6157
// private, member. Default is "all".
62-
Type string
58+
Type string `url:"type,omitempty"`
6359

6460
// How to sort the repository list. Possible values are: created, updated,
6561
// pushed, full_name. Default is "full_name".
66-
Sort string
62+
Sort string `url:"sort,omitempty"`
6763

6864
// Direction in which to sort repositories. Possible values are: asc, desc.
6965
// Default is "asc" when sort is "full_name", otherwise default is "desc".
70-
Direction string
66+
Direction string `url:"direction,omitempty"`
7167

72-
// For paginated result sets, page of results to retrieve.
73-
Page int
68+
ListOptions
7469
}
7570

7671
// List the repositories for a user. Passing the empty string will list
@@ -84,14 +79,9 @@ func (s *RepositoriesService) List(user string, opt *RepositoryListOptions) ([]R
8479
} else {
8580
u = "user/repos"
8681
}
87-
if opt != nil {
88-
params := url.Values{
89-
"type": []string{opt.Type},
90-
"sort": []string{opt.Sort},
91-
"direction": []string{opt.Direction},
92-
"page": []string{strconv.Itoa(opt.Page)},
93-
}
94-
u += "?" + params.Encode()
82+
u, err := addOptions(u, opt)
83+
if err != nil {
84+
return nil, nil, err
9585
}
9686

9787
req, err := s.client.NewRequest("GET", u, nil)
@@ -109,23 +99,19 @@ func (s *RepositoriesService) List(user string, opt *RepositoryListOptions) ([]R
10999
type RepositoryListByOrgOptions struct {
110100
// Type of repositories to list. Possible values are: all, public, private,
111101
// forks, sources, member. Default is "all".
112-
Type string
102+
Type string `url:"type,omitempty"`
113103

114-
// For paginated result sets, page of results to retrieve.
115-
Page int
104+
ListOptions
116105
}
117106

118107
// ListByOrg lists the repositories for an organization.
119108
//
120109
// GitHub API docs: http://developer.github.com/v3/repos/#list-organization-repositories
121110
func (s *RepositoriesService) ListByOrg(org string, opt *RepositoryListByOrgOptions) ([]Repository, *Response, error) {
122111
u := fmt.Sprintf("orgs/%v/repos", org)
123-
if opt != nil {
124-
params := url.Values{
125-
"type": []string{opt.Type},
126-
"page": []string{strconv.Itoa(opt.Page)},
127-
}
128-
u += "?" + params.Encode()
112+
u, err := addOptions(u, opt)
113+
if err != nil {
114+
return nil, nil, err
129115
}
130116

131117
req, err := s.client.NewRequest("GET", u, nil)
@@ -142,19 +128,18 @@ func (s *RepositoriesService) ListByOrg(org string, opt *RepositoryListByOrgOpti
142128
// RepositoriesService.ListAll method.
143129
type RepositoryListAllOptions struct {
144130
// ID of the last repository seen
145-
Since int
131+
Since int `url:"since,omitempty"`
132+
133+
ListOptions
146134
}
147135

148136
// ListAll lists all GitHub repositories in the order that they were created.
149137
//
150-
// GitHub API docs: http://developer.github.com/v3/repos/#list-all-repositories
138+
// GitHub API docs: http://developer.github.com/v3/repos/#list-all-public-repositories
151139
func (s *RepositoriesService) ListAll(opt *RepositoryListAllOptions) ([]Repository, *Response, error) {
152-
u := "repositories"
153-
if opt != nil {
154-
params := url.Values{
155-
"since": []string{strconv.Itoa(opt.Since)},
156-
}
157-
u += "?" + params.Encode()
140+
u, err := addOptions("repositories", opt)
141+
if err != nil {
142+
return nil, nil, err
158143
}
159144

160145
req, err := s.client.NewRequest("GET", u, nil)

github/repos_test.go

+8-4
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ func TestRepositoriesService_List_specifiedUser(t *testing.T) {
4949
fmt.Fprint(w, `[{"id":1}]`)
5050
})
5151

52-
opt := &RepositoryListOptions{"owner", "created", "asc", 2}
52+
opt := &RepositoryListOptions{"owner", "created", "asc", ListOptions{Page: 2}}
5353
repos, _, err := client.Repositories.List("u", opt)
5454
if err != nil {
5555
t.Errorf("Repositories.List returned error: %v", err)
@@ -79,7 +79,7 @@ func TestRepositoriesService_ListByOrg(t *testing.T) {
7979
fmt.Fprint(w, `[{"id":1}]`)
8080
})
8181

82-
opt := &RepositoryListByOrgOptions{"forks", 2}
82+
opt := &RepositoryListByOrgOptions{"forks", ListOptions{Page: 2}}
8383
repos, _, err := client.Repositories.ListByOrg("o", opt)
8484
if err != nil {
8585
t.Errorf("Repositories.ListByOrg returned error: %v", err)
@@ -102,11 +102,15 @@ func TestRepositoriesService_ListAll(t *testing.T) {
102102

103103
mux.HandleFunc("/repositories", func(w http.ResponseWriter, r *http.Request) {
104104
testMethod(t, r, "GET")
105-
testFormValues(t, r, values{"since": "1"})
105+
testFormValues(t, r, values{
106+
"since": "1",
107+
"page": "2",
108+
"per_page": "3",
109+
})
106110
fmt.Fprint(w, `[{"id":1}]`)
107111
})
108112

109-
opt := &RepositoryListAllOptions{1}
113+
opt := &RepositoryListAllOptions{1, ListOptions{2, 3}}
110114
repos, _, err := client.Repositories.ListAll(opt)
111115
if err != nil {
112116
t.Errorf("Repositories.ListAll returned error: %v", err)

github/users.go

+5-9
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@ package github
77

88
import (
99
"fmt"
10-
"net/url"
11-
"strconv"
10+
1211
"time"
1312
)
1413

@@ -83,19 +82,16 @@ func (s *UsersService) Edit(user *User) (*User, *Response, error) {
8382
// method.
8483
type UserListOptions struct {
8584
// ID of the last user seen
86-
Since int
85+
Since int `url:"since,omitempty"`
8786
}
8887

8988
// ListAll lists all GitHub users.
9089
//
9190
// GitHub API docs: http://developer.github.com/v3/users/#get-all-users
9291
func (s *UsersService) ListAll(opt *UserListOptions) ([]User, *Response, error) {
93-
u := "users"
94-
if opt != nil {
95-
params := url.Values{
96-
"since": []string{strconv.Itoa(opt.Since)},
97-
}
98-
u += "?" + params.Encode()
92+
u, err := addOptions("users", opt)
93+
if err != nil {
94+
return nil, nil, err
9995
}
10096

10197
req, err := s.client.NewRequest("GET", u, nil)

0 commit comments

Comments
 (0)