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

rnewson pushed a commit to branch custom-peer-header
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit b615fe30b9f85cde24a548c9ba9a25539c0f6934
Author: Robert Newson <[email protected]>
AuthorDate: Thu Jul 2 16:24:02 2026 +0100

    configurable request header for determining peer
---
 src/chttpd/src/chttpd.erl            | 28 ++++++++++++++++++++++++++--
 src/chttpd/src/chttpd_external.erl   |  2 +-
 src/couch/src/couch_auth_lockout.erl | 13 ++-----------
 src/couch/src/couch_httpd.erl        | 13 +++++++++++++
 src/couch/src/couch_httpd_auth.erl   | 10 ++++------
 5 files changed, 46 insertions(+), 20 deletions(-)

diff --git a/src/chttpd/src/chttpd.erl b/src/chttpd/src/chttpd.erl
index 485e012c2..b7ae2753e 100644
--- a/src/chttpd/src/chttpd.erl
+++ b/src/chttpd/src/chttpd.erl
@@ -64,7 +64,8 @@
     send_redirect/2,
     send_chunked_error/2,
     send_json/2, send_json/3, send_json/4,
-    validate_ctype/2
+    validate_ctype/2,
+    peer/1
 ]).
 
 -export([authenticate_request/3]).
@@ -266,7 +267,7 @@ handle_request_int(MochiReq) ->
                 P
         end,
 
-    Peer = MochiReq:get(peer),
+    Peer = peer(MochiReq),
 
     Method1 =
         case MochiReq:get(method) of
@@ -840,6 +841,29 @@ body(#httpd{mochi_req = MochiReq, req_body = ReqBody}) ->
 validate_ctype(Req, Ctype) ->
     couch_httpd:validate_ctype(Req, Ctype).
 
+peer(#httpd{} = Req) ->
+    peer(Req#httpd.mochi_req);
+peer(MochiReq) ->
+    case config:get("chttpd", "peer_header") of
+        undefined ->
+            peer_from_socket(MochiReq);
+        PeerHeader ->
+            case MochiReq:get_header_value(PeerHeader) of
+                undefined ->
+                    peer_from_socket(MochiReq);
+                Peer ->
+                    Peer
+            end
+    end.
+
+peer_from_socket(MochiReq) ->
+    case MochiReq:get(socket) of
+        {remote, _Pid, _} ->
+            nopeer;
+        _ ->
+            MochiReq:get(peer)
+    end.
+
 json_body(#httpd{} = Httpd) ->
     json_body(Httpd, []).
 
diff --git a/src/chttpd/src/chttpd_external.erl 
b/src/chttpd/src/chttpd_external.erl
index fe63de3b2..b57c42c56 100644
--- a/src/chttpd/src/chttpd_external.erl
+++ b/src/chttpd/src/chttpd_external.erl
@@ -93,7 +93,7 @@ json_req_obj_field(<<"body">>, #httpd{req_body = undefined, 
mochi_req = Req}, _D
 json_req_obj_field(<<"body">>, #httpd{req_body = Body}, _Db, _DocId) ->
     Body;
 json_req_obj_field(<<"peer">>, #httpd{peer = undefined, mochi_req = Req}, _, 
_) ->
-    ?l2b(Req:get(peer));
+    ?l2b(chttpd:peer(Req));
 json_req_obj_field(<<"peer">>, #httpd{peer = Peer}, _Db, _DocId) ->
     ?l2b(Peer);
 json_req_obj_field(<<"form">>, #httpd{mochi_req = Req, method = Method} = 
HttpReq, Db, DocId) ->
diff --git a/src/couch/src/couch_auth_lockout.erl 
b/src/couch/src/couch_auth_lockout.erl
index ceed57f11..63fdabd7b 100644
--- a/src/couch/src/couch_auth_lockout.erl
+++ b/src/couch/src/couch_auth_lockout.erl
@@ -27,7 +27,7 @@ is_locked_out(#httpd{} = Req, UserName, UserSalt) ->
 
 is_locked_out_int(#httpd{} = Req, Mode, UserName, UserSalt) ->
     LockoutThreshold = lockout_threshold(),
-    case peer(Req) of
+    case Req#httpd.peer of
         nopeer ->
             false;
         Peer ->
@@ -48,7 +48,7 @@ is_locked_out_int(#httpd{} = Req, Mode, UserName, UserSalt) ->
     end.
 
 lockout(#httpd{} = Req, UserName, UserSalt) ->
-    case peer(Req) of
+    case Req#httpd.peer of
         nopeer ->
             ok;
         Peer ->
@@ -74,12 +74,3 @@ lockout_mode() ->
 
 lockout_threshold() ->
     config:get_integer("chttpd_auth_lockout", "threshold", 5).
-
-peer(#httpd{mochi_req = MochiReq}) ->
-    Socket = mochiweb_request:get(socket, MochiReq),
-    case Socket of
-        {remote, _Pid, _Ref} ->
-            nopeer;
-        _ ->
-            mochiweb_request:get(peer, MochiReq)
-    end.
diff --git a/src/couch/src/couch_httpd.erl b/src/couch/src/couch_httpd.erl
index 5253e4d3c..ce7179ee2 100644
--- a/src/couch/src/couch_httpd.erl
+++ b/src/couch/src/couch_httpd.erl
@@ -1425,6 +1425,19 @@ http_respond_(#httpd{mochi_req = MochiReq}, Code, 
Headers, Args, Type) ->
     MochiReq:Type({Code, Headers, Args}).
 
 peer(MochiReq) ->
+    case config:get("chttpd", "peer_header") of
+        undefined ->
+            peer_from_socket(MochiReq);
+        PeerHeader ->
+            case MochiReq:get_header_value(PeerHeader) of
+                undefined ->
+                    peer_from_socket(MochiReq);
+                Peer ->
+                    Peer
+            end
+    end.
+
+peer_from_socket(MochiReq) ->
     case MochiReq:get(socket) of
         {remote, Pid, _} ->
             node(Pid);
diff --git a/src/couch/src/couch_httpd_auth.erl 
b/src/couch/src/couch_httpd_auth.erl
index 3779be66b..ba26ef50c 100644
--- a/src/couch/src/couch_httpd_auth.erl
+++ b/src/couch/src/couch_httpd_auth.erl
@@ -813,18 +813,16 @@ integer_to_binary(Int, Len) when is_integer(Int), 
is_integer(Len) ->
     Padded = <<Padding/binary, Unpadded/binary>>,
     binary:part(Padded, byte_size(Padded), -Len).
 
-authentication_warning(#httpd{mochi_req = Req}, User) ->
-    Peer = Req:get(peer),
+authentication_warning(#httpd{} = Req, User) ->
     couch_log:warning(
         "~p: Authentication failed for user ~s from ~s",
-        [?MODULE, User, Peer]
+        [?MODULE, User, Req#httpd.peer]
     ).
 
-lockout_warning(#httpd{mochi_req = Req}, User) ->
-    Peer = Req:get(peer),
+lockout_warning(#httpd{} = Req, User) ->
     couch_log:warning(
         "~p: Authentication rejected for locked-out user ~s from ~s",
-        [?MODULE, User, Peer]
+        [?MODULE, User, Req#httpd.peer]
     ).
 
 -ifdef(TEST).

Reply via email to