forked from philippseith/signalr
-
Notifications
You must be signed in to change notification settings - Fork 0
/
httpclient.go
92 lines (90 loc) · 2.35 KB
/
httpclient.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
package signalr
import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"nhooyr.io/websocket"
)
// NewHTTPClient creates a signalR Client which tries to connect over http to the given address
func NewHTTPClient(ctx context.Context, address string, options ...func(Party) error) (Client, error) {
req, err := http.NewRequest("POST", fmt.Sprintf("%v/negotiate", address), nil)
if err != nil {
return nil, err
}
httpClient := &http.Client{}
resp, err := httpClient.Do(req)
if err != nil {
return nil, err
}
defer func() { _ = resp.Body.Close() }()
if resp.StatusCode != 200 {
return nil, fmt.Errorf("%v -> %v", req, resp.Status)
}
body, _ := ioutil.ReadAll(resp.Body)
nr := negotiateResponse{}
err = json.Unmarshal(body, &nr)
if err != nil {
return nil, err
}
reqURL, err := url.Parse(address)
if err != nil {
return nil, err
}
q := reqURL.Query()
q.Set("id", nr.ConnectionID)
reqURL.RawQuery = q.Encode()
// Select the best connection
var conn Connection
var formats []string
if formats = nr.getTransferFormats("WebTransports"); formats != nil {
// TODO
} else if formats = nr.getTransferFormats("WebSockets"); formats != nil {
wsURL := reqURL
wsURL.Scheme = "ws"
ws, _, err := websocket.Dial(ctx, wsURL.String(), nil)
if err != nil {
return nil, err
}
conn = newWebSocketConnection(ctx, context.Background(), nr.ConnectionID, ws)
} else if formats = nr.getTransferFormats("ServerSentEvents"); formats != nil {
req, err := http.NewRequest("GET", reqURL.String(), nil)
if err != nil {
return nil, err
}
req.Header.Set("Accept", "text/event-stream")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
conn, err = newClientSSEConnection(ctx, address, nr.ConnectionID, resp.Body)
if err != nil {
return nil, err
}
}
if conn != nil {
// If only Text is supported, remove possible option for Binary
var filteredOptions []func(Party) error
if len(formats) == 1 && formats[0] == "Text" {
for _, option := range options {
c := client{}
_ = option(&c)
if c.format == "messagepack" {
continue
}
filteredOptions = append(filteredOptions, option)
}
} else {
filteredOptions = options
}
result, err := NewClient(ctx, conn, filteredOptions...)
if err != nil {
return nil, err
}
return result, nil
}
return nil, nil
}