-
Notifications
You must be signed in to change notification settings - Fork 1
/
xhr.go
89 lines (81 loc) · 2.25 KB
/
xhr.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
//go:build js && wasm
// Package http makes XML HTTP Requests using native browser code.
package http
import (
"errors"
"syscall/js"
"time"
)
type (
// Client makes HTTP requests.
Client struct {
// Timeout is the amount of time a request can take before being considered timed out.
Timeout time.Duration
}
// Request identifies the question to ask a server.
Request struct {
// Method is the HTTP method (GET/POST).
Method string
// URL is the address to the server.
URL string
// Headers contain additional request properties.
Headers map[string]string
// Body contains additional request data.
Body string
}
// Response is what the server responds.
Response struct {
// Code is a descriptive status about the server handled the response (200 OK, 500 Internal Server Error).
Code int
// Body contains the response data.
Body string
// err is used internally and is set if the response has an error.
err error
}
// DOM creates http requests
DOM interface {
NewXHR() js.Value
NewJsEventFunc(fn func(event js.Value)) js.Func
}
)
// Do makes a HTTP request.
func (c Client) Do(dom DOM, req Request) (*Response, error) {
if dom == nil {
return nil, errors.New("DOM not specified")
}
xhr := dom.NewXHR()
xhr.Call("open", req.Method, req.URL)
timeoutMillis := c.Timeout.Milliseconds()
xhr.Set("timeout", timeoutMillis)
for k, v := range req.Headers {
xhr.Call("setRequestHeader", k, v)
}
responseC := make(chan Response)
eventHandler := dom.NewJsEventFunc(handleEvent(xhr, responseC))
defer eventHandler.Release()
xhrEventTypes := []string{"load", "timeout", "abort", "error"}
for _, event := range xhrEventTypes {
xhr.Call("addEventListener", event, eventHandler)
}
go xhr.Call("send", req.Body)
response := <-responseC
if response.err != nil {
return nil, response.err
}
return &response, nil
}
// handleEvent handles an event for the XHR.
func handleEvent(xhr js.Value, responseC chan<- Response) func(event js.Value) {
return func(event js.Value) {
eventType := event.Get("type").String()
var r Response
switch eventType {
case "load":
r.Code = xhr.Get("status").Int()
r.Body = xhr.Get("response").String()
default:
r.err = errors.New("received event type: " + eventType)
}
responseC <- r
}
}