go-micro.dev/v5@v5.12.0/transport/http_socket.go (about) 1 package transport 2 3 import ( 4 "bufio" 5 "bytes" 6 "io" 7 "net" 8 "net/http" 9 "sync" 10 "time" 11 12 "github.com/pkg/errors" 13 ) 14 15 type httpTransportSocket struct { 16 w http.ResponseWriter 17 18 // the hijacked when using http 1 19 conn net.Conn 20 ht *httpTransport 21 r *http.Request 22 rw *bufio.ReadWriter 23 24 // for the first request 25 ch chan *http.Request 26 27 // h2 things 28 buf *bufio.Reader 29 // indicate if socket is closed 30 closed chan bool 31 32 // local/remote ip 33 local string 34 remote string 35 36 mtx sync.RWMutex 37 } 38 39 func (h *httpTransportSocket) Local() string { 40 return h.local 41 } 42 43 func (h *httpTransportSocket) Remote() string { 44 return h.remote 45 } 46 47 func (h *httpTransportSocket) Recv(msg *Message) error { 48 if msg == nil { 49 return errors.New("message passed in is nil") 50 } 51 52 if msg.Header == nil { 53 msg.Header = make(map[string]string, len(h.r.Header)) 54 } 55 56 if h.r.ProtoMajor == 1 { 57 return h.recvHTTP1(msg) 58 } 59 60 return h.recvHTTP2(msg) 61 } 62 63 func (h *httpTransportSocket) Send(msg *Message) error { 64 // we need to lock to protect the write 65 h.mtx.RLock() 66 defer h.mtx.RUnlock() 67 68 if h.r.ProtoMajor == 1 { 69 return h.sendHTTP1(msg) 70 } 71 72 return h.sendHTTP2(msg) 73 } 74 75 func (h *httpTransportSocket) Close() error { 76 h.mtx.Lock() 77 defer h.mtx.Unlock() 78 79 select { 80 case <-h.closed: 81 return nil 82 default: 83 // Close the channel 84 close(h.closed) 85 86 // Close the buffer 87 if err := h.r.Body.Close(); err != nil { 88 return err 89 } 90 } 91 92 return nil 93 } 94 95 func (h *httpTransportSocket) error(m *Message) error { 96 if h.r.ProtoMajor == 1 { 97 rsp := &http.Response{ 98 Header: make(http.Header), 99 Body: io.NopCloser(bytes.NewReader(m.Body)), 100 Status: "500 Internal Server Error", 101 StatusCode: http.StatusInternalServerError, 102 Proto: "HTTP/1.1", 103 ProtoMajor: 1, 104 ProtoMinor: 1, 105 ContentLength: int64(len(m.Body)), 106 } 107 108 for k, v := range m.Header { 109 rsp.Header.Set(k, v) 110 } 111 112 return rsp.Write(h.conn) 113 } 114 115 return nil 116 } 117 118 func (h *httpTransportSocket) recvHTTP1(msg *Message) error { 119 // set timeout if its greater than 0 120 if h.ht.opts.Timeout > time.Duration(0) { 121 if err := h.conn.SetDeadline(time.Now().Add(h.ht.opts.Timeout)); err != nil { 122 return errors.Wrap(err, "failed to set deadline") 123 } 124 } 125 126 var req *http.Request 127 128 select { 129 // get first request 130 case req = <-h.ch: 131 // read next request 132 default: 133 rr, err := http.ReadRequest(h.rw.Reader) 134 if err != nil { 135 return errors.Wrap(err, "failed to read request") 136 } 137 138 req = rr 139 } 140 141 // read body 142 b, err := io.ReadAll(req.Body) 143 if err != nil { 144 return errors.Wrap(err, "failed to read body") 145 } 146 147 // set body 148 if err := req.Body.Close(); err != nil { 149 return errors.Wrap(err, "failed to close body") 150 } 151 152 msg.Body = b 153 154 // set headers 155 for k, v := range req.Header { 156 if len(v) > 0 { 157 msg.Header[k] = v[0] 158 } else { 159 msg.Header[k] = "" 160 } 161 } 162 163 // return early early 164 return nil 165 } 166 167 func (h *httpTransportSocket) recvHTTP2(msg *Message) error { 168 // only process if the socket is open 169 select { 170 case <-h.closed: 171 return io.EOF 172 default: 173 } 174 175 // buffer pool for reuse 176 var bufPool = getHTTP2BufPool() 177 178 // set max buffer size 179 s := h.ht.opts.BuffSizeH2 180 if s == 0 { 181 s = DefaultBufSizeH2 182 } 183 184 buf := bufPool.Get().([]byte) 185 if cap(buf) < s { 186 buf = make([]byte, s) 187 } 188 buf = buf[:s] 189 190 n, err := h.buf.Read(buf) 191 if err != nil { 192 bufPool.Put(buf) 193 return err 194 } 195 196 if n > 0 { 197 msg.Body = make([]byte, n) 198 copy(msg.Body, buf[:n]) 199 } 200 bufPool.Put(buf) 201 202 for k, v := range h.r.Header { 203 if len(v) > 0 { 204 msg.Header[k] = v[0] 205 } else { 206 msg.Header[k] = "" 207 } 208 } 209 210 msg.Header[":path"] = h.r.URL.Path 211 212 return nil 213 } 214 215 func (h *httpTransportSocket) sendHTTP1(msg *Message) error { 216 // make copy of header 217 hdr := make(http.Header) 218 for k, v := range h.r.Header { 219 hdr[k] = v 220 } 221 222 rsp := &http.Response{ 223 Header: hdr, 224 Body: io.NopCloser(bytes.NewReader(msg.Body)), 225 Status: "200 OK", 226 StatusCode: http.StatusOK, 227 Proto: "HTTP/1.1", 228 ProtoMajor: 1, 229 ProtoMinor: 1, 230 ContentLength: int64(len(msg.Body)), 231 } 232 233 for k, v := range msg.Header { 234 rsp.Header.Set(k, v) 235 } 236 237 // set timeout if its greater than 0 238 if h.ht.opts.Timeout > time.Duration(0) { 239 if err := h.conn.SetDeadline(time.Now().Add(h.ht.opts.Timeout)); err != nil { 240 return err 241 } 242 } 243 244 return rsp.Write(h.conn) 245 } 246 247 func (h *httpTransportSocket) sendHTTP2(msg *Message) error { 248 // only process if the socket is open 249 select { 250 case <-h.closed: 251 return io.EOF 252 default: 253 } 254 255 // set headers 256 for k, v := range msg.Header { 257 h.w.Header().Set(k, v) 258 } 259 260 // write request 261 _, err := h.w.Write(msg.Body) 262 263 // flush the trailers 264 h.w.(http.Flusher).Flush() 265 266 return err 267 }