@@ -20,21 +20,11 @@ import (
20
20
type DialerClient interface {
21
21
IsClosed () bool
22
22
23
- // (ctx, baseURL, payload) -> err
24
- // baseURL already contains sessionId and seq
25
- SendUploadRequest (context.Context , string , io.ReadWriteCloser , int64 ) error
23
+ // ctx, url, body, uploadOnly
24
+ OpenStream (context.Context , string , io.Reader , bool ) (io.ReadCloser , net.Addr , net.Addr , error )
26
25
27
- // (ctx, baseURL) -> (downloadReader, remoteAddr, localAddr)
28
- // baseURL already contains sessionId
29
- OpenDownload (context.Context , string ) (io.ReadCloser , net.Addr , net.Addr , error )
30
-
31
- // (ctx, baseURL) -> uploadWriter
32
- // baseURL already contains sessionId
33
- OpenUpload (context.Context , string ) io.WriteCloser
34
-
35
- // (ctx, pureURL) -> (uploadWriter, downloadReader)
36
- // pureURL can not contain sessionId
37
- Open (context.Context , string ) (io.WriteCloser , io.ReadCloser )
26
+ // ctx, url, body, contentLength
27
+ PostPacket (context.Context , string , io.Reader , int64 ) error
38
28
}
39
29
40
30
// implements splithttp.DialerClient in terms of direct network connections
@@ -52,136 +42,56 @@ func (c *DefaultDialerClient) IsClosed() bool {
52
42
return c .closed
53
43
}
54
44
55
- func (c * DefaultDialerClient ) Open (ctx context.Context , pureURL string ) (io.WriteCloser , io.ReadCloser ) {
56
- reader , writer := io .Pipe ()
57
- req , _ := http .NewRequestWithContext (ctx , "POST" , pureURL , reader )
58
- req .Header = c .transportConfig .GetRequestHeader ()
59
- if ! c .transportConfig .NoGRPCHeader {
60
- req .Header .Set ("Content-Type" , "application/grpc" )
61
- }
62
- wrc := & WaitReadCloser {Wait : make (chan struct {})}
63
- go func () {
64
- response , err := c .client .Do (req )
65
- if err != nil || response .StatusCode != 200 {
66
- if err != nil {
67
- errors .LogInfoInner (ctx , err , "failed to open " , pureURL )
68
- } else {
69
- // c.closed = true
70
- response .Body .Close ()
71
- errors .LogInfo (ctx , "unexpected status " , response .StatusCode )
72
- }
73
- wrc .Close ()
74
- return
75
- }
76
- wrc .Set (response .Body )
77
- }()
78
- return writer , wrc
79
- }
80
-
81
- func (c * DefaultDialerClient ) OpenUpload (ctx context.Context , baseURL string ) io.WriteCloser {
82
- reader , writer := io .Pipe ()
83
- req , _ := http .NewRequestWithContext (ctx , "POST" , baseURL , reader )
84
- req .Header = c .transportConfig .GetRequestHeader ()
85
- if ! c .transportConfig .NoGRPCHeader {
86
- req .Header .Set ("Content-Type" , "application/grpc" )
87
- }
88
- go func () {
89
- if resp , err := c .client .Do (req ); err == nil {
90
- if resp .StatusCode != 200 {
91
- // c.closed = true
92
- }
93
- resp .Body .Close ()
94
- }
95
- }()
96
- return writer
97
- }
98
-
99
- func (c * DefaultDialerClient ) OpenDownload (ctx context.Context , baseURL string ) (io.ReadCloser , gonet.Addr , gonet.Addr , error ) {
100
- var remoteAddr gonet.Addr
101
- var localAddr gonet.Addr
45
+ func (c * DefaultDialerClient ) OpenStream (ctx context.Context , url string , body io.Reader , uploadOnly bool ) (wrc io.ReadCloser , remoteAddr , localAddr gonet.Addr , err error ) {
102
46
// this is done when the TCP/UDP connection to the server was established,
103
47
// and we can unblock the Dial function and print correct net addresses in
104
48
// logs
105
49
gotConn := done .New ()
50
+ ctx = httptrace .WithClientTrace (ctx , & httptrace.ClientTrace {
51
+ GotConn : func (connInfo httptrace.GotConnInfo ) {
52
+ remoteAddr = connInfo .Conn .RemoteAddr ()
53
+ localAddr = connInfo .Conn .LocalAddr ()
54
+ gotConn .Close ()
55
+ },
56
+ })
106
57
107
- var downResponse io.ReadCloser
108
- gotDownResponse := done .New ()
109
-
110
- ctx , ctxCancel := context .WithCancel (ctx )
58
+ method := "GET"
59
+ if body != nil {
60
+ method = "POST"
61
+ }
62
+ req , _ := http .NewRequestWithContext (ctx , method , url , body )
63
+ req .Header = c .transportConfig .GetRequestHeader ()
64
+ if method == "POST" && ! c .transportConfig .NoGRPCHeader {
65
+ req .Header .Set ("Content-Type" , "application/grpc" )
66
+ }
111
67
68
+ wrc = & WaitReadCloser {Wait : make (chan struct {})}
112
69
go func () {
113
- trace := & httptrace.ClientTrace {
114
- GotConn : func (connInfo httptrace.GotConnInfo ) {
115
- remoteAddr = connInfo .Conn .RemoteAddr ()
116
- localAddr = connInfo .Conn .LocalAddr ()
117
- gotConn .Close ()
118
- },
119
- }
120
-
121
- // in case we hit an error, we want to unblock this part
122
- defer gotConn .Close ()
123
-
124
- ctx = httptrace .WithClientTrace (ctx , trace )
125
-
126
- req , err := http .NewRequestWithContext (
127
- ctx ,
128
- "GET" ,
129
- baseURL ,
130
- nil ,
131
- )
132
- if err != nil {
133
- errors .LogInfoInner (ctx , err , "failed to construct download http request" )
134
- gotDownResponse .Close ()
135
- return
136
- }
137
-
138
- req .Header = c .transportConfig .GetRequestHeader ()
139
-
140
- response , err := c .client .Do (req )
141
- gotConn .Close ()
70
+ resp , err := c .client .Do (req )
142
71
if err != nil {
143
- errors .LogInfoInner (ctx , err , "failed to send download http request" )
144
- gotDownResponse .Close ()
72
+ errors .LogInfoInner (ctx , err , "failed to " + method + " " + url )
73
+ gotConn .Close ()
74
+ wrc .Close ()
145
75
return
146
76
}
147
-
148
- if response .StatusCode != 200 {
77
+ if resp .StatusCode != 200 && ! uploadOnly {
149
78
// c.closed = true
150
- response .Body .Close ()
151
- errors .LogInfo (ctx , "invalid status code on download:" , response .Status )
152
- gotDownResponse .Close ()
79
+ errors .LogInfo (ctx , "unexpected status " , resp .StatusCode )
80
+ }
81
+ if resp .StatusCode != 200 || uploadOnly {
82
+ resp .Body .Close ()
83
+ wrc .Close ()
153
84
return
154
85
}
155
-
156
- downResponse = response .Body
157
- gotDownResponse .Close ()
86
+ wrc .(* WaitReadCloser ).Set (resp .Body )
158
87
}()
159
88
160
89
<- gotConn .Wait ()
161
-
162
- lazyDownload := & LazyReader {
163
- CreateReader : func () (io.Reader , error ) {
164
- <- gotDownResponse .Wait ()
165
- if downResponse == nil {
166
- return nil , errors .New ("downResponse failed" )
167
- }
168
- return downResponse , nil
169
- },
170
- }
171
-
172
- // workaround for https://github.com/quic-go/quic-go/issues/2143 --
173
- // always cancel request context so that Close cancels any Read.
174
- // Should then match the behavior of http2 and http1.
175
- reader := downloadBody {
176
- lazyDownload ,
177
- ctxCancel ,
178
- }
179
-
180
- return reader , remoteAddr , localAddr , nil
90
+ return
181
91
}
182
92
183
- func (c * DefaultDialerClient ) SendUploadRequest (ctx context.Context , url string , payload io.ReadWriteCloser , contentLength int64 ) error {
184
- req , err := http .NewRequestWithContext (ctx , "POST" , url , payload )
93
+ func (c * DefaultDialerClient ) PostPacket (ctx context.Context , url string , body io.Reader , contentLength int64 ) error {
94
+ req , err := http .NewRequestWithContext (ctx , "POST" , url , body )
185
95
if err != nil {
186
96
return err
187
97
}
@@ -257,16 +167,6 @@ func (c *DefaultDialerClient) SendUploadRequest(ctx context.Context, url string,
257
167
return nil
258
168
}
259
169
260
- type downloadBody struct {
261
- io.Reader
262
- cancel context.CancelFunc
263
- }
264
-
265
- func (c downloadBody ) Close () error {
266
- c .cancel ()
267
- return nil
268
- }
269
-
270
170
type WaitReadCloser struct {
271
171
Wait chan struct {}
272
172
io.ReadCloser
0 commit comments