diff --git a/go.mod b/go.mod index a080ad9..e417b31 100644 --- a/go.mod +++ b/go.mod @@ -9,6 +9,7 @@ require ( github.com/pkg/errors v0.8.1 // indirect github.com/prometheus/client_golang v0.9.2 github.com/stretchr/testify v1.5.1 + github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce go.uber.org/atomic v1.4.0 // indirect go.uber.org/multierr v1.1.0 // indirect go.uber.org/zap v1.10.0 diff --git a/go.sum b/go.sum index 955f0bd..9d53859 100644 --- a/go.sum +++ b/go.sum @@ -30,6 +30,8 @@ github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce h1:fb190+cK2Xz/dvi9Hv8eCYJYvIGUTN2/KLq1pT6CjEc= +github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce/go.mod h1:o8v6yHRoik09Xen7gje4m9ERNah1d1PPsVq1VEx9vE4= go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI= diff --git a/repo/repo.go b/repo/repo.go index 7bf302b..09dd71f 100644 --- a/repo/repo.go +++ b/repo/repo.go @@ -2,6 +2,7 @@ package repo import ( "bytes" + "context" "errors" "fmt" "io" @@ -93,15 +94,16 @@ func (repo *Repo) GetURIs(dimension string, ids []string) map[string]string { } // GetNodes get nodes -func (repo *Repo) GetNodes(r *requests.Nodes) map[string]*content.Node { - return repo.getNodes(r.Nodes, r.Env) +func (repo *Repo) GetNodes(ctx context.Context, r *requests.Nodes) map[string]*content.Node { + return repo.getNodes(ctx, r.Nodes, r.Env) } -func (repo *Repo) getNodes(nodeRequests map[string]*requests.Node, env *requests.Env) map[string]*content.Node { +func (repo *Repo) getNodes(ctx context.Context, nodeRequests map[string]*requests.Node, env *requests.Env) map[string]*content.Node { var ( - nodes = map[string]*content.Node{} - path = []*content.Item{} + nodes = map[string]*content.Node{} + path = []*content.Item{} + remoteAddr = ctx.Value("remoteAddr").(string) ) for nodeName, nodeRequest := range nodeRequests { @@ -140,6 +142,7 @@ func (repo *Repo) getNodes(nodeRequests map[string]*requests.Node, env *requests nodes[nodeName] = repo.getNode(treeNode, nodeRequest.Expand, nodeRequest.MimeTypes, path, 0, groups, nodeRequest.DataFields, nodeRequest.ExposeHiddenNodes) } else { Log.Error("an invalid tree node was requested", + zap.String("remoteAddr", remoteAddr), zap.String("nodeName", nodeName), zap.String("ID", nodeRequest.ID), ) @@ -157,7 +160,7 @@ func (repo *Repo) getNodes(nodeRequests map[string]*requests.Node, env *requests // In the second step it collects the requested nodes. // // those two steps are independent. -func (repo *Repo) GetContent(r *requests.Content) (c *content.SiteContent, err error) { +func (repo *Repo) GetContent(ctx context.Context, r *requests.Content) (c *content.SiteContent, err error) { // add more input validation err = repo.validateContentRequest(r) if err != nil { @@ -206,7 +209,7 @@ func (repo *Repo) GetContent(r *requests.Content) (c *content.SiteContent, err e node.Dimension = resolvedDimension } } - c.Nodes = repo.getNodes(r.Nodes, r.Env) + c.Nodes = repo.getNodes(ctx, r.Nodes, r.Env) return c, nil } diff --git a/server/handlerequest.go b/server/handlerequest.go index 3562ad6..d4c566c 100644 --- a/server/handlerequest.go +++ b/server/handlerequest.go @@ -1,6 +1,7 @@ package server import ( + "context" "time" "go.uber.org/zap" @@ -12,7 +13,7 @@ import ( "github.com/foomo/contentserver/status" ) -func handleRequest(r *repo.Repo, handler Handler, jsonBytes []byte, source string) (replyBytes []byte, err error) { +func handleRequest(ctx context.Context, r *repo.Repo, handler Handler, jsonBytes []byte, source string) (replyBytes []byte, err error) { var ( reply interface{} @@ -41,12 +42,12 @@ func handleRequest(r *repo.Repo, handler Handler, jsonBytes []byte, source strin case HandlerGetContent: contentRequest := &requests.Content{} processIfJSONIsOk(json.Unmarshal(jsonBytes, &contentRequest), func() { - reply, apiErr = r.GetContent(contentRequest) + reply, apiErr = r.GetContent(ctx, contentRequest) }) case HandlerGetNodes: nodesRequest := &requests.Nodes{} processIfJSONIsOk(json.Unmarshal(jsonBytes, &nodesRequest), func() { - reply = r.GetNodes(nodesRequest) + reply = r.GetNodes(ctx, nodesRequest) }) case HandlerUpdate: updateRequest := &requests.Update{} diff --git a/server/socketserver.go b/server/socketserver.go index eb89906..a4b60c7 100644 --- a/server/socketserver.go +++ b/server/socketserver.go @@ -2,6 +2,7 @@ package server import ( "bytes" + "context" "errors" "fmt" "net" @@ -56,8 +57,8 @@ func (s *socketServer) execute(handler Handler, jsonBytes []byte) (reply []byte) addMetrics(handler, start, nil, nil, sourceSocketServer) return b.Bytes() } - - reply, handlingError := handleRequest(s.repo, handler, jsonBytes, sourceSocketServer) + ctx := context.WithValue(context.TODO(), "remoteAddr", "socket") // TODO: set socket remote address + reply, handlingError := handleRequest(ctx, s.repo, handler, jsonBytes, sourceSocketServer) if handlingError != nil { Log.Error("socketServer.execute failed", zap.Error(handlingError)) } diff --git a/server/webserver.go b/server/webserver.go index f58546f..0cda0fe 100644 --- a/server/webserver.go +++ b/server/webserver.go @@ -1,6 +1,7 @@ package server import ( + "context" "fmt" "io/ioutil" "net/http" @@ -11,6 +12,7 @@ import ( . "github.com/foomo/contentserver/logger" "github.com/foomo/contentserver/repo" + "github.com/tomasen/realip" ) const sourceWebserver = "webserver" @@ -53,7 +55,9 @@ func (s *webServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { addMetrics(h, start, nil, nil, sourceWebserver) return } - reply, errReply := handleRequest(s.r, h, jsonBytes, "webserver") + ip := realip.FromRequest(r) + ctx := context.WithValue(r.Context(), "remoteAddr", ip) + reply, errReply := handleRequest(ctx, s.r, h, jsonBytes, "webserver") if errReply != nil { http.Error(w, errReply.Error(), http.StatusInternalServerError) return