This is an automated email from the ASF dual-hosted git repository.

wesm pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/arrow.git


The following commit(s) were added to refs/heads/master by this push:
     new 4e9992a  ARROW-9175: [FlightRPC][C++] Expose peer to server
4e9992a is described below

commit 4e9992aff33b56b343e4c70fb75024bd40091fdd
Author: David Li <[email protected]>
AuthorDate: Thu Jun 18 18:02:24 2020 -0500

    ARROW-9175: [FlightRPC][C++] Expose peer to server
    
    Being able to read and log the client IP/port is often useful when 
analyzing a request after-the-fact.
    
    Closes #7481 from lidavidm/arrow-9175
    
    Authored-by: David Li <[email protected]>
    Signed-off-by: Wes McKinney <[email protected]>
---
 cpp/src/arrow/flight/flight_test.cc         | 9 ++++++++-
 cpp/src/arrow/flight/server.cc              | 5 ++++-
 cpp/src/arrow/flight/server.h               | 2 ++
 python/pyarrow/_flight.pyx                  | 4 ++++
 python/pyarrow/includes/libarrow_flight.pxd | 1 +
 python/pyarrow/tests/test_flight.py         | 7 +++++--
 6 files changed, 24 insertions(+), 4 deletions(-)

diff --git a/cpp/src/arrow/flight/flight_test.cc 
b/cpp/src/arrow/flight/flight_test.cc
index e040611..5ef5c3c 100644
--- a/cpp/src/arrow/flight/flight_test.cc
+++ b/cpp/src/arrow/flight/flight_test.cc
@@ -392,7 +392,9 @@ class AuthTestServer : public FlightServerBase {
   Status DoAction(const ServerCallContext& context, const Action& action,
                   std::unique_ptr<ResultStream>* result) override {
     auto buf = Buffer::FromString(context.peer_identity());
-    *result = std::unique_ptr<ResultStream>(new 
SimpleResultStream({Result{buf}}));
+    auto peer = Buffer::FromString(context.peer());
+    *result = std::unique_ptr<ResultStream>(
+        new SimpleResultStream({Result{buf}, Result{peer}}));
     return Status::OK();
   }
 };
@@ -1527,6 +1529,11 @@ TEST_F(TestAuthHandler, CheckPeerIdentity) {
   ASSERT_NE(result, nullptr);
   // Action returns the peer identity as the result.
   ASSERT_EQ(result->body->ToString(), "user");
+
+  ASSERT_OK(results->Next(&result));
+  ASSERT_NE(result, nullptr);
+  // Action returns the peer address as the result.
+  ASSERT_NE(result->body->ToString(), "");
 }
 
 TEST_F(TestBasicAuthHandler, PassAuthenticatedCalls) {
diff --git a/cpp/src/arrow/flight/server.cc b/cpp/src/arrow/flight/server.cc
index 0f9dfb9..c27d5b1 100644
--- a/cpp/src/arrow/flight/server.cc
+++ b/cpp/src/arrow/flight/server.cc
@@ -359,9 +359,11 @@ class DoExchangeMessageWriter : public FlightMessageWriter 
{
 
 class FlightServiceImpl;
 class GrpcServerCallContext : public ServerCallContext {
-  explicit GrpcServerCallContext(grpc::ServerContext* context) : 
context_(context) {}
+  explicit GrpcServerCallContext(grpc::ServerContext* context)
+      : context_(context), peer_(context_->peer()) {}
 
   const std::string& peer_identity() const override { return peer_identity_; }
+  const std::string& peer() const override { return peer_; }
 
   // Helper method that runs interceptors given the result of an RPC,
   // then returns the final gRPC status to send to the client
@@ -392,6 +394,7 @@ class GrpcServerCallContext : public ServerCallContext {
  private:
   friend class FlightServiceImpl;
   ServerContext* context_;
+  std::string peer_;
   std::string peer_identity_;
   std::vector<std::shared_ptr<ServerMiddleware>> middleware_;
   std::unordered_map<std::string, std::shared_ptr<ServerMiddleware>> 
middleware_map_;
diff --git a/cpp/src/arrow/flight/server.h b/cpp/src/arrow/flight/server.h
index f1206bd..f3d33b6 100644
--- a/cpp/src/arrow/flight/server.h
+++ b/cpp/src/arrow/flight/server.h
@@ -113,6 +113,8 @@ class ARROW_FLIGHT_EXPORT ServerCallContext {
   virtual ~ServerCallContext() = default;
   /// \brief The name of the authenticated peer (may be the empty string)
   virtual const std::string& peer_identity() const = 0;
+  /// \brief The peer address (not validated)
+  virtual const std::string& peer() const = 0;
   /// \brief Look up a middleware by key. Do not maintain a reference
   /// to the object beyond the request body.
   /// \return The middleware, or nullptr if not found.
diff --git a/python/pyarrow/_flight.pyx b/python/pyarrow/_flight.pyx
index 6bead9e..9ec2ea2 100644
--- a/python/pyarrow/_flight.pyx
+++ b/python/pyarrow/_flight.pyx
@@ -1413,6 +1413,10 @@ cdef class ServerCallContext:
         """
         return tobytes(self.context.peer_identity())
 
+    def peer(self):
+        """Get the address of the peer."""
+        return frombytes(self.context.peer())
+
     def get_middleware(self, key):
         """
         Get a middleware instance by key.
diff --git a/python/pyarrow/includes/libarrow_flight.pxd 
b/python/pyarrow/includes/libarrow_flight.pxd
index 3334902..c8c12e0 100644
--- a/python/pyarrow/includes/libarrow_flight.pxd
+++ b/python/pyarrow/includes/libarrow_flight.pxd
@@ -206,6 +206,7 @@ cdef extern from "arrow/flight/api.h" namespace "arrow" 
nogil:
 
     cdef cppclass CServerCallContext" arrow::flight::ServerCallContext":
         c_string& peer_identity()
+        c_string& peer()
         CServerMiddleware* GetMiddleware(const c_string& key)
 
     cdef cppclass CTimeoutDuration" arrow::flight::TimeoutDuration":
diff --git a/python/pyarrow/tests/test_flight.py 
b/python/pyarrow/tests/test_flight.py
index 518e741..eed31b2 100644
--- a/python/pyarrow/tests/test_flight.py
+++ b/python/pyarrow/tests/test_flight.py
@@ -215,7 +215,7 @@ class EchoStreamFlightServer(EchoFlightServer):
 
     def do_action(self, context, action):
         if action.type == "who-am-i":
-            return [context.peer_identity()]
+            return [context.peer_identity(), context.peer().encode("utf-8")]
         raise NotImplementedError
 
 
@@ -935,8 +935,11 @@ def test_http_basic_auth():
         client = FlightClient(('localhost', server.port))
         action = flight.Action("who-am-i", b"")
         client.authenticate(HttpBasicClientAuthHandler('test', 'p4ssw0rd'))
-        identity = next(client.do_action(action))
+        results = client.do_action(action)
+        identity = next(results)
         assert identity.body.to_pybytes() == b'test'
+        peer_address = next(results)
+        assert peer_address.body.to_pybytes() != b''
 
 
 def test_http_basic_auth_invalid_password():

Reply via email to