github.com/ronaksoft/rony@v0.16.26-0.20230807065236-1743dbfe6959/edgec/http_conn.go (about) 1 package edgec 2 3 import ( 4 "net/http" 5 "time" 6 7 "github.com/ronaksoft/rony" 8 "github.com/ronaksoft/rony/log" 9 "github.com/ronaksoft/rony/pools" 10 "github.com/valyala/fasthttp" 11 "go.uber.org/zap" 12 "google.golang.org/protobuf/proto" 13 ) 14 15 /* 16 Creation Time: 2021 - Jan - 05 17 Created by: (ehsan) 18 Maintainers: 19 1. Ehsan N. Moosa (E2) 20 Auditor: Ehsan N. Moosa (E2) 21 Copyright Ronak Software Group 2020 22 */ 23 24 type httpConn struct { 25 h *Http 26 replicaSet uint64 27 id string 28 hostPorts []string 29 secure bool 30 } 31 32 func (c *httpConn) send(req, res *rony.MessageEnvelope, timeout time.Duration) (replicaSet uint64, err error) { 33 replicaSet = c.replicaSet 34 35 mo := proto.MarshalOptions{UseCachedSize: true} 36 buf := pools.Buffer.GetCap(mo.Size(req)) 37 defer pools.Buffer.Put(buf) 38 39 b, err := mo.MarshalAppend(*buf.Bytes(), req) 40 if err != nil { 41 return 42 } 43 44 httpReq := fasthttp.AcquireRequest() 45 defer fasthttp.ReleaseRequest(httpReq) 46 47 httpReq.Header.SetMethod(http.MethodPost) 48 if c.secure { 49 httpReq.URI().SetScheme("https") 50 } 51 httpReq.SetHost(c.hostPorts[0]) 52 httpReq.SetBody(b) 53 if hf := c.h.cfg.HeaderFunc; hf != nil { 54 for k, v := range hf() { 55 httpReq.Header.Set(k, v) 56 } 57 } 58 59 httpRes := fasthttp.AcquireResponse() 60 defer fasthttp.ReleaseResponse(httpRes) 61 62 SendLoop: 63 err = c.h.c.DoTimeout(httpReq, httpRes, timeout) 64 switch err { 65 case fasthttp.ErrNoFreeConns: 66 goto SendLoop 67 } 68 if err != nil { 69 return 70 } 71 err = res.Unmarshal(httpRes.Body()) 72 if err != nil { 73 return 74 } 75 switch res.GetConstructor() { 76 case rony.C_Redirect: 77 x := &rony.Redirect{} 78 err = proto.Unmarshal(res.Message, x) 79 if err != nil { 80 return 81 } 82 replicaSet, err = c.redirect(x) 83 84 return 85 } 86 87 return 88 } 89 90 func (c *httpConn) redirect(x *rony.Redirect) (replicaSet uint64, err error) { 91 if ce := c.h.logger.Check(log.InfoLevel, "Redirect"); ce != nil { 92 ce.Write( 93 zap.Any("Edges", x.Edges), 94 zap.Any("Wait", x.WaitInSec), 95 ) 96 } 97 98 replicaSet = x.Edges[0].ReplicaSet 99 for _, n := range x.Edges { 100 c.h.addConn(n.ServerID, n.ReplicaSet, c.h.newConn(n.ServerID, n.ReplicaSet, n.HostPorts...)) 101 } 102 103 switch x.Reason { 104 case rony.RedirectReason_ReplicaSetSession: 105 c.h.sessionReplica = replicaSet 106 err = ErrReplicaSetSession 107 case rony.RedirectReason_ReplicaSetRequest: 108 replicaSet = x.Edges[0].ReplicaSet 109 err = ErrReplicaSetRequest 110 default: 111 err = ErrUnknownResponse 112 } 113 114 return 115 }