Skip to content

Commit e88cac6

Browse files
committed
fix: update examples
1 parent 4ec0020 commit e88cac6

2 files changed

Lines changed: 81 additions & 21 deletions

File tree

examples/dumper/main.go

Lines changed: 81 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
package main
22

33
import (
4+
"bytes"
5+
"compress/flate"
6+
"compress/gzip"
7+
"compress/zlib"
48
"context"
59
"crypto/tls"
6-
"encoding/hex"
710
"flag"
811
"fmt"
912
"io"
1013
"log/slog"
1114
"net"
1215
"net/http"
13-
"net/http/httputil"
1416
"os"
1517
"os/signal"
1618
"strings"
@@ -22,15 +24,68 @@ import (
2224
"github.com/josexy/mitmpgo/metadata"
2325
)
2426

27+
const CHUNK_SIZE = 512
28+
29+
const (
30+
CHUNK_TYPE_REQ = 1 << iota
31+
CHUNK_TYPE_RSP
32+
)
33+
34+
type bodyDecoder struct {
35+
reader io.ReadCloser
36+
pw *io.PipeWriter
37+
}
38+
39+
func newBodyDecoder(r io.ReadCloser, encoding string, chunkType int) (io.ReadCloser, error) {
40+
if encoding == "" {
41+
return newChunkBodyReader(r, CHUNK_SIZE, chunkType), nil
42+
}
43+
44+
pr, pw := io.Pipe()
45+
teeReader := io.TeeReader(r, pw)
46+
go func() {
47+
decodedReader, err := getDecodedReader(pr, encoding)
48+
if err != nil {
49+
// if the decoder creation fails, we need to read pr to avoid pw blocking
50+
io.Copy(io.Discard, pr)
51+
return
52+
}
53+
decodedReader = newChunkBodyReader(decodedReader, CHUNK_SIZE, chunkType)
54+
defer decodedReader.Close()
55+
// need to read all data to avoid pw blocking, but we don't care about the decoded data here, so just discard it
56+
io.Copy(io.Discard, decodedReader)
57+
}()
58+
return &bodyDecoder{
59+
reader: io.NopCloser(teeReader),
60+
pw: pw,
61+
}, nil
62+
}
63+
64+
func (b *bodyDecoder) Close() error {
65+
return b.reader.Close()
66+
}
67+
68+
func (b *bodyDecoder) Read(p []byte) (n int, err error) {
69+
n, err = b.reader.Read(p)
70+
if err == io.EOF {
71+
// when reader is closed or reaches EOF, we should also close the pipe writer to avoid goroutine leak
72+
b.pw.CloseWithError(err)
73+
}
74+
return
75+
}
76+
2577
type chunkBodyReader struct {
2678
io.ReadCloser
27-
N int64
79+
N int64
80+
buf bytes.Buffer // or use buf pool?
81+
chunkType int
2882
}
2983

30-
func newChunkBodyReader(r io.ReadCloser, chunkBodySize int64) *chunkBodyReader {
84+
func newChunkBodyReader(r io.ReadCloser, chunkBodySize int64, chunkType int) io.ReadCloser {
3185
return &chunkBodyReader{
3286
N: chunkBodySize,
3387
ReadCloser: r,
88+
chunkType: chunkType,
3489
}
3590
}
3691

@@ -43,7 +98,11 @@ func (r *chunkBodyReader) Read(p []byte) (n int, err error) {
4398
}
4499
n, err = r.ReadCloser.Read(p)
45100
if n > 0 {
46-
fmt.Printf("--> hex dump(chunk size/data size: %d/%d):\n%s\n", r.N, n, hex.Dump(p[:n]))
101+
r.buf.Write(p[:n])
102+
// fmt.Printf("--> hex dump(chunk size/data size: %d/%d):\n%s\n", r.N, n, hex.Dump(p[:n]))
103+
}
104+
if err == io.EOF {
105+
fmt.Printf("<<-- [%d]full data dump (%d bytes):\n%s\n", r.chunkType, r.buf.Len(), r.buf.Bytes())
47106
}
48107
return
49108
}
@@ -178,12 +237,7 @@ func httpInterceptor(ctx context.Context, req *http.Request, invoker mitmpgo.HTT
178237
)
179238
}
180239

181-
if md.StreamBody {
182-
req.Body = newChunkBodyReader(req.Body, 512)
183-
} else {
184-
data, _ := httputil.DumpRequest(req, true)
185-
fmt.Println("request:", string(data))
186-
}
240+
req.Body, _ = newBodyDecoder(req.Body, "", CHUNK_TYPE_REQ)
187241

188242
rsp, err := invoker.Invoke(req)
189243
if err != nil {
@@ -198,12 +252,7 @@ func httpInterceptor(ctx context.Context, req *http.Request, invoker mitmpgo.HTT
198252
slog.String("protocol", rsp.Proto),
199253
)
200254

201-
if md.StreamBody {
202-
rsp.Body = newChunkBodyReader(rsp.Body, 512)
203-
} else {
204-
data, _ := httputil.DumpResponse(rsp, true)
205-
fmt.Println("response:", string(data))
206-
}
255+
rsp.Body, err = newBodyDecoder(rsp.Body, rsp.Header.Get("Content-Encoding"), CHUNK_TYPE_RSP)
207256

208257
return rsp, err
209258
}
@@ -248,3 +297,18 @@ func websocketInterceptor(ctx context.Context, dir mitmpgo.WSDirection, msgType
248297
// }
249298
return wdi.Invoke(msgType, b)
250299
}
300+
301+
func getDecodedReader(r io.Reader, encoding string) (io.ReadCloser, error) {
302+
switch encoding {
303+
case "gzip":
304+
return gzip.NewReader(r)
305+
case "deflate":
306+
zr, err := zlib.NewReader(r)
307+
if err != nil {
308+
return io.NopCloser(flate.NewReader(r)), nil
309+
}
310+
return zr, nil
311+
default: // other encodings...
312+
return io.NopCloser(r), nil
313+
}
314+
}

go.sum

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
22
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
3-
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
4-
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
53
golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
64
golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
7-
golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
8-
golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
95
golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU=
106
golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=

0 commit comments

Comments
 (0)