Skip to content

Commit 9235e82

Browse files
authored
Merge pull request #3 from tkc/feat/request-log
Feat Request Logger
2 parents 9b844d0 + bf0f0e8 commit 9235e82

File tree

10 files changed

+235
-7
lines changed

10 files changed

+235
-7
lines changed

api.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"port": 3000,
3+
"endpoints": [
4+
{
5+
"method": "GET",
6+
"status": 200,
7+
"path": "/users",
8+
"jsonPath": "./users.json"
9+
},
10+
{
11+
"method": "GET",
12+
"status": 200,
13+
"path": "/user/1",
14+
"jsonPath": "./user.json"
15+
},
16+
{
17+
"path": "/file",
18+
"folder": "./static"
19+
}
20+
]
21+
}

go-json-server.go

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import (
99
"net/http"
1010
"os"
1111
"strconv"
12+
13+
"github.com/tkc/go-json-server/src/logger"
1214
)
1315

1416
const (
@@ -78,7 +80,6 @@ const (
7880
HeaderXCSRFToken = "X-CSRF-Token"
7981
)
8082

81-
8283
type Endpoint struct {
8384
Type string `json:"type"`
8485
Method string `json:"method"`
@@ -97,7 +98,6 @@ type API struct {
9798
var api API
9899

99100
func main() {
100-
101101
raw, err := ioutil.ReadFile("./api.json")
102102
if err != nil {
103103
fmt.Println(err.Error())
@@ -114,39 +114,45 @@ func main() {
114114
if len(ep.Folder) > 0 {
115115
http.Handle(ep.Path+"/", http.StripPrefix(ep.Path+"/", http.FileServer(http.Dir(ep.Folder))))
116116
} else {
117-
http.HandleFunc(ep.Path, Response)
117+
http.HandleFunc(ep.Path, response)
118118
}
119119
}
120120

121121
err = http.ListenAndServe(":"+strconv.Itoa(api.Port), nil)
122+
122123
if err != nil {
123124
log.Fatal(" ", err)
124125
}
125126
}
126127

127-
func Response(w http.ResponseWriter, r *http.Request) {
128+
129+
func response(w http.ResponseWriter, r *http.Request) {
130+
131+
appLogger := logger.CreateLogger()
132+
133+
r.ParseForm()
134+
appLogger.AccessLog(r)
128135

129136
w.Header().Set("Access-Control-Allow-Origin", "*")
130137
w.Header().Set("Access-Control-Allow-Credentials", "true")
131138
w.Header().Set("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization")
132139
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
133140

134-
r.ParseForm()
135141
for _, ep := range api.Endpoints {
136142
if r.URL.Path == ep.Path && r.Method == ep.Method {
137143
fmt.Println("method:", r.Method)
138144
fmt.Println("path:", r.URL.Path)
139145
w.Header().Set(HeaderContentType, MIMETextPlainCharsetUTF8)
140146
w.WriteHeader(ep.Status)
141-
s := Path2Response(ep.JsonPath)
147+
s := path2Response(ep.JsonPath)
142148
b := []byte(s)
143149
w.Write(b)
144150
}
145151
continue
146152
}
147153
}
148154

149-
func Path2Response(path string) string {
155+
func path2Response(path string) string {
150156
file, err := os.Open(path)
151157
if err != nil {
152158
log.Print(err)

go.mod

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
module github.com/tkc/go-json-server
2+
3+
go 1.13
4+
5+
require (
6+
github.com/spf13/cast v1.3.1
7+
github.com/stretchr/testify v1.5.1
8+
)

go.sum

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
2+
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
3+
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
4+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
5+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
6+
github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng=
7+
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
8+
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
9+
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
10+
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
11+
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
12+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
13+
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
14+
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

log.csv

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
GET,localhost:3000,HTTP/1.1,/users,[::1]:56235,/users
2+
GET,localhost:3000,HTTP/1.1,/users,[::1]:56259,/users
3+
GET,localhost:3000,HTTP/1.1,/users,[::1]:56302
4+
GET,localhost:3000,HTTP/1.1,/users,[::1]:56302
5+
GET,localhost:3000,HTTP/1.1,/users,[::1]:56302
6+
GET,localhost:3000,HTTP/1.1,/user/1,[::1]:56302

src/logger/logger.go

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package logger
2+
3+
import (
4+
"encoding/csv"
5+
"encoding/json"
6+
"fmt"
7+
"io"
8+
"log"
9+
stdlog "log"
10+
"net/http"
11+
"os"
12+
"strconv"
13+
)
14+
15+
type stdLogger struct {
16+
stderr *stdlog.Logger
17+
stdout *stdlog.Logger
18+
}
19+
20+
func CreateLogger() *stdLogger {
21+
return &stdLogger{
22+
stdout: stdlog.New(os.Stdout, "", 0),
23+
stderr: stdlog.New(os.Stderr, "", 0),
24+
}
25+
}
26+
27+
func (l *stdLogger) AccessLog(r *http.Request) {
28+
file, err := os.OpenFile("log.csv", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
29+
if err != nil {
30+
log.Fatal(err)
31+
}
32+
33+
defer file.Close()
34+
35+
jsonBody := dumpJsonBoddy(r)
36+
37+
s := []string{r.Method, r.Host, r.Proto, r.RequestURI, r.RemoteAddr, jsonBody}
38+
writer := csv.NewWriter(file)
39+
writer.Write(s)
40+
writer.Flush()
41+
}
42+
43+
func (l *stdLogger) Printf(format string, args ...interface{}) {
44+
l.stdout.Printf(format, args...)
45+
}
46+
47+
func (l *stdLogger) Errorf(format string, args ...interface{}) {
48+
l.stderr.Printf(format, args...)
49+
}
50+
51+
func (l *stdLogger) Fatalf(format string, args ...interface{}) {
52+
l.stderr.Fatalf(format, args...)
53+
}
54+
55+
func dumpJsonBoddy(req *http.Request) string {
56+
57+
if req.Method == "GET" {
58+
return ""
59+
}
60+
61+
if req.Header.Get("Content-Type") != "application/json" {
62+
return ""
63+
}
64+
65+
length, err := strconv.Atoi(req.Header.Get("Content-Length"))
66+
67+
if err != nil {
68+
return ""
69+
}
70+
71+
body := make([]byte, length)
72+
length, err = req.Body.Read(body)
73+
74+
if err != nil && err != io.EOF {
75+
return ""
76+
}
77+
78+
var jsonBody map[string]interface{}
79+
err = json.Unmarshal(body[:length], &jsonBody)
80+
81+
if err != nil {
82+
return ""
83+
}
84+
85+
s := fmt.Sprintf("%v", jsonBody)
86+
return s
87+
}

src/logger/logger_test.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package logger
2+
3+
import (
4+
"bytes"
5+
"net/http"
6+
"testing"
7+
8+
"github.com/spf13/cast"
9+
"github.com/stretchr/testify/assert"
10+
)
11+
12+
func TestGetNonReadRecord(t *testing.T) {
13+
14+
url := "example.com"
15+
content := `{"integer":1,"string":"xyz", "object": { "element": 1 } , "array": [1, 2, 3]}`
16+
byte := []byte(content)
17+
18+
body := bytes.NewReader(byte)
19+
req, _ := http.NewRequest("POST", url, body)
20+
21+
req.Header.Set("Content-Type", "application/json")
22+
req.Header.Set("Content-Length", cast.ToString(len(content)))
23+
24+
result := dumpJsonBoddy(req)
25+
assert.Equal(t, result, "map[array:[1 2 3] integer:1 object:map[element:1] string:xyz]")
26+
}

test/main.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package main
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"io"
7+
"log"
8+
"net/http"
9+
"strconv"
10+
)
11+
12+
func dumpJsonRequestHandlerFunc(w http.ResponseWriter, req *http.Request) {
13+
14+
if req.Header.Get("Content-Type") != "application/json" {
15+
w.WriteHeader(http.StatusBadRequest)
16+
return
17+
}
18+
19+
length, err := strconv.Atoi(req.Header.Get("Content-Length"))
20+
if err != nil {
21+
w.WriteHeader(http.StatusInternalServerError)
22+
return
23+
}
24+
25+
log.Print(length)
26+
27+
body := make([]byte, length)
28+
length, err = req.Body.Read(body)
29+
30+
if err != nil && err != io.EOF {
31+
w.WriteHeader(http.StatusInternalServerError)
32+
return
33+
}
34+
35+
var jsonBody map[string]interface{}
36+
err = json.Unmarshal(body[:length], &jsonBody)
37+
if err != nil {
38+
w.WriteHeader(http.StatusInternalServerError)
39+
return
40+
}
41+
42+
fmt.Printf("%v\n", jsonBody)
43+
// w.WriteHeader(http.StatusOK)
44+
}
45+
46+
func main() {
47+
http.HandleFunc("/json", dumpJsonRequestHandlerFunc)
48+
http.ListenAndServe(":8080", nil)
49+
}

user.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"id": 1,
3+
"name": "name",
4+
"address": "address"
5+
}

users.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[
2+
{
3+
"id": 1,
4+
"name": "name"
5+
}
6+
]

0 commit comments

Comments
 (0)