-
Notifications
You must be signed in to change notification settings - Fork 59
/
dialer.go
100 lines (81 loc) · 2.48 KB
/
dialer.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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
package conduit
import (
"errors"
"strings"
)
var (
// ErrJSONOutputUnsupported is returned when conduit doesn't support JSON output.
ErrJSONOutputUnsupported = errors.New("json output not supported")
// ErrURLEncodedInputUnsupported is returned when conduit doesn't support URL encoded input.
ErrURLEncodedInputUnsupported = errors.New("urlencoded input not supported")
// ErrSessionAuthUnsupported is returned when conduit doesn't support session authentication.
ErrSessionAuthUnsupported = errors.New("session authentication not supported")
)
// ConduitError is returned when conduit
// requests return an error response.
type ConduitError struct {
code string
info string
}
// Code returns the error_code returned in a conduit response.
func (err *ConduitError) Code() string {
return err.code
}
// Info returns the error_info returned in a conduit response.
func (err *ConduitError) Info() string {
return err.info
}
func (err *ConduitError) Error() string {
return err.code + ": " + err.info
}
// IsConduitError checks whether or not err is a ConduitError.
func IsConduitError(err error) bool {
_, ok := err.(*ConduitError)
return ok
}
// A Dialer contains options for connecting to an address.
type Dialer struct {
ClientName string
ClientVersion string
ClientDescription string
}
type conduitCapabilitiesResponse struct {
Authentication []string `json:"authentication"`
Signatures []string `json:"signatures"`
Input []string `json:"input"`
Output []string `json:"output"`
}
// Dial connects to conduit and confirms the API capabilities
// for future calls.
func Dial(host string) (*Conn, error) {
var d Dialer
d.ClientName = "go-conduit"
d.ClientVersion = "1"
return d.Dial(host)
}
// Dial connects to conduit and confirms the API capabilities
// for future calls.
func (d *Dialer) Dial(host string) (*Conn, error) {
host = strings.TrimSuffix(host, "/")
var resp conduitCapabilitiesResponse
if err := call(host+"/api/conduit.getcapabilities", nil, &resp); err != nil {
return nil, err
}
// We use conduit.connect for authentication
// and it establishes a session.
if !containsString(resp.Authentication, "session") {
return nil, ErrSessionAuthUnsupported
}
if !containsString(resp.Input, "urlencoded") {
return nil, ErrURLEncodedInputUnsupported
}
if !containsString(resp.Output, "json") {
return nil, ErrJSONOutputUnsupported
}
conn := Conn{
host: host,
capabilities: &resp,
dialer: d,
}
return &conn, nil
}