Rearrange Nginx files
This commit is contained in:
parent
9237dc785a
commit
aa34a28bd3
13
Makefile
13
Makefile
|
@ -321,6 +321,11 @@ start_web_server: all prepare_test_server
|
||||||
@if test "$(TESTWEBSERVER)" = "apache"; then \
|
@if test "$(TESTWEBSERVER)" = "apache"; then \
|
||||||
LLNG_DEFAULTCONFFILE=`pwd`/e2e-tests/conf/lemonldap-ng.ini /usr/sbin/apache2 -d `pwd`/e2e-tests -f apache2.conf -k start; \
|
LLNG_DEFAULTCONFFILE=`pwd`/e2e-tests/conf/lemonldap-ng.ini /usr/sbin/apache2 -d `pwd`/e2e-tests -f apache2.conf -k start; \
|
||||||
elif test "$(TESTWEBSERVER)" = "nginx"; then \
|
elif test "$(TESTWEBSERVER)" = "nginx"; then \
|
||||||
|
echo "Testing nginx conf"; \
|
||||||
|
$(NGINX) -t -p `pwd`/e2e-tests \
|
||||||
|
-g 'error_log '`pwd`'/e2e-tests/conf/nginx.log;' \
|
||||||
|
-c `pwd`/e2e-tests/nginx.conf \
|
||||||
|
2>&1 | grep -v 'Permission denied' || true; \
|
||||||
echo "Launching nginx"; \
|
echo "Launching nginx"; \
|
||||||
$(NGINX) -p `pwd`/e2e-tests \
|
$(NGINX) -p `pwd`/e2e-tests \
|
||||||
-g 'error_log '`pwd`'/e2e-tests/conf/nginx.log;' \
|
-g 'error_log '`pwd`'/e2e-tests/conf/nginx.log;' \
|
||||||
|
@ -364,12 +369,10 @@ restart_web_server: start_web_server
|
||||||
|
|
||||||
plackup:
|
plackup:
|
||||||
@LLNG_DEFAULTCONFFILE=`pwd`/e2e-tests/conf/lemonldap-ng.ini \
|
@LLNG_DEFAULTCONFFILE=`pwd`/e2e-tests/conf/lemonldap-ng.ini \
|
||||||
/sbin/start-stop-daemon --start \
|
plackup -s FCGI \
|
||||||
--pidfile e2e-tests/conf/plackup.pid \
|
|
||||||
-d `pwd` -b -m \
|
|
||||||
--exec /usr/bin/plackup -- \
|
|
||||||
-s FCGI \
|
|
||||||
--listen e2e-tests/conf/llng.sock \
|
--listen e2e-tests/conf/llng.sock \
|
||||||
|
--daemonize --pid e2e-tests/conf/plackup.pid \
|
||||||
|
--nproc 1 --proc-title llng-fastcgi-server \
|
||||||
e2e-tests/llng.psgi
|
e2e-tests/llng.psgi
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
|
@ -25,7 +25,8 @@ server {
|
||||||
# Client requests
|
# Client requests
|
||||||
location / {
|
location / {
|
||||||
auth_request /lmauth;
|
auth_request /lmauth;
|
||||||
auth_request_set $lmlocation $upstream_http_x_location;
|
auth_request_set $lmremote_user $upstream_http_lm_remote_user;
|
||||||
|
auth_request_set $lmlocation $upstream_http_location;
|
||||||
error_page 401 $lmlocation;
|
error_page 401 $lmlocation;
|
||||||
try_files $uri $uri/ =404;
|
try_files $uri $uri/ =404;
|
||||||
|
|
||||||
|
|
2
debian/control
vendored
2
debian/control
vendored
|
@ -111,7 +111,7 @@ Package: liblemonldap-ng-handler-perl
|
||||||
Architecture: all
|
Architecture: all
|
||||||
Depends: ${misc:Depends},
|
Depends: ${misc:Depends},
|
||||||
${perl:Depends},
|
${perl:Depends},
|
||||||
libapache2-mod-perl2,
|
libapache2-mod-perl2 | nginx,
|
||||||
liblemonldap-ng-common-perl (= ${binary:Version}),
|
liblemonldap-ng-common-perl (= ${binary:Version}),
|
||||||
libmouse-perl,
|
libmouse-perl,
|
||||||
liburi-perl,
|
liburi-perl,
|
||||||
|
|
|
@ -18,8 +18,8 @@ my %_apps;
|
||||||
|
|
||||||
my %builder = (
|
my %builder = (
|
||||||
handler => sub {
|
handler => sub {
|
||||||
require Lemonldap::NG::Handler::PSGI::Server;
|
require Lemonldap::NG::Handler::Nginx;
|
||||||
return Lemonldap::NG::Handler::PSGI::Server->run( {} );
|
return Lemonldap::NG::Handler::Nginx->run( {} );
|
||||||
},
|
},
|
||||||
manager => sub {
|
manager => sub {
|
||||||
require Lemonldap::NG::Manager;
|
require Lemonldap::NG::Manager;
|
||||||
|
|
|
@ -119,6 +119,8 @@ has CONTENT_LENGTH => (
|
||||||
);
|
);
|
||||||
has error => ( is => 'rw', isa => 'Str', default => '' );
|
has error => ( is => 'rw', isa => 'Str', default => '' );
|
||||||
|
|
||||||
|
has respHeaders => ( is => 'rw', isa => 'HashRef' );
|
||||||
|
|
||||||
# JSON parser
|
# JSON parser
|
||||||
sub jsonBodyToObj {
|
sub jsonBodyToObj {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
|
|
|
@ -43,8 +43,8 @@ sub AUTOLOAD {
|
||||||
# - Nginx
|
# - Nginx
|
||||||
if ( !$mode or $func eq 'newRequest' ) {
|
if ( !$mode or $func eq 'newRequest' ) {
|
||||||
$mode =
|
$mode =
|
||||||
( ( caller(1) )[0] eq 'Lemonldap::NG::Handler::PSGI::Server' )
|
( ( caller(1) )[0] eq 'Lemonldap::NG::Handler::Nginx' )
|
||||||
? 'PSGI/Server'
|
? 'Nginx'
|
||||||
: (
|
: (
|
||||||
( caller(0) )[0] =~ /^Lemonldap::NG::Handler::PSGI/
|
( caller(0) )[0] =~ /^Lemonldap::NG::Handler::PSGI/
|
||||||
or (
|
or (
|
||||||
|
@ -57,7 +57,7 @@ sub AUTOLOAD {
|
||||||
: $ENV{GATEWAY_INTERFACE} ? 'CGI'
|
: $ENV{GATEWAY_INTERFACE} ? 'CGI'
|
||||||
: ( MP == 2 ) ? 'ApacheMP2'
|
: ( MP == 2 ) ? 'ApacheMP2'
|
||||||
: ( MP == 1 ) ? 'ApacheMP1'
|
: ( MP == 1 ) ? 'ApacheMP1'
|
||||||
: $main::{'nginx::'} ? 'Nginx'
|
: $main::{'nginx::'} ? 'ExperimentalNginx'
|
||||||
: 'CGI';
|
: 'CGI';
|
||||||
unless ( $INC{"Lemonldap/NG/Handler/API/$mode.pm"} ) {
|
unless ( $INC{"Lemonldap/NG/Handler/API/$mode.pm"} ) {
|
||||||
$mode =~ s#/#::#g;
|
$mode =~ s#/#::#g;
|
||||||
|
|
|
@ -0,0 +1,222 @@
|
||||||
|
package Lemonldap::NG::Handler::API::Nginx;
|
||||||
|
|
||||||
|
our $VERSION = '1.9.0';
|
||||||
|
|
||||||
|
use constant FORBIDDEN => 403;
|
||||||
|
use constant HTTP_UNAUTHORIZED => 401;
|
||||||
|
use constant REDIRECT => 302;
|
||||||
|
use constant OK => 0;
|
||||||
|
use constant DECLINED => -1;
|
||||||
|
use constant DONE => -2;
|
||||||
|
use constant SERVER_ERROR => 500;
|
||||||
|
use constant AUTH_REQUIRED => 401;
|
||||||
|
use constant MAINTENANCE => 503;
|
||||||
|
|
||||||
|
my $request; # Nginx object for current request
|
||||||
|
|
||||||
|
## @method void thread_share(string $variable)
|
||||||
|
# not applicable with Nginx
|
||||||
|
sub thread_share {
|
||||||
|
}
|
||||||
|
|
||||||
|
## @method void setServerSignature(string sign)
|
||||||
|
# modifies web server signature
|
||||||
|
# @param $sign String to add to server signature
|
||||||
|
sub setServerSignature {
|
||||||
|
my ( $class, $sign ) = @_;
|
||||||
|
|
||||||
|
# TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
sub newRequest {
|
||||||
|
my ( $class, $r ) = @_;
|
||||||
|
$request = $r;
|
||||||
|
$Lemonldap::NG::API::mode = 'Nginx';
|
||||||
|
}
|
||||||
|
|
||||||
|
## @method void lmLog(string $msg, string $level)
|
||||||
|
# logs message $msg to Apache logs with loglevel $level
|
||||||
|
# @param $msg string message to log
|
||||||
|
# @param $level string loglevel
|
||||||
|
sub lmLog {
|
||||||
|
my ( $class, $msg, $level ) = @_;
|
||||||
|
|
||||||
|
# TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
## @method void set_user(string user)
|
||||||
|
# sets remote_user
|
||||||
|
# @param user string username
|
||||||
|
sub set_user {
|
||||||
|
my ( $class, $user ) = @_;
|
||||||
|
$request->variable( 'lmremote_user', $user );
|
||||||
|
}
|
||||||
|
|
||||||
|
## @method string header_in(string header)
|
||||||
|
# returns request header value
|
||||||
|
# @param header string request header
|
||||||
|
# @return request header value
|
||||||
|
sub header_in {
|
||||||
|
my ( $class, $header ) = @_;
|
||||||
|
$header ||= $class; # to use header_in as a method or as a function
|
||||||
|
return $request->header_in($header);
|
||||||
|
}
|
||||||
|
|
||||||
|
## @method void set_header_in(hash headers)
|
||||||
|
# sets or modifies request headers
|
||||||
|
# @param headers hash containing header names => header value
|
||||||
|
sub set_header_in {
|
||||||
|
my ( $class, %headers ) = @_;
|
||||||
|
while ( my ( $h, $v ) = each %headers ) {
|
||||||
|
if ( $h =~ /cookie/i ) {
|
||||||
|
|
||||||
|
# TODO: check that variable $lmcookie is defined,
|
||||||
|
# else warn that LL::NG cookie will not be removed
|
||||||
|
$request->variable( 'lmcookie', $v );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
# TODO: check that header is not yet set, else throw warning
|
||||||
|
# or reject request if mode paranoid is set
|
||||||
|
# TODO: check that variable nginxName($h) is defined,
|
||||||
|
# else warn that header will not be sent
|
||||||
|
$request->variable( nginxName($h), $v );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
## @method void unset_header_in(array headers)
|
||||||
|
# removes request headers
|
||||||
|
# @param headers array with header names to remove
|
||||||
|
sub unset_header_in {
|
||||||
|
my ( $class, @headers ) = @_;
|
||||||
|
foreach my $h1 (@headers) {
|
||||||
|
|
||||||
|
# TODO: check that header is not yet set, else throw warning
|
||||||
|
$request->variable( nginxName($h), '' );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
## @method void set_header_out(hash headers)
|
||||||
|
# sets response headers
|
||||||
|
# @param headers hash containing header names => header value
|
||||||
|
sub set_header_out {
|
||||||
|
my ( $class, %headers ) = @_;
|
||||||
|
while ( my ( $h, $v ) = each %headers ) {
|
||||||
|
if ( $h =~ /location/i ) {
|
||||||
|
$request->variable( 'lmlocation', $v );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$request->header_out( $h, $v );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
## @method string hostname()
|
||||||
|
# returns host, as set by full URI or Host header
|
||||||
|
# @return host string Host value
|
||||||
|
sub hostname {
|
||||||
|
my $class = shift;
|
||||||
|
return $request->variable('host');
|
||||||
|
}
|
||||||
|
|
||||||
|
## @method string remote_ip
|
||||||
|
# returns client IP address
|
||||||
|
# @return IP_Addr string client IP
|
||||||
|
sub remote_ip {
|
||||||
|
my $class = shift;
|
||||||
|
return $request->variable('remote_addr');
|
||||||
|
}
|
||||||
|
|
||||||
|
## @method boolean is_initial_req
|
||||||
|
# returns true unless the current request is a subrequest
|
||||||
|
# @return is_initial_req boolean
|
||||||
|
sub is_initial_req {
|
||||||
|
my $class = shift;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
## @method string args(string args)
|
||||||
|
# gets the query string
|
||||||
|
# @return args string Query string
|
||||||
|
sub args {
|
||||||
|
my $class = shift;
|
||||||
|
return $request->args();
|
||||||
|
}
|
||||||
|
|
||||||
|
## @method string uri
|
||||||
|
# returns the path portion of the URI, normalized, i.e. :
|
||||||
|
# * URL decoded (characters encoded as %XX are decoded,
|
||||||
|
# except ? in order not to merge path and query string)
|
||||||
|
# * references to relative path components "." and ".." are resolved
|
||||||
|
# * two or more adjacent slashes are merged into a single slash
|
||||||
|
# @return path portion of the URI, normalized
|
||||||
|
sub uri {
|
||||||
|
my $class = shift;
|
||||||
|
return $request->uri();
|
||||||
|
}
|
||||||
|
|
||||||
|
## @method string uri_with_args
|
||||||
|
# returns the URI, with arguments and with path portion normalized
|
||||||
|
# @return URI with normalized path portion
|
||||||
|
sub uri_with_args {
|
||||||
|
my $class = shift;
|
||||||
|
return uri() . ( $request->args ? "?" . $request->args : "" );
|
||||||
|
}
|
||||||
|
|
||||||
|
## @method string unparsed_uri
|
||||||
|
# returns the full original request URI, with arguments
|
||||||
|
# @return full original request URI, with arguments
|
||||||
|
sub unparsed_uri {
|
||||||
|
my $class = shift;
|
||||||
|
return $request->variable('request_uri');
|
||||||
|
}
|
||||||
|
|
||||||
|
## @method string get_server_port
|
||||||
|
# returns the port the server is receiving the current request on
|
||||||
|
# @return port string server port
|
||||||
|
sub get_server_port {
|
||||||
|
my $class = shift;
|
||||||
|
return $request->variable('server_port');
|
||||||
|
}
|
||||||
|
|
||||||
|
## @method string method
|
||||||
|
# returns the method the request is sent with
|
||||||
|
# @return port string server port
|
||||||
|
sub method {
|
||||||
|
my $class = shift;
|
||||||
|
return $request->request_method;
|
||||||
|
}
|
||||||
|
|
||||||
|
## @method void print(string data)
|
||||||
|
# write data in HTTP response body
|
||||||
|
# @param data Text to add in response body
|
||||||
|
sub print {
|
||||||
|
my ( $class, $data ) = @_;
|
||||||
|
$request->print($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
## @method void addToHtmlHead(string data)
|
||||||
|
# add data at end of html head: not feasible with Nginx
|
||||||
|
# @param data Text to add in html head
|
||||||
|
sub addToHtmlHead {
|
||||||
|
my ( $class, $data ) = @_;
|
||||||
|
|
||||||
|
# TODO: throw error log
|
||||||
|
}
|
||||||
|
|
||||||
|
## @method void setPostParams(hashref $params)
|
||||||
|
# add or modify parameters in POST request body: not feasible with Nginx
|
||||||
|
# @param $params hashref containing name => value
|
||||||
|
sub setPostParams {
|
||||||
|
my ( $class, $params ) = @_;
|
||||||
|
|
||||||
|
# TODO: throw error log
|
||||||
|
}
|
||||||
|
|
||||||
|
sub nginxName {
|
||||||
|
my $h = lc(shift);
|
||||||
|
$h =~ s/-/_/g;
|
||||||
|
return "lm_$h";
|
||||||
|
}
|
||||||
|
|
||||||
|
1;
|
|
@ -1,222 +1,12 @@
|
||||||
package Lemonldap::NG::Handler::API::Nginx;
|
package Lemonldap::NG::Handler::API::Nginx;
|
||||||
|
|
||||||
|
use strict;
|
||||||
our $VERSION = '1.9.0';
|
our $VERSION = '1.9.0';
|
||||||
|
|
||||||
use constant FORBIDDEN => 403;
|
use base 'Lemonldap::NG::Handler::API::PSGI';
|
||||||
use constant HTTP_UNAUTHORIZED => 401;
|
|
||||||
use constant REDIRECT => 302;
|
|
||||||
use constant OK => 0;
|
|
||||||
use constant DECLINED => -1;
|
|
||||||
use constant DONE => -2;
|
|
||||||
use constant SERVER_ERROR => 500;
|
|
||||||
use constant AUTH_REQUIRED => 401;
|
|
||||||
use constant MAINTENANCE => 503;
|
|
||||||
|
|
||||||
my $request; # Nginx object for current request
|
|
||||||
|
|
||||||
## @method void thread_share(string $variable)
|
|
||||||
# not applicable with Nginx
|
|
||||||
sub thread_share {
|
|
||||||
}
|
|
||||||
|
|
||||||
## @method void setServerSignature(string sign)
|
|
||||||
# modifies web server signature
|
|
||||||
# @param $sign String to add to server signature
|
|
||||||
sub setServerSignature {
|
|
||||||
my ( $class, $sign ) = @_;
|
|
||||||
|
|
||||||
# TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
sub newRequest {
|
|
||||||
my ( $class, $r ) = @_;
|
|
||||||
$request = $r;
|
|
||||||
$Lemonldap::NG::API::mode = 'Nginx';
|
|
||||||
}
|
|
||||||
|
|
||||||
## @method void lmLog(string $msg, string $level)
|
|
||||||
# logs message $msg to Apache logs with loglevel $level
|
|
||||||
# @param $msg string message to log
|
|
||||||
# @param $level string loglevel
|
|
||||||
sub lmLog {
|
|
||||||
my ( $class, $msg, $level ) = @_;
|
|
||||||
|
|
||||||
# TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
## @method void set_user(string user)
|
|
||||||
# sets remote_user
|
|
||||||
# @param user string username
|
|
||||||
sub set_user {
|
|
||||||
my ( $class, $user ) = @_;
|
|
||||||
$request->variable( 'lmremote_user', $user );
|
|
||||||
}
|
|
||||||
|
|
||||||
## @method string header_in(string header)
|
|
||||||
# returns request header value
|
|
||||||
# @param header string request header
|
|
||||||
# @return request header value
|
|
||||||
sub header_in {
|
|
||||||
my ( $class, $header ) = @_;
|
|
||||||
$header ||= $class; # to use header_in as a method or as a function
|
|
||||||
return $request->header_in($header);
|
|
||||||
}
|
|
||||||
|
|
||||||
## @method void set_header_in(hash headers)
|
|
||||||
# sets or modifies request headers
|
|
||||||
# @param headers hash containing header names => header value
|
|
||||||
sub set_header_in {
|
|
||||||
my ( $class, %headers ) = @_;
|
|
||||||
while ( my ( $h, $v ) = each %headers ) {
|
|
||||||
if ( $h =~ /cookie/i ) {
|
|
||||||
|
|
||||||
# TODO: check that variable $lmcookie is defined,
|
|
||||||
# else warn that LL::NG cookie will not be removed
|
|
||||||
$request->variable( 'lmcookie', $v );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
# TODO: check that header is not yet set, else throw warning
|
|
||||||
# or reject request if mode paranoid is set
|
|
||||||
# TODO: check that variable nginxName($h) is defined,
|
|
||||||
# else warn that header will not be sent
|
|
||||||
$request->variable( nginxName($h), $v );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
## @method void unset_header_in(array headers)
|
|
||||||
# removes request headers
|
|
||||||
# @param headers array with header names to remove
|
|
||||||
sub unset_header_in {
|
|
||||||
my ( $class, @headers ) = @_;
|
|
||||||
foreach my $h1 (@headers) {
|
|
||||||
|
|
||||||
# TODO: check that header is not yet set, else throw warning
|
|
||||||
$request->variable( nginxName($h), '' );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
## @method void set_header_out(hash headers)
|
|
||||||
# sets response headers
|
|
||||||
# @param headers hash containing header names => header value
|
|
||||||
sub set_header_out {
|
|
||||||
my ( $class, %headers ) = @_;
|
|
||||||
while ( my ( $h, $v ) = each %headers ) {
|
|
||||||
if ( $h =~ /location/i ) {
|
|
||||||
$request->variable( 'lmlocation', $v );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$request->header_out( $h, $v );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
## @method string hostname()
|
|
||||||
# returns host, as set by full URI or Host header
|
|
||||||
# @return host string Host value
|
|
||||||
sub hostname {
|
|
||||||
my $class = shift;
|
|
||||||
return $request->variable('host');
|
|
||||||
}
|
|
||||||
|
|
||||||
## @method string remote_ip
|
|
||||||
# returns client IP address
|
|
||||||
# @return IP_Addr string client IP
|
|
||||||
sub remote_ip {
|
|
||||||
my $class = shift;
|
|
||||||
return $request->variable('remote_addr');
|
|
||||||
}
|
|
||||||
|
|
||||||
## @method boolean is_initial_req
|
|
||||||
# returns true unless the current request is a subrequest
|
|
||||||
# @return is_initial_req boolean
|
|
||||||
sub is_initial_req {
|
|
||||||
my $class = shift;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
## @method string args(string args)
|
|
||||||
# gets the query string
|
|
||||||
# @return args string Query string
|
|
||||||
sub args {
|
|
||||||
my $class = shift;
|
|
||||||
return $request->args();
|
|
||||||
}
|
|
||||||
|
|
||||||
## @method string uri
|
|
||||||
# returns the path portion of the URI, normalized, i.e. :
|
|
||||||
# * URL decoded (characters encoded as %XX are decoded,
|
|
||||||
# except ? in order not to merge path and query string)
|
|
||||||
# * references to relative path components "." and ".." are resolved
|
|
||||||
# * two or more adjacent slashes are merged into a single slash
|
|
||||||
# @return path portion of the URI, normalized
|
|
||||||
sub uri {
|
sub uri {
|
||||||
my $class = shift;
|
return $Lemonldap::NG::Handler::API::PSGI::request->original_uri;
|
||||||
return $request->uri();
|
|
||||||
}
|
|
||||||
|
|
||||||
## @method string uri_with_args
|
|
||||||
# returns the URI, with arguments and with path portion normalized
|
|
||||||
# @return URI with normalized path portion
|
|
||||||
sub uri_with_args {
|
|
||||||
my $class = shift;
|
|
||||||
return uri() . ( $request->args ? "?" . $request->args : "" );
|
|
||||||
}
|
|
||||||
|
|
||||||
## @method string unparsed_uri
|
|
||||||
# returns the full original request URI, with arguments
|
|
||||||
# @return full original request URI, with arguments
|
|
||||||
sub unparsed_uri {
|
|
||||||
my $class = shift;
|
|
||||||
return $request->variable('request_uri');
|
|
||||||
}
|
|
||||||
|
|
||||||
## @method string get_server_port
|
|
||||||
# returns the port the server is receiving the current request on
|
|
||||||
# @return port string server port
|
|
||||||
sub get_server_port {
|
|
||||||
my $class = shift;
|
|
||||||
return $request->variable('server_port');
|
|
||||||
}
|
|
||||||
|
|
||||||
## @method string method
|
|
||||||
# returns the method the request is sent with
|
|
||||||
# @return port string server port
|
|
||||||
sub method {
|
|
||||||
my $class = shift;
|
|
||||||
return $request->request_method;
|
|
||||||
}
|
|
||||||
|
|
||||||
## @method void print(string data)
|
|
||||||
# write data in HTTP response body
|
|
||||||
# @param data Text to add in response body
|
|
||||||
sub print {
|
|
||||||
my ( $class, $data ) = @_;
|
|
||||||
$request->print($data);
|
|
||||||
}
|
|
||||||
|
|
||||||
## @method void addToHtmlHead(string data)
|
|
||||||
# add data at end of html head: not feasible with Nginx
|
|
||||||
# @param data Text to add in html head
|
|
||||||
sub addToHtmlHead {
|
|
||||||
my ( $class, $data ) = @_;
|
|
||||||
|
|
||||||
# TODO: throw error log
|
|
||||||
}
|
|
||||||
|
|
||||||
## @method void setPostParams(hashref $params)
|
|
||||||
# add or modify parameters in POST request body: not feasible with Nginx
|
|
||||||
# @param $params hashref containing name => value
|
|
||||||
sub setPostParams {
|
|
||||||
my ( $class, $params ) = @_;
|
|
||||||
|
|
||||||
# TODO: throw error log
|
|
||||||
}
|
|
||||||
|
|
||||||
sub nginxName {
|
|
||||||
my $h = lc(shift);
|
|
||||||
$h =~ s/-/_/g;
|
|
||||||
return "lm_$h";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|
|
@ -30,6 +30,10 @@ sub thread_share {
|
||||||
# nothing to do in PSGI
|
# nothing to do in PSGI
|
||||||
}
|
}
|
||||||
|
|
||||||
|
## @method void newRequest($r)
|
||||||
|
# Store request in global $request variable
|
||||||
|
#
|
||||||
|
#@param $r Lemonldap::NG::Common::PSGI::Request
|
||||||
sub newRequest {
|
sub newRequest {
|
||||||
my ( $class, $r ) = @_;
|
my ( $class, $r ) = @_;
|
||||||
$request = $r;
|
$request = $r;
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
package Lemonldap::NG::Handler::API::PSGI::Server;
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
our $VERSION = '1.9.0';
|
|
||||||
|
|
||||||
use base 'Lemonldap::NG::Handler::API::PSGI';
|
|
||||||
|
|
||||||
sub uri {
|
|
||||||
return $Lemonldap::NG::Handler::API::PSGI::request->original_uri;
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
72
lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Nginx.pm
Normal file
72
lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Nginx.pm
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
# PSGI authentication package written for Nginx. It replace
|
||||||
|
# Lemonldap::NG::Handler::PSGI::Server to manage Nginx behaviour
|
||||||
|
package Lemonldap::NG::Handler::Nginx;
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use Mouse;
|
||||||
|
use Lemonldap::NG::Handler::SharedConf qw(:tsv);
|
||||||
|
|
||||||
|
extends 'Lemonldap::NG::Handler::PSGI';
|
||||||
|
|
||||||
|
## @method Code-Ref _run()
|
||||||
|
# Return a subroutine that call _authAndTrace() and tranform redirection
|
||||||
|
# response code from 302 to 401 (not authenticated) ones. This is required
|
||||||
|
# because Nginx "auth_request" parameter does not accept it. The Nginx
|
||||||
|
# configuration file should transform them back to 302 using:
|
||||||
|
#
|
||||||
|
# auth_request_set $lmlocation $upstream_http_location;
|
||||||
|
# error_page 401 $lmlocation;
|
||||||
|
#
|
||||||
|
#@return subroutine that will be called to manage FastCGI queries
|
||||||
|
sub _run {
|
||||||
|
my $self = shift;
|
||||||
|
return sub {
|
||||||
|
my $req = $_[0];
|
||||||
|
$self->lmLog( 'New request', 'debug' );
|
||||||
|
my $res = $self->_authAndTrace(
|
||||||
|
Lemonldap::NG::Common::PSGI::Request->new( $_[0] ) );
|
||||||
|
|
||||||
|
# Transform 302 responses in 401 since Nginx refuse it
|
||||||
|
if ( $res->[0] == 302 or $res->[0] == 303 ) {
|
||||||
|
$res->[0] = 401;
|
||||||
|
}
|
||||||
|
|
||||||
|
# TODO: transform headers in $res->[1]
|
||||||
|
return $res;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
## @method PSGI-Response router()
|
||||||
|
# Transform headers returned by handler main process:
|
||||||
|
# each "Name: value" is transformed to:
|
||||||
|
# - Headername<i>: Name
|
||||||
|
# - Headervalue<i>: value
|
||||||
|
# where <i> is an integer starting from 1
|
||||||
|
# It can be used in Nginx virtualhost configuration:
|
||||||
|
#
|
||||||
|
# auth_request_set $headername1 $upstream_http_headername1;
|
||||||
|
# auth_request_set $headervalue1 $upstream_http_headervalue1;
|
||||||
|
# #proxy_set_header $headername1 $headervalue1;
|
||||||
|
# # OR
|
||||||
|
# #fastcgi_param $fheadername1 $headervalue1;
|
||||||
|
#
|
||||||
|
# It add also a header called Lm-Remote-User set to whatToTrace value that can
|
||||||
|
# be used in Nginx virtualhost configuration to insert user id in logs
|
||||||
|
#
|
||||||
|
# auth_request_set $llremoteuser $upstream_http_lm_remote_user
|
||||||
|
#
|
||||||
|
#@param $req Lemonldap::NG::Common::PSGI::Request
|
||||||
|
sub router {
|
||||||
|
my ( $self, $req ) = @_;
|
||||||
|
my $hdrs = $req->{respHeaders} || {};
|
||||||
|
my @convertedHdrs =
|
||||||
|
[ 'Lm-Remote-User', $self->userId, 'Content-Length', 0 ];
|
||||||
|
my $i = 0;
|
||||||
|
foreach my $k ( keys %$hdrs ) {
|
||||||
|
$i++;
|
||||||
|
push @convertedHdrs, "Headername$i", $k, "Headervalue$i", $hdrs->{$k};
|
||||||
|
}
|
||||||
|
return [ 200, \@convertedHdrs, [] ];
|
||||||
|
}
|
||||||
|
|
||||||
|
1;
|
|
@ -8,6 +8,8 @@ our $VERSION = '1.9.0';
|
||||||
|
|
||||||
has protection => ( is => 'rw', isa => 'Str' );
|
has protection => ( is => 'rw', isa => 'Str' );
|
||||||
|
|
||||||
|
## @method boolean init($args)
|
||||||
|
# Initalize main handler
|
||||||
sub init {
|
sub init {
|
||||||
my ( $self, $args ) = @_;
|
my ( $self, $args ) = @_;
|
||||||
eval { Lemonldap::NG::Handler::SharedConf->init($self) };
|
eval { Lemonldap::NG::Handler::SharedConf->init($self) };
|
||||||
|
@ -25,6 +27,9 @@ sub init {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
## @methodi CODE-ref _run
|
||||||
|
# Check if protecton is activated then return a code ref that will launch
|
||||||
|
# _authAndTrace() if protection in on or router() else
|
||||||
sub _run {
|
sub _run {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
|
|
||||||
|
@ -45,6 +50,8 @@ sub _run {
|
||||||
|
|
||||||
else {
|
else {
|
||||||
$self->lmLog( 'PSGI app is not protected', 'debug' );
|
$self->lmLog( 'PSGI app is not protected', 'debug' );
|
||||||
|
|
||||||
|
# Check if main handler initialization has been done
|
||||||
unless (%$tsv) {
|
unless (%$tsv) {
|
||||||
$self->lmLog( 'Checking conf', 'debug' );
|
$self->lmLog( 'Checking conf', 'debug' );
|
||||||
eval { Lemonldap::NG::Handler::SharedConf->checkConf() };
|
eval { Lemonldap::NG::Handler::SharedConf->checkConf() };
|
||||||
|
@ -58,6 +65,9 @@ sub _run {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
## @method private PSGI-Response _authAndTrace($req)
|
||||||
|
# Launch Lemonldap::NG::Handler::SharedConf::run() and then router() if
|
||||||
|
# response is 200.
|
||||||
sub _authAndTrace {
|
sub _authAndTrace {
|
||||||
my ( $self, $req ) = @_;
|
my ( $self, $req ) = @_;
|
||||||
Lemonldap::NG::Handler::API->newRequest($req);
|
Lemonldap::NG::Handler::API->newRequest($req);
|
||||||
|
@ -69,36 +79,6 @@ sub _authAndTrace {
|
||||||
$self->lmLog( 'User authenticated, calling router()', 'debug' );
|
$self->lmLog( 'User authenticated, calling router()', 'debug' );
|
||||||
return $self->router($req);
|
return $self->router($req);
|
||||||
}
|
}
|
||||||
|
|
||||||
# Ajax hook: Ajax requests can not understand 30x responses. This
|
|
||||||
# is not really HTTP compliant but nothing in this
|
|
||||||
# protocol can do this. Our javascripts understand that
|
|
||||||
# they have to prompt user with the URL
|
|
||||||
#elsif (
|
|
||||||
# $req->accept =~ m|application/json|
|
|
||||||
# or ( $req->contentType
|
|
||||||
# and $req->contentType =~ m|application/json| )
|
|
||||||
# )
|
|
||||||
#{
|
|
||||||
# $self->lmLog( 'Ajax request detected', 'debug' );
|
|
||||||
# if ( $res == 302 or $res == 303 ) {
|
|
||||||
# $self->lmLog( 'Rewrite redirection to 401 response', 'debug' );
|
|
||||||
# return [
|
|
||||||
# 401, [ 'WWW-Authenticate' => $req->{respHeaders}->{Location} ], ['']
|
|
||||||
# ];
|
|
||||||
# }
|
|
||||||
# else {
|
|
||||||
# $self->lmLog(
|
|
||||||
# "Lemonldap::NG::Handler::SharedConf::run() returns $res",
|
|
||||||
# 'debug' );
|
|
||||||
# return [
|
|
||||||
# $res, [ 'Content-Type', 'application/json' ],
|
|
||||||
# [qq({"error":"$res"})]
|
|
||||||
# ];
|
|
||||||
# }
|
|
||||||
#}
|
|
||||||
|
|
||||||
# Non Ajax requests may be redirected to portal
|
|
||||||
else {
|
else {
|
||||||
my %h = $req->{respHeaders} ? %{ $req->{respHeaders} } : ();
|
my %h = $req->{respHeaders} ? %{ $req->{respHeaders} } : ();
|
||||||
my $s = $tsv->{portal}->() . "?lmError=$res";
|
my $s = $tsv->{portal}->() . "?lmError=$res";
|
||||||
|
@ -148,4 +128,5 @@ sub sendError {
|
||||||
$err = '[' . $self->userId($req) . "] $err";
|
$err = '[' . $self->userId($req) . "] $err";
|
||||||
return $self->Lemonldap::NG::Common::PSGI::sendError( $req, $err, $code );
|
return $self->Lemonldap::NG::Common::PSGI::sendError( $req, $err, $code );
|
||||||
}
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|
|
@ -6,27 +6,18 @@ use Lemonldap::NG::Handler::SharedConf qw(:tsv);
|
||||||
|
|
||||||
extends 'Lemonldap::NG::Handler::PSGI';
|
extends 'Lemonldap::NG::Handler::PSGI';
|
||||||
|
|
||||||
|
## @method PSGI-Response router($res)
|
||||||
|
# If PSGI is used as an authentication FastCGI only, this method will be
|
||||||
|
# called for authenticated users and will set headers in response without
|
||||||
|
# content.
|
||||||
|
# @param $req Lemonldap::NG::Common::PSGI::Request
|
||||||
sub router {
|
sub router {
|
||||||
return [ 200, [], [] ];
|
my ( $self, $req ) = @_;
|
||||||
}
|
my $hdrs = $req->{respHeaders} || {};
|
||||||
|
return [
|
||||||
sub _run {
|
200, [ 'Lm-Remote-User', $self->userId, 'Content-Length', 0, %$hdrs ],
|
||||||
my $self = shift;
|
[]
|
||||||
return sub {
|
];
|
||||||
my $req = $_[0];
|
|
||||||
$self->lmLog( 'New request', 'debug' );
|
|
||||||
my $res = $self->_authAndTrace(
|
|
||||||
Lemonldap::NG::Common::PSGI::Request->new( $_[0] ) );
|
|
||||||
|
|
||||||
# Transform 302 responses in 401 since Nginx refuse it
|
|
||||||
if($res->[0] == 302 or $res->[0] == 303) {
|
|
||||||
$res->[0] = 401;
|
|
||||||
push @{$res->[1]},'X-Location' => $tsv->{portal}->();
|
|
||||||
}
|
|
||||||
|
|
||||||
# TODO: transform headers in $res->[1]
|
|
||||||
return $res;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user