返回 DeepSeek-Reasonix
bootstrap.go
根目录 / internal / extension / rpcwire / bootstrap.go
1 package rpcwire
2
3 import (
4 "bufio"
5 "encoding/json"
6 "errors"
7 "io"
8 )
9
10 // StrictRequestFrame is one validated JSON-RPC 2.0 NDJSON request. Raw retains
11 // the exact bytes consumed from the reader, including line ending and harmless
12 // surrounding whitespace, so a bootstrap proxy can forward it unchanged.
13 type StrictRequestFrame struct {
14 Raw []byte
15 ID json.RawMessage
16 Method string
17 Params json.RawMessage
18 }
19
20 // ResponseIDForError returns an ID that is safe to place in a JSON-RPC error
21 // response. Invalid request IDs must never be reflected back because doing so
22 // would make the error response invalid too. Missing and invalid IDs therefore
23 // become null; valid string, integer, and null IDs retain their value.
24 func ResponseIDForError(id json.RawMessage) json.RawMessage {
25 id = trimSpace(id)
26 if !validRPCID(id) {
27 return json.RawMessage("null")
28 }
29 return append(json.RawMessage(nil), id...)
30 }
31
32 // ReadStrictRequestFrame reads exactly one request while retaining br and any
33 // buffered remainder for subsequent proxying. It shares rpcwire's strict frame
34 // validator and inbound byte-limit semantics.
35 func ReadStrictRequestFrame(br *bufio.Reader, maxBytes int) (StrictRequestFrame, error) {
36 var raw []byte
37 for {
38 chunk, err := br.ReadSlice('\n')
39 raw = append(raw, chunk...)
40 if maxBytes > 0 && len(raw) > maxBytes {
41 return StrictRequestFrame{Raw: append([]byte(nil), raw...)}, &FrameTooLargeError{Direction: "inbound", Size: len(raw), Limit: maxBytes}
42 }
43 if errors.Is(err, bufio.ErrBufferFull) {
44 continue
45 }
46 if err != nil && !errors.Is(err, io.EOF) {
47 return StrictRequestFrame{}, err
48 }
49 if len(raw) == 0 {
50 return StrictRequestFrame{}, io.EOF
51 }
52 break
53 }
54
55 payload := trimSpace(raw)
56 var in inbound
57 if err := json.Unmarshal(payload, &in); err != nil {
58 return StrictRequestFrame{Raw: append([]byte(nil), raw...)}, err
59 }
60 frame := StrictRequestFrame{
61 Raw: append([]byte(nil), raw...), ID: append(json.RawMessage(nil), in.ID...),
62 Method: in.Method, Params: append(json.RawMessage(nil), in.Params...),
63 }
64 if err := validateStrictFrame(payload, in); err != nil {
65 return frame, err
66 }
67 if in.Method == "" || len(in.ID) == 0 {
68 return frame, errors.New("rpcwire: bootstrap frame must be a request")
69 }
70 return frame, nil
71 }
72
72 lines GO