...
1 package playwright
2
3 import (
4 "bufio"
5 "encoding/binary"
6 "errors"
7 "fmt"
8 "io"
9 "log"
10 "os"
11 "sync"
12
13 "gopkg.in/square/go-jose.v2/json"
14 )
15
16 type pipeTransport struct {
17 stdin io.WriteCloser
18 stdout io.ReadCloser
19 onmessage func(msg *message)
20 rLock sync.Mutex
21 }
22
23 func (t *pipeTransport) Start() error {
24 reader := bufio.NewReader(t.stdout)
25 for {
26 lengthContent := make([]byte, 4)
27 _, err := io.ReadFull(reader, lengthContent)
28 if err == io.EOF || errors.Is(err, os.ErrClosed) {
29 return nil
30 } else if err != nil {
31 return fmt.Errorf("could not read padding: %w", err)
32 }
33 length := binary.LittleEndian.Uint32(lengthContent)
34
35 msg := &message{}
36 if err := json.NewDecoder(io.LimitReader(reader, int64(length))).Decode(&msg); err != nil {
37 return fmt.Errorf("could not decode json: %w", err)
38 }
39 if os.Getenv("DEBUGP") != "" {
40 fmt.Print("RECV>")
41 if err := json.NewEncoder(os.Stderr).Encode(msg); err != nil {
42 log.Printf("could not encode json: %v", err)
43 }
44 }
45 t.onmessage(msg)
46 }
47 }
48
49 type errorPayload struct {
50 Name string `json:"name"`
51 Message string `json:"message"`
52 Stack string `json:"stack"`
53 }
54
55 type message struct {
56 ID int `json:"id"`
57 GUID string `json:"guid"`
58 Method string `json:"method"`
59 Params map[string]interface{} `json:"params"`
60 Result interface{} `json:"result"`
61 Error *struct {
62 Error errorPayload `json:"error"`
63 } `json:"error"`
64 }
65
66 func (t *pipeTransport) Send(message map[string]interface{}) error {
67 msg, err := json.Marshal(message)
68 if err != nil {
69 return fmt.Errorf("could not marshal json: %w", err)
70 }
71 if os.Getenv("DEBUGP") != "" {
72 fmt.Print("SEND>")
73 if err := json.NewEncoder(os.Stderr).Encode(message); err != nil {
74 log.Printf("could not encode json: %v", err)
75 }
76 }
77 lengthPadding := make([]byte, 4)
78 t.rLock.Lock()
79 defer t.rLock.Unlock()
80 binary.LittleEndian.PutUint32(lengthPadding, uint32(len(msg)))
81 if _, err = t.stdin.Write(lengthPadding); err != nil {
82 return err
83 }
84 if _, err = t.stdin.Write(msg); err != nil {
85 return err
86 }
87 return nil
88 }
89
90 func newPipeTransport(stdin io.WriteCloser, stdout io.ReadCloser) *pipeTransport {
91 return &pipeTransport{
92 stdout: stdout,
93 stdin: stdin,
94 }
95 }
96
View as plain text