1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
package ui
import (
"net/http"
"sort"
"strings"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/dialog"
"fyne.io/fyne/v2/widget"
"github.com/shiv/internal/store"
"github.com/shiv/internal/ui/widgets"
)
func showInspectorDialog(tx store.Transaction, win fyne.Window) {
tabs := container.NewAppTabs()
if len(tx.ReqHeaders) > 0 {
tabs.Append(container.NewTabItem("Req Headers", buildHeadersList(tx.ReqHeaders)))
}
if len(tx.ReqBody) > 0 {
body := widgets.NewTextView()
body.SetWindow(win)
body.SetText(string(PrettyJSON(tx.ReqBody)))
tabs.Append(container.NewTabItem("Req Body", body.Build()))
}
tabs.Append(container.NewTabItem("Resp Headers", buildHeadersList(tx.RespHeaders)))
cookies := parseCookies(tx.RespHeaders)
tabs.Append(container.NewTabItem("Cookies", buildKVTable(cookies)))
if len(tx.RespBody) > 0 {
body := widgets.NewTextView()
body.SetWindow(win)
ct := tx.RespHeaders.Get("Content-Type")
if strings.Contains(ct, "application/json") {
body.SetText(string(PrettyJSON(tx.RespBody)))
tabs.Append(container.NewTabItem("JSON", body.Build()))
} else {
body.SetText(string(tx.RespBody))
tabs.Append(container.NewTabItem("Resp Body", body.Build()))
}
}
d := dialog.NewCustom("Inspector", "Close", tabs, win)
d.Resize(fyne.NewSize(700, 500))
closeOnEscape(win, d.Dismiss)
d.Show()
}
func parseCookies(headers http.Header) [][2]string {
var result [][2]string
for _, line := range headers["Set-Cookie"] {
parts := strings.SplitN(line, ";", 2)
cookieParts := strings.SplitN(strings.TrimSpace(parts[0]), "=", 2)
if len(cookieParts) == 2 {
result = append(result, [2]string{cookieParts[0], cookieParts[1]})
} else if len(cookieParts) == 1 {
result = append(result, [2]string{cookieParts[0], ""})
}
if len(parts) > 1 {
for attr := range strings.SplitSeq(parts[1], ";") {
attr = strings.TrimSpace(attr)
if attr == "" {
continue
}
attrParts := strings.SplitN(attr, "=", 2)
if len(attrParts) == 2 {
result = append(result, [2]string{" " + attrParts[0], attrParts[1]})
} else {
result = append(result, [2]string{" " + attrParts[0], ""})
}
}
}
}
return result
}
func buildHeadersList(headers http.Header) fyne.CanvasObject {
keys := make([]string, 0, len(headers))
for k := range headers {
keys = append(keys, k)
}
sort.Strings(keys)
var pairs [][2]string
for _, k := range keys {
for _, v := range headers[k] {
pairs = append(pairs, [2]string{k, v})
}
}
return buildKVTable(pairs)
}
func buildKVTable(pairs [][2]string) fyne.CanvasObject {
if len(pairs) == 0 {
l := widget.NewLabel("None")
l.Importance = widget.LowImportance
return container.NewCenter(l)
}
t := widget.NewTable(
func() (int, int) { return len(pairs), 2 },
func() fyne.CanvasObject {
l := widget.NewLabel("")
l.Truncation = fyne.TextTruncateEllipsis
return l
},
func(id widget.TableCellID, obj fyne.CanvasObject) {
l := obj.(*widget.Label)
if id.Col == 0 {
l.TextStyle = fyne.TextStyle{Bold: true}
l.SetText(pairs[id.Row][0])
} else {
l.TextStyle = fyne.TextStyle{}
l.SetText(pairs[id.Row][1])
}
},
)
t.SetColumnWidth(0, 200)
t.SetColumnWidth(1, 450)
return t
}
|