From c071727adba362feb318a1ca92e2b1c8e1ef6157 Mon Sep 17 00:00:00 2001 From: Maxime Besson Date: Fri, 8 Mar 2024 17:39:47 +0100 Subject: [PATCH 1/6] Add request_id to $req (#3120) --- .../lib/Lemonldap/NG/Common/PSGI/Request.pm | 8 ++++++-- .../Lemonldap/NG/Handler/ApacheMP2/Request.pm | 20 ++++++++++++------- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/lemonldap-ng-common/lib/Lemonldap/NG/Common/PSGI/Request.pm b/lemonldap-ng-common/lib/Lemonldap/NG/Common/PSGI/Request.pm index ed0af54afb..fbde93f6cc 100644 --- a/lemonldap-ng-common/lib/Lemonldap/NG/Common/PSGI/Request.pm +++ b/lemonldap-ng-common/lib/Lemonldap/NG/Common/PSGI/Request.pm @@ -27,8 +27,10 @@ sub new { $self->env->{PATH_INFO} =~ s|//+|/|g; $self->env->{PATH_INFO} ||= '/'; $self->env->{REQUEST_URI} =~ s|^//+|/|g; - $self->{uri} = uri_unescape( $self->env->{REQUEST_URI} ); - $self->{data} = {}; + $self->{uri} = uri_unescape( $self->env->{REQUEST_URI} ); + $self->{data} = {}; + $self->{request_id} = ( $self->env->{UNIQUE_ID} + || join( '', map { [ 0 .. 9, "a" .. "f" ]->[ rand 16 ] } 1 .. 16 ) ); $self->{error} = 0; $self->{respHeaders} = []; return bless( $self, $_[0] ); @@ -38,6 +40,8 @@ sub data { return $_[0]->{data} } sub uri { return $_[0]->{uri} } +sub request_id { return $_[0]->{request_id} } + sub userData { my ( $self, $v ) = @_; return $self->{userData} = $v if ($v); diff --git a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/ApacheMP2/Request.pm b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/ApacheMP2/Request.pm index a9b14df554..04df733497 100644 --- a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/ApacheMP2/Request.pm +++ b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/ApacheMP2/Request.pm @@ -19,13 +19,17 @@ sub new { my $env = { #%ENV, - HTTP_HOST => $r->hostname, - REMOTE_ADDR => $r->useragent_ip, - QUERY_STRING => $args, - REQUEST_URI => $uri_full, - PATH_INFO => '', - SERVER_PORT => $ENV{SERVER_PORT} || $r->get_server_port, - REQUEST_METHOD => $r->method, + HTTP_HOST => $r->hostname, + REMOTE_ADDR => $r->useragent_ip, + QUERY_STRING => $args, + REQUEST_URI => $uri_full, + PATH_INFO => '', + SERVER_PORT => $ENV{SERVER_PORT} || $r->get_server_port, + REQUEST_METHOD => $r->method, + UNIQUE_ID => ( + $r->subprocess_env('UNIQUE_ID') + || join( '', map { [ 0 .. 9, 'a' .. 'f' ]->[ rand 16 ] } 1 .. 16 ) + ), 'psgi.version' => [ 1, 1 ], 'psgi.url_scheme' => ( $ENV{HTTPS} || 'off' ) =~ /^(?:on|1)$/i ? 'https' @@ -73,4 +77,6 @@ sub wantJSON { return 0; } +sub request_id { return $_[0]->env->{UNIQUE_ID} } + 1; -- GitLab From 56eebb54d5dc7cfdd86c833574a21655454626fa Mon Sep 17 00:00:00 2001 From: Maxime Besson Date: Tue, 6 Feb 2024 11:18:43 +0100 Subject: [PATCH 2/6] Unit test for request ID (#3120) --- lemonldap-ng-common/t/10-PSGI-Request.t | 54 +++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 lemonldap-ng-common/t/10-PSGI-Request.t diff --git a/lemonldap-ng-common/t/10-PSGI-Request.t b/lemonldap-ng-common/t/10-PSGI-Request.t new file mode 100644 index 0000000000..45d28ff138 --- /dev/null +++ b/lemonldap-ng-common/t/10-PSGI-Request.t @@ -0,0 +1,54 @@ +use strict; +use open ':std', ':encoding(utf8)'; +use Test::More; +use Plack::Test; +use Lemonldap::NG::Common::PSGI::Request; + +use JSON; +use HTTP::Request; +use HTTP::Message::PSGI; +use utf8; + +sub build_json_request { + my ($href) = @_; + my $header = [ 'Content-Type' => 'application/json; charset=UTF-8' ]; + return HTTP::Request->new( 'POST', "http://www.example.com", $header, + encode_json($href) ); +} + +subtest "Request ID" => sub { + my $req = Lemonldap::NG::Common::PSGI::Request->new( + HTTP::Request->new( GET => 'http://www.example.com/' )->to_psgi ); + + my $request_id = $req->request_id; + like( $request_id, qr/^\w{16}$/, "Generated request ID" ); + is( $req->request_id, $request_id, "Request ID is stable across calls" ); + + my $req2 = Lemonldap::NG::Common::PSGI::Request->new( + HTTP::Request->new( GET => 'http://www.example.com/' )->to_psgi ); + isnt( $req2->request_id, $request_id, + "Request ID is different for each request" ); + + my $req3 = Lemonldap::NG::Common::PSGI::Request->new( + HTTP::Request->new( GET => 'http://www.example.com/' ) + ->to_psgi( UNIQUE_ID => 123456 ) ); + + is( $req3->request_id, "123456", + "Request ID is read from UNIQUE_ID env if set" ); +}; + +subtest "Request JSON body" => sub { + my $req = Lemonldap::NG::Common::PSGI::Request->new( + build_json_request( { key1 => 123, key2 => "€ncoded" } )->to_psgi ); + + ok(1); + ok( my $obj = $req->jsonBodyToObj, "Found JSON body" ); + is( $obj->{key1}, "123", "Found correct ascii value" ); + + TODO: { + local $TODO = "UTF-8 handling in request is broken, see #2748"; + is( $obj->{key2}, "€ncoded", "Found correct UTF-8 value" ); + } +}; + +done_testing(); -- GitLab From 510c94a9145451989b4d40c222e18d52134c6949 Mon Sep 17 00:00:00 2001 From: Maxime Besson Date: Tue, 12 Mar 2024 11:27:42 +0100 Subject: [PATCH 3/6] Documentation for #3120 --- doc/sources/admin/logs.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/sources/admin/logs.rst b/doc/sources/admin/logs.rst index 24f918fbd0..c0ccd922b2 100644 --- a/doc/sources/admin/logs.rst +++ b/doc/sources/admin/logs.rst @@ -249,6 +249,12 @@ For additional information, please read the `Log4Perl documentation Date: Tue, 12 Mar 2024 12:07:29 +0100 Subject: [PATCH 4/6] Add UNIQUE_ID to Nginx config (#3120) --- _example/etc/api-nginx.conf | 2 ++ _example/etc/manager-nginx.conf | 2 ++ _example/etc/portal-nginx.conf | 2 ++ _example/etc/test-nginx.conf | 2 ++ 4 files changed, 8 insertions(+) diff --git a/_example/etc/api-nginx.conf b/_example/etc/api-nginx.conf index 42a7978e8d..34c1ac3b19 100644 --- a/_example/etc/api-nginx.conf +++ b/_example/etc/api-nginx.conf @@ -32,6 +32,7 @@ server { fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_split_path_info ^(.*\.psgi)(/.*)$; fastcgi_param PATH_INFO $fastcgi_path_info; + fastcgi_param UNIQUE_ID $request_id; # OR TO USE uWSGI #include /etc/nginx/uwsgi_params; @@ -39,6 +40,7 @@ server { #uwsgi_param LLTYPE psgi; #uwsgi_param SCRIPT_FILENAME $document_root$sc; #uwsgi_param SCRIPT_NAME $sc; + #uwsgi_param UNIQUE_ID $request_id; } diff --git a/_example/etc/manager-nginx.conf b/_example/etc/manager-nginx.conf index 3ba01f9061..7276264c4e 100644 --- a/_example/etc/manager-nginx.conf +++ b/_example/etc/manager-nginx.conf @@ -28,6 +28,7 @@ server { fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_split_path_info ^(.*\.psgi)(/.*)$; fastcgi_param PATH_INFO $fastcgi_path_info; + fastcgi_param UNIQUE_ID $request_id; # Or with uWSGI #include /etc/nginx/uwsgi_params; @@ -35,6 +36,7 @@ server { #uwsgi_param LLTYPE psgi; #uwsgi_param SCRIPT_FILENAME $document_root$sc; #uwsgi_param SCRIPT_NAME $sc; + #uwsgi_param UNIQUE_ID $request_id; } location / { diff --git a/_example/etc/portal-nginx.conf b/_example/etc/portal-nginx.conf index 464dcd8bea..099958ceb7 100644 --- a/_example/etc/portal-nginx.conf +++ b/_example/etc/portal-nginx.conf @@ -42,6 +42,7 @@ server { fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_split_path_info ^(.*\.psgi)(/.*)$; fastcgi_param PATH_INFO $fastcgi_path_info; + fastcgi_param UNIQUE_ID $request_id; # Uncomment this if you use Auth SSL: #fastcgi_param SSL_CLIENT_S_DN_CN $ssl_client_s_dn_cn; @@ -51,6 +52,7 @@ server { #uwsgi_param LLTYPE psgi; #uwsgi_param SCRIPT_FILENAME $document_root$sc; #uwsgi_param SCRIPT_NAME $sc; + #uwsgi_param UNIQUE_ID $request_id; # Uncomment this if you use Auth SSL: #uwsgi_param SSL_CLIENT_S_DN_CN $ssl_client_s_dn_cn; diff --git a/_example/etc/test-nginx.conf b/_example/etc/test-nginx.conf index f591ac6d2e..03d15361ed 100644 --- a/_example/etc/test-nginx.conf +++ b/_example/etc/test-nginx.conf @@ -27,6 +27,7 @@ server { fastcgi_param HOST $http_host; # Keep original request (LLNG server will receive /lmauth) fastcgi_param X_ORIGINAL_URI $original_uri; + fastcgi_param UNIQUE_ID $request_id; # Improve performances #fastcgi_buffer_size 32k; #fastcgi_buffers 32 32k; @@ -42,6 +43,7 @@ server { #uwsgi_param HOST $http_host; # Keep original request (LLNG server will receive /lmauth) #uwsgi_param X_ORIGINAL_URI $original_uri; + #uwsgi_param UNIQUE_ID $request_id; ## Improve performances #uwsgi_buffer_size 32k; #uwsgi_buffers 32 32k; -- GitLab From 5e193b8527d0a447c869180eebbe640bf79172e5 Mon Sep 17 00:00:00 2001 From: Maxime Besson Date: Tue, 12 Mar 2024 12:12:15 +0100 Subject: [PATCH 5/6] Reorder log to make Apache2 request attributes visible --- lemonldap-ng-handler/lib/Lemonldap/NG/Handler/ApacheMP2.pm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/ApacheMP2.pm b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/ApacheMP2.pm index 17a005c376..6c40fc585a 100644 --- a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/ApacheMP2.pm +++ b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/ApacheMP2.pm @@ -44,9 +44,6 @@ sub launch { eval "require $class"; die $@ if ($@); - $class->logger->info( - "New request $class " . $req->method . " " . $req->request_uri ); - # register the request object to the logging system if ( ref( $class->logger ) and $class->logger->can('setRequestObj') ) { $class->logger->setRequestObj($req); @@ -57,6 +54,9 @@ sub launch { $class->userLogger->setRequestObj($req); } + $class->logger->info( + "New request $class " . $req->method . " " . $req->request_uri ); + my ($res) = $class->$sub($req); # Clear the logging system before the next request -- GitLab From 75e2346ee9d24dae8ed3c72600c392a555fdbc52 Mon Sep 17 00:00:00 2001 From: Maxime Besson Date: Tue, 12 Mar 2024 14:17:54 +0100 Subject: [PATCH 6/6] Fix tests for #3120 --- lemonldap-ng-common/t/10-PSGI-Request.t | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lemonldap-ng-common/t/10-PSGI-Request.t b/lemonldap-ng-common/t/10-PSGI-Request.t index 45d28ff138..a1d2d6e255 100644 --- a/lemonldap-ng-common/t/10-PSGI-Request.t +++ b/lemonldap-ng-common/t/10-PSGI-Request.t @@ -1,5 +1,4 @@ use strict; -use open ':std', ':encoding(utf8)'; use Test::More; use Plack::Test; use Lemonldap::NG::Common::PSGI::Request; @@ -7,7 +6,13 @@ use Lemonldap::NG::Common::PSGI::Request; use JSON; use HTTP::Request; use HTTP::Message::PSGI; + +# UTF-8 awareness use utf8; +my $builder = Test::More->builder; +binmode $builder->output, ":encoding(utf8)"; +binmode $builder->failure_output, ":encoding(utf8)"; +binmode $builder->todo_output, ":encoding(utf8)"; sub build_json_request { my ($href) = @_; -- GitLab