Skip to content

Commit e9f5500

Browse files
committed
Add details flag
This will print all headers in a table under the incoming request when the --details flag is passed to the CLI. Header keys are sorted alphabetically. Default option for the flag is set to false.
1 parent 3ee18a0 commit e9f5500

File tree

7 files changed

+111
-7
lines changed

7 files changed

+111
-7
lines changed

cmd/protocol.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ func init() {
2020
}
2121

2222
func http(cmd *cobra.Command, args []string) {
23-
renderer := &renderer.Printer{Port: Port, Addr: Address, BuildInfo: BuildInfo}
23+
renderer := &renderer.Printer{Port: Port, Addr: Address, BuildInfo: BuildInfo, Details: Details}
2424
httpServer := server.Http{Addr: Address, Port: Port, ResponseCode: ResponseCode, Output: renderer}
2525
httpServer.Start()
2626
}

cmd/root.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ var (
88
Port int
99
ResponseCode int
1010
BuildInfo map[string]string
11+
Details bool
1112
)
1213

1314
var rootCmd = &cobra.Command{
@@ -26,4 +27,5 @@ func init() {
2627
rootCmd.PersistentFlags().IntVarP(&Port, "port", "p", 8080, "sets the port for the endpoint")
2728
rootCmd.PersistentFlags().StringVarP(&Address, "address", "a", "localhost", "sets the address for the endpoint")
2829
rootCmd.PersistentFlags().IntVarP(&ResponseCode, "response_code", "r", 200, "sets the response code")
30+
rootCmd.PersistentFlags().BoolVar(&Details, "details", false, "shows header details in the request")
2931
}

pkg/renderer/printer.go

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import (
44
"fmt"
55
"log"
66
"os"
7+
"sort"
8+
"strings"
79

810
"github.com/aaronvb/logrequest"
911
"github.com/pterm/pterm"
@@ -21,6 +23,9 @@ type Printer struct {
2123

2224
// Contains build info
2325
BuildInfo map[string]string
26+
27+
// Determines if header details should be shown with the request
28+
Details bool
2429
}
2530

2631
// Start renders the initial header and the spinner. The Spinner should be consistent during
@@ -63,7 +68,7 @@ func (p *Printer) Fatal(err error) {
6368
}
6469

6570
// IncomingRequest handles the output for incoming requests to the server.
66-
func (p *Printer) IncomingRequest(fields logrequest.RequestFields, params string) {
71+
func (p *Printer) IncomingRequest(fields logrequest.RequestFields, params string, headers map[string][]string) {
6772
p.Spinner.Stop()
6873
prefix := pterm.Prefix{
6974
Text: fields.Method,
@@ -72,6 +77,12 @@ func (p *Printer) IncomingRequest(fields logrequest.RequestFields, params string
7277

7378
text := p.incomingRequestText(fields, params)
7479
pterm.Info.WithPrefix(prefix).Println(text)
80+
81+
if p.Details {
82+
table := p.incomingRequestHeadersTable(headers)
83+
pterm.Printf("%s\n\n", table)
84+
}
85+
7586
p.startSpinner()
7687
}
7788

@@ -85,6 +96,35 @@ func (p *Printer) incomingRequestText(fields logrequest.RequestFields, params st
8596
return text
8697
}
8798

99+
// incomingRequestHeadersTable constructs the headers table string.
100+
// This takes the headers map from the request and sorts it alphabetically by key.
101+
func (p *Printer) incomingRequestHeadersTable(headers map[string][]string) string {
102+
keys := make([]string, 0, len(headers))
103+
for key := range headers {
104+
keys = append(keys, key)
105+
}
106+
107+
sort.Strings(keys)
108+
109+
var headersFormatted [][]string
110+
111+
headerRow := []string{"Header", "Value"}
112+
headersFormatted = append(headersFormatted, headerRow)
113+
114+
for _, key := range keys {
115+
value := strings.Join(headers[key], ",")
116+
headersRow := []string{key, value}
117+
headersFormatted = append(headersFormatted, headersRow)
118+
}
119+
120+
headersTable, err := pterm.DefaultTable.WithHasHeader().WithData(headersFormatted).Srender()
121+
if err != nil {
122+
pterm.Error.WithShowLineNumber(false).Println(err)
123+
}
124+
125+
return headersTable
126+
}
127+
88128
// Create the spinner which will be displayed at the bottom.
89129
func (p *Printer) startSpinner() {
90130
listeningText := pterm.DefaultBasicText.

pkg/renderer/printer_test.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,27 @@ func TestIncomingRequestText(t *testing.T) {
3434
t.Errorf("Expected %s, got %s", expected, result)
3535
}
3636
}
37+
38+
func TestIncomingRequestHeadersTables(t *testing.T) {
39+
pterm.DisableColor()
40+
printer := Printer{}
41+
headers := map[string][]string{
42+
"hello": {"world", "foobar"},
43+
"foo": {"bar"},
44+
}
45+
result := printer.incomingRequestHeadersTable(headers)
46+
47+
headersForTable := [][]string{}
48+
headersForTable = append(headersForTable, []string{"Header", "Value"})
49+
headersForTable = append(headersForTable, []string{"foo", "bar"})
50+
headersForTable = append(headersForTable, []string{"hello", "world,foobar"})
51+
52+
expected, err := pterm.DefaultTable.WithHasHeader().WithData(headersForTable).Srender()
53+
if err != nil {
54+
t.Error(err)
55+
}
56+
57+
if result != expected {
58+
t.Errorf("Expected %s, got %s", expected, result)
59+
}
60+
}

pkg/renderer/renderer.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,5 @@ type Renderer interface {
1818
// Fatal is used when we need to display a message and should always exit the CLI.
1919
Fatal(error)
2020

21-
IncomingRequest(logrequest.RequestFields, string)
21+
IncomingRequest(logrequest.RequestFields, string, map[string][]string)
2222
}

pkg/server/http.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,6 @@ func (s *Http) logRequest(next http.Handler) http.Handler {
6363
lr := logrequest.LogRequest{Request: r, Writer: w, Handler: next}
6464
fields := lr.ToFields()
6565
params := logparams.LogParams{Request: r, HidePrefix: true}
66-
s.Output.IncomingRequest(fields, params.ToString())
66+
s.Output.IncomingRequest(fields, params.ToString(), r.Header)
6767
})
6868
}

pkg/server/http_test.go

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,18 @@ import (
1212
)
1313

1414
type MockPrinter struct {
15-
fields logrequest.RequestFields
16-
params string
15+
fields logrequest.RequestFields
16+
params string
17+
headers map[string][]string
1718
}
1819

1920
func (mp *MockPrinter) Fatal(error) {}
2021
func (mp *MockPrinter) Start() {}
2122
func (mp *MockPrinter) ErrorLogger() *log.Logger { return log.New(os.Stderr, "", 0) }
22-
func (mp *MockPrinter) IncomingRequest(fields logrequest.RequestFields, params string) {
23+
func (mp *MockPrinter) IncomingRequest(fields logrequest.RequestFields, params string, headers map[string][]string) {
2324
mp.fields = fields
2425
mp.params = params
26+
mp.headers = headers
2527
}
2628

2729
func TestResponseCodeFlag(t *testing.T) {
@@ -97,3 +99,39 @@ func TestLogRequest(t *testing.T) {
9799
}
98100
}
99101
}
102+
103+
func TestLogRequestHeaders(t *testing.T) {
104+
headers := map[string]string{
105+
"Content-Type": "application/json",
106+
"Foo": "bar",
107+
"Bearer": "hello!",
108+
}
109+
110+
renderer := &MockPrinter{}
111+
httpServer := Http{ResponseCode: 200, Output: renderer}
112+
srv := httptest.NewServer(httpServer.routes())
113+
defer srv.Close()
114+
115+
req, err := http.NewRequest(http.MethodGet, srv.URL, nil)
116+
if err != nil {
117+
t.Error(err)
118+
}
119+
120+
for key, value := range headers {
121+
req.Header.Set(key, value)
122+
}
123+
124+
resp, err := http.DefaultClient.Do(req)
125+
if err != nil {
126+
t.Error(err)
127+
}
128+
129+
defer resp.Body.Close()
130+
131+
for key, value := range headers {
132+
result := renderer.headers[key][0]
133+
if value != result {
134+
t.Errorf("Expected %s, got %s", value, result)
135+
}
136+
}
137+
}

0 commit comments

Comments
 (0)