diff --git a/_example/etc/api-nginx.conf b/_example/etc/api-nginx.conf index 42a7978e8d9113f1ff4da0eb7ac6b24164e0e596..34c1ac3b192161787df129cf8604e106b3cc0d60 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 3ba01f9061139ee0b12b5ae5a73b37e4207ca254..7276264c4e842f965ef116a64bdc378db0d43887 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 464dcd8beac66d71af623005b2441f62563ea347..099958ceb7807d5410a6f0a41ed46eb9c2565551 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 f591ac6d2eb76615819eb4e06973a7561d29cca1..03d15361ed248e59b950991b303401c91cff85dd 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; diff --git a/doc/sources/admin/logs.rst b/doc/sources/admin/logs.rst index 24f918fbd03fb48160f0bebd6452cb6af40b6dcc..c0ccd922b2cdfd89f5b17857fb4e44ab733d202f 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 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-common/t/10-PSGI-Request.t b/lemonldap-ng-common/t/10-PSGI-Request.t new file mode 100644 index 0000000000000000000000000000000000000000..a1d2d6e255d9e19e8fdc233156502d6c594fbbda --- /dev/null +++ b/lemonldap-ng-common/t/10-PSGI-Request.t @@ -0,0 +1,59 @@ +use strict; +use Test::More; +use Plack::Test; +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) = @_; + 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(); diff --git a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/ApacheMP2.pm b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/ApacheMP2.pm index 17a005c376f7c2c0661bfc0765f448dfaeb8fcd0..6c40fc585a109c811d9d06f1d48dc82758e1231f 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 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 a9b14df554f3e9d0978be6e37b94d0a9e638433a..04df73349723a3ee0f320c6418ece46151733873 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;