Skip to content

Commit bae7ba3

Browse files
authored
Merge pull request #22 from LaurenceGA/master
Switch to new Auckland council property search API
2 parents 5692146 + 7127bb0 commit bae7ba3

File tree

9 files changed

+104
-87
lines changed

9 files changed

+104
-87
lines changed

README.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,8 @@ Two endpoints so far, both accepting `addr` parameter.
4444
}
4545
],
4646
"Address": {
47-
"ACRateAccountKey": "12342478585",
48-
"Address": "500 Queen Street, Auckland Central",
49-
"Suggestion": "500 Queen Street, Auckland Central"
47+
"ID": "12342478585",
48+
"Address": "500 Queen Street, Auckland Central"
5049
}
5150
}
5251

addr.go

Lines changed: 38 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,73 +1,85 @@
11
package aklapi
22

33
import (
4-
"bytes"
54
"encoding/json"
65
"errors"
76
"log"
87
"net/http"
8+
"strconv"
99
"time"
1010
)
1111

1212
var (
1313
// defined as a variable so it can be overridden in tests.
14-
addrURI = `https://www.aucklandcouncil.govt.nz/_vti_bin/ACWeb/ACservices.svc/GetMatchingPropertyAddresses`
14+
addrURI = `https://www.aucklandcouncil.govt.nz/nextapi/property`
1515
)
1616

1717
// AddrRequest is the address request.
1818
type AddrRequest struct {
19-
ResultCount int `json:"ResultCount"`
20-
SearchText string `json:"SearchText"`
21-
RateKeyRequired bool `json:"RateKeyRequired"`
19+
PageSize int
20+
SearchText string
2221
}
2322

24-
// AddrResponse is the address response.
25-
type AddrResponse []Address
26-
27-
// AddrSuggestion is the address suggestion.
23+
// Address is the address and its unique identifier (rate account key).
2824
type Address struct {
29-
ACRateAccountKey string `json:"ACRateAccountKey"`
30-
Address string `json:"Address"`
31-
Suggestion string `json:"Suggestion"`
25+
ID string `json:"ID"`
26+
Address string `json:"Address"`
27+
}
28+
29+
// AddrResponse is the address response.
30+
type AddrResponse struct {
31+
Items []Address `json:"items"`
3232
}
3333

3434
func (s Address) String() string {
35-
return "<" + s.Address + " (" + s.ACRateAccountKey + ")>"
35+
return "<" + s.Address + " (" + s.ID + ")>"
3636
}
3737

3838
// AddressLookup is a convenience function to get addresses.
39-
func AddressLookup(addr string) (AddrResponse, error) {
40-
return MatchingPropertyAddresses(&AddrRequest{SearchText: addr, RateKeyRequired: false, ResultCount: 10})
39+
func AddressLookup(addr string) (*AddrResponse, error) {
40+
return MatchingPropertyAddresses(&AddrRequest{SearchText: addr, PageSize: 10})
4141
}
4242

4343
// MatchingPropertyAddresses wrapper around the AKL Council API.
44-
func MatchingPropertyAddresses(addrReq *AddrRequest) (AddrResponse, error) {
44+
func MatchingPropertyAddresses(addrReq *AddrRequest) (*AddrResponse, error) {
4545
cachedAr, ok := addrCache.Lookup(addrReq.SearchText)
4646
if ok {
4747
log.Printf("cached address result: %q", cachedAr)
4848
return cachedAr, nil
4949
}
50-
var buf bytes.Buffer
51-
enc := json.NewEncoder(&buf)
52-
if err := enc.Encode(addrReq); err != nil {
50+
51+
req, err := http.NewRequest("GET", addrURI, nil)
52+
if err != nil {
5353
return nil, err
5454
}
55+
q := req.URL.Query()
56+
q.Add("query", addrReq.SearchText)
57+
if addrReq.PageSize > 0 {
58+
q.Add("pageSize", strconv.Itoa(addrReq.PageSize))
59+
}
60+
req.URL.RawQuery = q.Encode()
5561

5662
start := time.Now()
57-
resp, err := http.Post(addrURI, "application/json; charset=UTF-8", &buf)
63+
client := &http.Client{}
64+
resp, err := client.Do(req)
5865
if err != nil {
5966
return nil, err
6067
}
6168
defer resp.Body.Close()
6269
log.Printf("address call complete in %s", time.Since(start))
6370

71+
if resp.StatusCode != http.StatusOK {
72+
return nil, errors.New("address API returned status code: " + strconv.Itoa(resp.StatusCode))
73+
}
74+
6475
dec := json.NewDecoder(resp.Body)
65-
ar := AddrResponse{}
66-
if err := dec.Decode(&ar); err != nil {
76+
var apiResp AddrResponse
77+
if err := dec.Decode(&apiResp); err != nil {
6778
return nil, err
6879
}
69-
addrCache.Add(addrReq.SearchText, ar)
70-
return ar, nil
80+
81+
addrCache.Add(addrReq.SearchText, &apiResp)
82+
return &apiResp, nil
7183
}
7284

7385
func oneAddress(addr string) (*Address, error) {
@@ -76,8 +88,8 @@ func oneAddress(addr string) (*Address, error) {
7688
return nil, err
7789
}
7890
// need exactly one address to continue
79-
if len(resp) != 1 {
91+
if len(resp.Items) != 1 {
8092
return nil, errors.New("ambiguous or empty address results")
8193
}
82-
return &resp[0], nil
94+
return &resp.Items[0], nil
8395
}

addr_cache.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
package aklapi
22

3-
type addrResponseCache map[string]AddrResponse
3+
type addrResponseCache map[string]*AddrResponse
44

55
var addrCache = make(addrResponseCache)
66

7-
func (c addrResponseCache) Lookup(searchText string) (resp AddrResponse, ok bool) {
7+
func (c addrResponseCache) Lookup(searchText string) (resp *AddrResponse, ok bool) {
88
if NoCache {
99
return nil, false
1010
}
1111
resp, ok = c[searchText]
1212
return
1313
}
1414

15-
func (c addrResponseCache) Add(searchText string, ar AddrResponse) {
15+
func (c addrResponseCache) Add(searchText string, ar *AddrResponse) {
1616
c[searchText] = ar
1717
}

addr_cache_test.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,13 @@ func Test_addrResponseCache_Lookup(t *testing.T) {
1919
NoCache bool // if true, set NoCache to true before running test
2020
c addrResponseCache
2121
args args
22-
wantResp AddrResponse
22+
wantResp *AddrResponse
2323
wantOk bool
2424
}{
2525
{"not in cache",
2626
false,
2727
addrResponseCache{
28-
"xxx": AddrResponse{*testAddr},
28+
"xxx": &AddrResponse{Items: []Address{*testAddr}},
2929
},
3030
args{"yyy"},
3131
nil,
@@ -34,16 +34,16 @@ func Test_addrResponseCache_Lookup(t *testing.T) {
3434
{"cached",
3535
false,
3636
addrResponseCache{
37-
testAddr.Address: AddrResponse{*testAddr},
37+
testAddr.Address: &AddrResponse{Items: []Address{*testAddr}},
3838
},
3939
args{testAddr.Address},
40-
AddrResponse{*testAddr},
40+
&AddrResponse{Items: []Address{*testAddr}},
4141
true,
4242
},
4343
{"cached, no cache mode",
4444
true,
4545
addrResponseCache{
46-
testAddr.Address: AddrResponse{*testAddr},
46+
testAddr.Address: &AddrResponse{Items: []Address{*testAddr}},
4747
},
4848
args{testAddr.Address},
4949
nil,
@@ -67,7 +67,7 @@ func Test_addrResponseCache_Lookup(t *testing.T) {
6767
func Test_addrResponseCache_Add(t *testing.T) {
6868
type args struct {
6969
searchText string
70-
ar AddrResponse
70+
ar *AddrResponse
7171
}
7272
tests := []struct {
7373
name string
@@ -77,9 +77,9 @@ func Test_addrResponseCache_Add(t *testing.T) {
7777
}{
7878
{"add",
7979
addrResponseCache{},
80-
args{testAddr.Address, AddrResponse{*testAddr}},
80+
args{testAddr.Address, &AddrResponse{Items: []Address{*testAddr}}},
8181
addrResponseCache{
82-
testAddr.Address: AddrResponse{*testAddr},
82+
testAddr.Address: &AddrResponse{Items: []Address{*testAddr}},
8383
},
8484
},
8585
}

addr_test.go

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,8 @@ import (
1010
)
1111

1212
var testAddr = &Address{
13-
ACRateAccountKey: "42",
14-
Address: "Red Square",
15-
Suggestion: "Red Square",
13+
ID: "42",
14+
Address: "Red Square",
1615
}
1716

1817
func TestMatchingPropertyAddresses(t *testing.T) {
@@ -23,21 +22,29 @@ func TestMatchingPropertyAddresses(t *testing.T) {
2322
name string
2423
testSrv *httptest.Server
2524
args args
26-
want AddrResponse
25+
want *AddrResponse
2726
wantErr bool
2827
}{
2928
{"main branch",
3029
httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
31-
writeAddrJSON(w, AddrResponse{*testAddr})
30+
writeAddrJSON(w, AddrResponse{Items: []Address{*testAddr}})
3231
})),
3332
args{&AddrRequest{
34-
ResultCount: 1,
35-
SearchText: "red sq",
36-
RateKeyRequired: false,
33+
PageSize: 1,
34+
SearchText: "red sq",
3735
}},
38-
AddrResponse{*testAddr},
36+
&AddrResponse{Items: []Address{*testAddr}},
3937
false,
4038
},
39+
{"non-200 status code",
40+
httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
41+
w.WriteHeader(http.StatusInternalServerError)
42+
writeAddrJSON(w, AddrResponse{})
43+
})),
44+
args{&AddrRequest{}},
45+
nil,
46+
true,
47+
},
4148
{"post error",
4249
httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
4350
http.NotFound(w, r)
@@ -81,15 +88,15 @@ func TestAddress(t *testing.T) {
8188
name string
8289
testSrv *httptest.Server
8390
args args
84-
want AddrResponse
91+
want *AddrResponse
8592
wantErr bool
8693
}{
8794
{"main branch",
8895
httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
89-
writeAddrJSON(w, AddrResponse{*testAddr})
96+
writeAddrJSON(w, AddrResponse{Items: []Address{*testAddr}})
9097
})),
9198
args{"red square"},
92-
AddrResponse{*testAddr},
99+
&AddrResponse{Items: []Address{*testAddr}},
93100
false,
94101
},
95102
}
@@ -124,23 +131,23 @@ func Test_oneAddress(t *testing.T) {
124131
}{
125132
{"one address",
126133
httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
127-
writeAddrJSON(w, AddrResponse{*testAddr})
134+
writeAddrJSON(w, AddrResponse{Items: []Address{*testAddr}})
128135
})),
129136
args{"red square"},
130137
testAddr,
131138
false,
132139
},
133140
{"several address",
134141
httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
135-
writeAddrJSON(w, AddrResponse{*testAddr, *testAddr})
142+
writeAddrJSON(w, AddrResponse{Items: []Address{*testAddr, *testAddr}})
136143
})),
137144
args{"red squarex"},
138145
nil,
139146
true,
140147
},
141148
{"no address",
142149
httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
143-
w.Write([]byte("[]"))
150+
w.Write([]byte("{\"items\":[]}"))
144151
})),
145152
args{"red squarec"},
146153
nil,

rubbish.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ func CollectionDayDetail(addr string) (*CollectionDayDetailResult, error) {
101101
return nil, err
102102
}
103103
start := time.Now()
104-
result, err := fetchandparse(address.ACRateAccountKey)
104+
result, err := fetchandparse(address.ID)
105105
if err != nil {
106106
return nil, err
107107
}
@@ -112,8 +112,8 @@ func CollectionDayDetail(addr string) (*CollectionDayDetailResult, error) {
112112
}
113113

114114
// fetchandparse retrieves the data from the webpage and attempts to parse it.
115-
func fetchandparse(ACRateAccountKey string) (*CollectionDayDetailResult, error) {
116-
resp, err := http.Get(fmt.Sprintf(collectionDayURI, ACRateAccountKey))
115+
func fetchandparse(addressID string) (*CollectionDayDetailResult, error) {
116+
resp, err := http.Get(fmt.Sprintf(collectionDayURI, addressID))
117117
if err != nil {
118118
return nil, err
119119
}

0 commit comments

Comments
 (0)