...
1 package http
2
3 import (
4 "context"
5 "fmt"
6 "io"
7 "net/http"
8 "time"
9
10 "golang.conradwood.net/go-easyops/errors"
11 "golang.yacloud.eu/apis/urlcacher"
12 )
13
14 var (
15 foo_ctr int
16 )
17
18
19 type cHTTP struct {
20 timeout time.Duration
21 ctx context.Context
22 ctx_cancel context.CancelFunc
23 tio *timeouter
24 last_message_received time.Time
25 cancelled bool
26 debug bool
27 }
28 type timeouter struct {
29 ch chan bool
30 idx int
31 }
32
33 func (h *cHTTP) SetDebug(b bool) {
34 h.debug = b
35 }
36 func (h *cHTTP) Cookie(name string) *http.Cookie {
37 panic("cookie not supported")
38 }
39 func (h *cHTTP) Cookies() []*http.Cookie {
40 panic("cookies not supported")
41 }
42 func (h *cHTTP) Delete(url string, body []byte) *HTTPResponse {
43 panic("delete not supported")
44 }
45 func (h *cHTTP) Get(url string) *HTTPResponse {
46 defer h.stop_timeouter()
47 ctx := h.ctx
48 hr := &HTTPResponse{}
49 empty := &urlcacher.GetRequest{URL: url}
50 srv, err := urlcacher.GetURLCacherClient().Get(ctx, empty)
51 if err != nil {
52 hr.err = err
53 return hr
54 }
55
56 l := uint64(0)
57 started := time.Now()
58 var buf []byte
59 for {
60 if h.timeout != 0 {
61 dur := time.Since(started)
62 if dur > h.timeout {
63 hr.err = fmt.Errorf("timeout after %0.2fs seconds", dur.Seconds())
64 }
65 }
66
67 data, err := srv.Recv()
68 if h.ctx.Err() != nil {
69 hr.err = fmt.Errorf("ctx error after %0.2fs: %s", time.Since(started).Seconds(), h.ctx.Err())
70 break
71 }
72 if h.cancelled {
73 hr.err = fmt.Errorf("Cancelled (timeout)")
74 break
75 }
76 h.last_message_received = time.Now()
77 if (data != nil) && (len(data.Data)) > 0 {
78 buf = append(buf, data.Data...)
79 }
80 if (data != nil) && (data.Result != nil) {
81 r := data.Result
82 hr.httpCode = int(r.HTTPCode)
83 if !r.Success {
84 if hr.httpCode == 404 {
85 hr.err = errors.NotFound(ctx, "url \"%s\" not found (code %d): %s", url, hr.httpCode, r.Message)
86 } else {
87 hr.err = fmt.Errorf("failed to retrieve url \"%s\" (code %d): %s", url, hr.httpCode, r.Message)
88 }
89 break
90 }
91 }
92
93 if err == io.EOF {
94 break
95 }
96 if err != nil {
97 hr.err = err
98 break
99 }
100 r := uint64(len(data.Data))
101 l = l + r
102 }
103 hr.setBody(buf)
104 return hr
105 }
106 func (h *cHTTP) GetStream(url string) *HTTPResponse {
107 return nil
108 }
109 func (h *cHTTP) Head(url string) *HTTPResponse {
110 panic("head not supported")
111 }
112 func (h *cHTTP) Post(url string, body []byte) *HTTPResponse {
113 panic("post not supported")
114 }
115 func (h *cHTTP) Put(url string, body string) *HTTPResponse {
116 panic("put not supported")
117 }
118 func (h *cHTTP) SetHeader(key string, value string) {
119 panic("setheader not supported")
120 }
121 func (h *cHTTP) SetTimeout(dur time.Duration) {
122 h.debugf("setting timeout to %0.2fs\n", dur.Seconds())
123 h.timeout = dur
124 h.stop_timeouter()
125 foo_ctr++
126 h.tio = &timeouter{ch: make(chan bool), idx: foo_ctr}
127 if h.tio == nil {
128 panic("no timeouter")
129 }
130
131 go h.timeouter(h.tio)
132 }
133 func (h *cHTTP) stop_timeouter() {
134 if h.tio == nil {
135 h.debugf("no timeouter to stop\n")
136 return
137 }
138 h.debugf("stopping timeouter %d\n", h.tio.idx)
139 select {
140 case h.tio.ch <- false:
141 case <-time.After(time.Duration(10) * time.Millisecond):
142 }
143 }
144 func (h *cHTTP) SetCreds(username, password string) {
145 panic("cannot use credentials for caching http")
146 }
147
148 func (h *cHTTP) timeouter(t *timeouter) {
149 h.debugf("timeouter %d started\n", t.idx)
150 var b bool
151 ch := t.ch
152 select {
153 case b = <-ch:
154 h.debugf("timeouter %d received %v\n", t.idx, b)
155 case <-time.After(h.timeout):
156 h.debugf("timeouter %d timer-outed\n", t.idx)
157 b = true
158 }
159 if b {
160 h.ctx_cancel()
161 h.cancelled = true
162 h.debugf("timeouter %d cancelled context\n", t.idx)
163 }
164 h.debugf("timeouter %d done\n", t.idx)
165
166 }
167
168 func (h *cHTTP) debugf(format string, args ...interface{}) {
169 if !*debug {
170 return
171 }
172 sn := "[cHTTP] "
173 sx := fmt.Sprintf(format, args...)
174 fmt.Print(sn + sx)
175 }
176
View as plain text