Skip to content

Commit d3a415b

Browse files
committed
refacto using middleware
1 parent 158de53 commit d3a415b

File tree

5 files changed

+122
-56
lines changed

5 files changed

+122
-56
lines changed

cmd/gopherapi/main.go

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,15 @@ import (
2424
func main() {
2525

2626
var (
27-
hostName, _ = os.Hostname()
28-
defaultServerName = fmt.Sprintf("%s-%s", os.Getenv("GOPHERAPI_NAME"), hostName)
29-
defaultHost = os.Getenv("GOPHERAPI_SERVER_HOST")
30-
defaultPort, _ = strconv.Atoi(os.Getenv("GOPHERAPI_SERVER_PORT"))
27+
hostName, _ = os.Hostname()
28+
defaultServerID = fmt.Sprintf("%s-%s", os.Getenv("GOPHERAPI_NAME"), hostName)
29+
defaultHost = os.Getenv("GOPHERAPI_SERVER_HOST")
30+
defaultPort, _ = strconv.Atoi(os.Getenv("GOPHERAPI_SERVER_PORT"))
3131
)
3232

3333
host := flag.String("host", defaultHost, "define host of the server")
3434
port := flag.Int("port", defaultPort, "define port of the server")
35-
serverName := flag.String("server-name", defaultServerName, "define name of the server")
35+
serverID := flag.String("server-id", defaultServerID, "define server identifier")
3636
withData := flag.Bool("withData", false, "initialize the api with some gophers")
3737
flag.Parse()
3838

@@ -52,8 +52,7 @@ func main() {
5252
httpAddr := fmt.Sprintf("%s:%d", *host, *port)
5353

5454
s := server.New(
55-
*serverName,
56-
httpAddr,
55+
*serverID,
5756
fetchingService,
5857
addingService,
5958
modifyingService,

pkg/log/logrus/logrus.go

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,21 @@ func (l *logger) UnexpectedError(ctx context.Context, err error) {
3636
}
3737

3838
func (l *logger) WithDefaultFields(ctx context.Context) *logrus.Entry {
39-
hostname, _ := server.Name(ctx)
40-
httpAddr, _ := server.HttpAddr(ctx)
41-
42-
return l.WithFields(logrus.Fields{
43-
"hostname": hostname,
44-
"httpAddr": httpAddr,
45-
})
46-
39+
serverID, _ := server.ID(ctx)
40+
endpoint, _ := server.Endpoint(ctx)
41+
clientIP, _ := server.ClientIP(ctx)
42+
fields := logrus.Fields{
43+
"serverid": serverID,
44+
"endpoint": endpoint,
45+
"clientip": clientIP,
46+
}
47+
48+
if xForwardedFor, ok := server.XForwardedFor(ctx); ok {
49+
fields["xforwardedfor"] = xForwardedFor
50+
}
51+
if xForwardedProto, ok := server.XForwardedProto(ctx); ok {
52+
fields["xforwardedproto"] = xForwardedProto
53+
}
54+
55+
return l.WithFields(fields)
4756
}

pkg/server/context.go

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,11 @@ import (
55
)
66

77
var (
8-
contextKeyServerName = contextKey("Name")
9-
contextKeyHttpAddr = contextKey("HttpAddr")
8+
contextKeyServerID = contextKey("id")
9+
contextKeyXForwardedFor = contextKey("xForwardedFor")
10+
contextKeyXForwardedProto = contextKey("xForwardedProto")
11+
contextKeyEndpoint = contextKey("endpoint")
12+
contextKeyClientIP = contextKey("clientIP")
1013
)
1114

1215
type contextKey string
@@ -15,14 +18,32 @@ func (c contextKey) String() string {
1518
return "server" + string(c)
1619
}
1720

18-
// Name gets the name server from context
19-
func Name(ctx context.Context) (string, bool) {
20-
n, ok := ctx.Value(contextKeyServerName).(string)
21-
return n, ok
21+
// ID gets the name server from context
22+
func ID(ctx context.Context) (string, bool) {
23+
id, ok := ctx.Value(contextKeyServerID).(string)
24+
return id, ok
2225
}
2326

24-
// HttpAddr gets the http address server from context
25-
func HttpAddr(ctx context.Context) (string, bool) {
26-
httpAddrStr, ok := ctx.Value(contextKeyHttpAddr).(string)
27-
return httpAddrStr, ok
27+
// XForwardedFor gets the http address server from context
28+
func XForwardedFor(ctx context.Context) (string, bool) {
29+
xForwardedFor, ok := ctx.Value(contextKeyXForwardedFor).(string)
30+
return xForwardedFor, ok
31+
}
32+
33+
// XForwardedProto gets the http address server from context
34+
func XForwardedProto(ctx context.Context) (string, bool) {
35+
xForwardedProto, ok := ctx.Value(contextKeyXForwardedProto).(string)
36+
return xForwardedProto, ok
37+
}
38+
39+
// Endpoint gets the http address server from context
40+
func Endpoint(ctx context.Context) (string, bool) {
41+
endpoint, ok := ctx.Value(contextKeyEndpoint).(string)
42+
return endpoint, ok
43+
}
44+
45+
// ClientIP gets the http address server from context
46+
func ClientIP(ctx context.Context) (string, bool) {
47+
clientIP, ok := ctx.Value(contextKeyClientIP).(string)
48+
return clientIP, ok
2849
}

pkg/server/middleware.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package server
2+
3+
import (
4+
"context"
5+
"net"
6+
"net/http"
7+
)
8+
9+
type handler struct {
10+
serverID string
11+
next http.Handler
12+
}
13+
14+
func newServerMiddleware(serverID string) func(http.Handler) http.Handler {
15+
return func(next http.Handler) http.Handler {
16+
h := &handler{
17+
serverID: serverID,
18+
next: next,
19+
}
20+
return h
21+
}
22+
}
23+
24+
// ServeHTTP implements http.Handler.
25+
func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
26+
ctx := h.createRequestContext(r)
27+
h.next.ServeHTTP(w, r.WithContext(ctx))
28+
}
29+
30+
func (h handler) createRequestContext(req *http.Request) context.Context {
31+
ctx := req.Context()
32+
33+
var (
34+
xForwardedFor = req.Header.Get("X-FORWARDED-FOR")
35+
xForwardedProto = req.Header.Get("X-FORWARDED-PROTO")
36+
)
37+
38+
if xForwardedFor != "" {
39+
ctx = context.WithValue(ctx, contextKeyXForwardedFor, xForwardedFor)
40+
}
41+
if xForwardedProto != "" {
42+
ctx = context.WithValue(ctx, contextKeyXForwardedProto, xForwardedProto)
43+
}
44+
45+
ip, _, _ := net.SplitHostPort(req.RemoteAddr)
46+
ctx = context.WithValue(ctx, contextKeyClientIP, ip)
47+
ctx = context.WithValue(ctx, contextKeyEndpoint, req.URL.RequestURI())
48+
49+
ctx = context.WithValue(ctx, contextKeyServerID, h.serverID)
50+
51+
return ctx
52+
}

pkg/server/server.go

Lines changed: 16 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package server
22

33
import (
4-
"context"
54
"encoding/json"
65
"net/http"
76

@@ -15,8 +14,8 @@ import (
1514

1615
// server all server necessary dependencies
1716
type server struct {
18-
serverName string
19-
httpAddr string
17+
serverID string
18+
httpAddr string
2019

2120
router http.Handler
2221
fetching fetching.Service
@@ -37,33 +36,27 @@ type Server interface {
3736

3837
// New initialize the server
3938
func New(
40-
serverName string,
41-
httpAddr string,
39+
serverID string,
4240
fS fetching.Service,
4341
aS adding.Service,
4442
mS modifying.Service,
4543
rS removing.Service) Server {
4644
a := &server{
47-
serverName: serverName,
48-
httpAddr: httpAddr,
49-
fetching: fS,
50-
adding: aS,
51-
modifying: mS,
52-
removing: rS}
45+
serverID: serverID,
46+
fetching: fS,
47+
adding: aS,
48+
modifying: mS,
49+
removing: rS}
5350
router(a)
5451

5552
return a
5653
}
5754

58-
func (s *server) createContext(ctx context.Context) context.Context {
59-
ctx = context.WithValue(ctx, contextKeyServerName, s.serverName)
60-
ctx = context.WithValue(ctx, contextKeyHttpAddr, s.httpAddr)
61-
62-
return ctx
63-
}
64-
6555
func router(s *server) {
6656
r := mux.NewRouter()
57+
58+
r.Use(newServerMiddleware(s.serverID))
59+
6760
r.HandleFunc("/gophers", s.FetchGophers).Methods(http.MethodGet)
6861
r.HandleFunc("/gophers/{ID:[a-zA-Z0-9_]+}", s.FetchGopher).Methods(http.MethodGet)
6962
r.HandleFunc("/gophers", s.AddGopher).Methods(http.MethodPost)
@@ -79,9 +72,7 @@ func (s *server) Router() http.Handler {
7972

8073
// FetchGophers return a list of all gophers
8174
func (s *server) FetchGophers(w http.ResponseWriter, r *http.Request) {
82-
ctx := s.createContext(r.Context())
83-
84-
gophers, _ := s.fetching.FetchGophers(ctx)
75+
gophers, _ := s.fetching.FetchGophers(r.Context())
8576

8677
w.Header().Set("Content-Type", "application/json")
8778
_ = json.NewEncoder(w).Encode(gophers)
@@ -90,10 +81,8 @@ func (s *server) FetchGophers(w http.ResponseWriter, r *http.Request) {
9081

9182
// FetchGopher return a gopher by ID
9283
func (s *server) FetchGopher(w http.ResponseWriter, r *http.Request) {
93-
ctx := s.createContext(r.Context())
94-
9584
vars := mux.Vars(r)
96-
gopher := s.fetching.FetchGopherByID(ctx, vars["ID"])
85+
gopher := s.fetching.FetchGopherByID(r.Context(), vars["ID"])
9786
w.Header().Set("Content-Type", "application/json")
9887
if gopher == nil {
9988
w.WriteHeader(http.StatusNotFound)
@@ -125,8 +114,7 @@ func (s *server) AddGopher(w http.ResponseWriter, r *http.Request) {
125114
_ = json.NewEncoder(w).Encode("Error unmarshalling request body")
126115
return
127116
}
128-
ctx := s.createContext(r.Context())
129-
if err := s.adding.AddGopher(ctx, g.ID, g.Name, g.Image, g.Age); err != nil {
117+
if err := s.adding.AddGopher(r.Context(), g.ID, g.Name, g.Image, g.Age); err != nil {
130118
w.WriteHeader(http.StatusInternalServerError)
131119
_ = json.NewEncoder(w).Encode("Can't create a gopher")
132120
return
@@ -155,9 +143,7 @@ func (s *server) ModifyGopher(w http.ResponseWriter, r *http.Request) {
155143
return
156144
}
157145
vars := mux.Vars(r)
158-
ctx := s.createContext(r.Context())
159-
160-
if err := s.modifying.ModifyGopher(ctx, vars["ID"], g.Name, g.Image, g.Age); err != nil {
146+
if err := s.modifying.ModifyGopher(r.Context(), vars["ID"], g.Name, g.Image, g.Age); err != nil {
161147
w.WriteHeader(http.StatusInternalServerError)
162148
_ = json.NewEncoder(w).Encode("Can't modify a gopher")
163149
return
@@ -168,10 +154,9 @@ func (s *server) ModifyGopher(w http.ResponseWriter, r *http.Request) {
168154

169155
// RemoveGopher remove a gopher
170156
func (s *server) RemoveGopher(w http.ResponseWriter, r *http.Request) {
171-
ctx := s.createContext(r.Context())
172157
vars := mux.Vars(r)
173158

174-
_ = s.removing.RemoveGopher(ctx, vars["ID"])
159+
_ = s.removing.RemoveGopher(r.Context(), vars["ID"])
175160
w.Header().Set("Content-Type", "application/json")
176161
w.WriteHeader(http.StatusNoContent)
177162

0 commit comments

Comments
 (0)