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