github.com/philippseith/signalr@v0.6.3/clientsseconnection.go (about) 1 package signalr 2 3 import ( 4 "bytes" 5 "context" 6 "fmt" 7 "io" 8 "net/http" 9 "net/url" 10 "strings" 11 ) 12 13 type clientSSEConnection struct { 14 ConnectionBase 15 reqURL string 16 sseReader io.Reader 17 sseWriter io.Writer 18 } 19 20 func newClientSSEConnection(address string, connectionID string, body io.ReadCloser) (*clientSSEConnection, error) { 21 // Setup request 22 reqURL, err := url.Parse(address) 23 if err != nil { 24 return nil, err 25 } 26 q := reqURL.Query() 27 q.Set("id", connectionID) 28 reqURL.RawQuery = q.Encode() 29 c := clientSSEConnection{ 30 ConnectionBase: ConnectionBase{ 31 ctx: context.Background(), 32 connectionID: connectionID, 33 }, 34 reqURL: reqURL.String(), 35 } 36 c.sseReader, c.sseWriter = io.Pipe() 37 go func() { 38 defer func() { closeResponseBody(body) }() 39 p := make([]byte, 1<<15) 40 loop: 41 for { 42 n, err := body.Read(p) 43 if err != nil { 44 break loop 45 } 46 lines := strings.Split(string(p[:n]), "\n") 47 for _, line := range lines { 48 line = strings.Trim(line, "\r\t ") 49 // Ignore everything but data 50 if strings.Index(line, "data:") != 0 { 51 continue 52 } 53 json := strings.Replace(strings.Trim(line, "\r"), "data:", "", 1) 54 // Spec says: If it starts with Space, remove it 55 if len(json) > 0 && json[0] == ' ' { 56 json = json[1:] 57 } 58 _, err = c.sseWriter.Write([]byte(json)) 59 if err != nil { 60 break loop 61 } 62 } 63 } 64 }() 65 return &c, nil 66 } 67 68 func (c *clientSSEConnection) Read(p []byte) (n int, err error) { 69 return c.sseReader.Read(p) 70 } 71 72 func (c *clientSSEConnection) Write(p []byte) (n int, err error) { 73 req, err := http.NewRequest("POST", c.reqURL, bytes.NewReader(p)) 74 if err != nil { 75 return 0, err 76 } 77 client := &http.Client{} 78 resp, err := client.Do(req) 79 if err != nil { 80 return 0, err 81 } 82 if resp.StatusCode != 200 { 83 err = fmt.Errorf("POST %v -> %v", c.reqURL, resp.Status) 84 } 85 closeResponseBody(resp.Body) 86 return len(p), err 87 }