Skip to content

Commit dc6c2ff

Browse files
committed
fix(http): refactor JSON request body
1 parent b6fcf65 commit dc6c2ff

File tree

2 files changed

+79
-3
lines changed

2 files changed

+79
-3
lines changed

api/client.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package api
22

33
import (
4-
"bytes"
54
"context"
65
"encoding/json"
76
"github.com/murphysecurity/murphysec/utils/must"
@@ -115,8 +114,10 @@ func (c *Client) POST(url *url.URL, body io.Reader) *http.Request {
115114
}
116115

117116
func (c *Client) PostJson(url *url.URL, data any) *http.Request {
118-
u := c.POST(url, bytes.NewReader(must.A(json.Marshal(data))))
119-
u.Header.Set("Content-Type", "application/json")
117+
var body = NewJsonRequestBody(data)
118+
u := c.POST(url, body)
119+
u.GetBody = body.GetBody
120+
u.Header.Set("Content-Type", "application/json; charset=utf-8")
120121
return u
121122
}
122123

api/json_request_body.go

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package api
2+
3+
import (
4+
"bufio"
5+
"encoding/json"
6+
"errors"
7+
"io"
8+
"sync/atomic"
9+
)
10+
11+
type JsonRequestBody interface {
12+
GetBody() (io.ReadCloser, error)
13+
io.ReadCloser
14+
}
15+
16+
func NewJsonRequestBody(V any) JsonRequestBody {
17+
return &jsonReqBody{v: V}
18+
}
19+
20+
type jsonReqBody struct {
21+
v any
22+
pr *io.PipeReader
23+
closed atomic.Bool
24+
}
25+
26+
func (j *jsonReqBody) GetBody() (io.ReadCloser, error) {
27+
return &jsonReqBody{v: j.v}, nil
28+
}
29+
30+
func (j *jsonReqBody) Read(p []byte) (n int, err error) {
31+
if j.closed.Load() {
32+
return 0, io.ErrClosedPipe
33+
}
34+
if j.pr == nil {
35+
var pw *io.PipeWriter
36+
j.pr, pw = io.Pipe()
37+
go func() {
38+
defer func() {
39+
r := recover()
40+
if r != nil {
41+
switch r.(type) {
42+
case error:
43+
_ = pw.CloseWithError(r.(error))
44+
default:
45+
_ = pw.CloseWithError(errors.New("panic in json encoding routing"))
46+
}
47+
}
48+
}()
49+
var bw = bufio.NewWriter(pw)
50+
defer func() { _ = pw.Close() }()
51+
var e = json.NewEncoder(pw).Encode(j.v)
52+
if e != nil {
53+
_ = pw.CloseWithError(e)
54+
return
55+
}
56+
e = bw.Flush()
57+
if e != nil {
58+
_ = pw.CloseWithError(e)
59+
return
60+
}
61+
_ = pw.Close()
62+
}()
63+
}
64+
return j.pr.Read(p)
65+
}
66+
67+
func (j *jsonReqBody) Close() error {
68+
if j.closed.Load() {
69+
return io.ErrClosedPipe
70+
}
71+
j.closed.Store(true)
72+
return j.pr.Close()
73+
}
74+
75+
var _ io.ReadCloser = &jsonReqBody{}

0 commit comments

Comments
 (0)