-
Notifications
You must be signed in to change notification settings - Fork 0
/
brasilapi.go
83 lines (76 loc) · 1.81 KB
/
brasilapi.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
package cep
import (
"context"
"encoding/json"
"fmt"
"net/http"
)
type brasilapi struct {
client *http.Client
}
func (brasilapi) Name() string { return "brasilapi" }
// Brasilapi returns a fetcher of brasilapi.
func Brasilapi(c *http.Client) Fetcher {
if c == nil {
c = http.DefaultClient
}
return &brasilapi{client: c}
}
// Fetch implements the Fetcher interface.
func (b *brasilapi) Fetch(ctx context.Context, cep string) (Address, error) {
url := fmt.Sprintf("https://brasilapi.com.br/api/cep/v1/%s", cep)
rsp, err := request(ctx, b.client, url)
if err != nil {
return Address{}, &Error{
Kind: err.Kind,
Err: fmt.Errorf("%s: %s", b.Name(), err.Error()),
}
}
defer rsp.Body.Close()
if rsp.StatusCode != 200 {
// BrasilAPI returns 404 when the CEP was not found.
if rsp.StatusCode != 404 {
return Address{}, &Error{
Kind: Other,
Err: fmt.Errorf("%s: %s", b.Name(), err.Error()),
}
}
// TODO: Check if the 404 is in fact a CEP not found.
// It can be a server problem...
return Address{}, &Error{
Kind: CEPNotFound,
Err: fmt.Errorf("%s: CEP not found", b.Name()),
}
}
addr := new(Address)
if err1 := json.NewDecoder(rsp.Body).Decode(addr); err1 != nil {
return Address{}, &Error{
Kind: UnmarshalErr,
Err: fmt.Errorf("%s: %s", b.Name(), err1.Error()),
}
}
return *addr, nil
}
type timeouter interface {
Timeout() bool
}
func request(ctx context.Context, c *http.Client, url string) (*http.Response, *Error) {
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
if err != nil {
return nil, &Error{
Kind: Other,
Err: err,
}
}
rsp, err := c.Do(req)
if err != nil {
e := &Error{Err: err}
if terr, ok := err.(timeouter); ok && terr.Timeout() {
e.Kind = Timeout
return nil, e
}
e.Kind = Other
return nil, e
}
return rsp, nil
}