2016-08-29 3 views
14

Я пытаюсь выяснить, есть ли способ завершить ответ в mod_perl 2, не возвращаясь к основному обработчику. Пока не удалось найти способ для этого в документах. Ниже приведен пример того, что я пытаюсь достичь:Close response in mod_perl 2

#!/usr/bin/perl 
# This is some mod_perl handler 
use strict; 
use warnings; 
use Apache2::Const ':common'; 

sub handler { 
    my $r = shift; 
    if ($r->method eq 'POST') { 
     # just to do something as example 
     do_post_response($r); 
    } 
    $r->content_type('text/plain'); 
    print "Thank you, goodbye."; 
    return Apache2::Const::OK; 
} 

sub do_post_response { 
    my $r = shift; 
    unless (check_somthing()) { 
     # Suppose I find a situation that requires 
     # a different response than normal... 
     $r->content_type('text/plain'); 
     print "We have a situation..."; 
     $r->something_to_finish_the_request_immediatly(Apache2::Const::OK); 
    } 
} 

В обычном сценарии Perl, работает как отдельно или под mod_cgi, я мог бы просто exit() с новым ответом, но под mod_perl мне нужно возвратите что-то в оригинальной подпрограмме handler. Это побуждает меня отслеживать целую цепочку звонков, где все они должны что-то вернуть, пока я не вернусь к основному handler.

Например, вместо:

unless (check_something()) { ... 

мне нужно сделать что-то вроде:

my $check = check_something(); 
return $check if $check; 

и я должен сделать что-то подобное в основной обработчик, который является довольно ungly для некоторых положение дел.

Есть ли способ закрыть запрос, когда внутри вложенного вызова, как и то, что я попытался проиллюстрировать с помощью моего примера?

EDIT: Я обнаружил, что я могу назвать goto LABEL и место, которое маркировать только до последнего возвращения в основном handler подпрограммы. Он работает, но все еще чувствует себя грязным хаком. Я действительно надеюсь, что есть более хороший способ.

+2

Я не эксперт по mod_perl2, но в целом это выглядит как-то вы бы использовать исключения для. Внутри do_post_response() используйте 'die 'У нас есть ситуация ..."; 'и поймаем это в обработчике(), используя блок' eval' или даже лучше используя модуль, например 'Try :: Tiny'. Добавьте «Исключение :: Класс», если вам нужно отличать свои пользовательские исключения от других, которые могут возникнуть в результате других неперехваченных сбоев. – mbethke

ответ

2

Я думаю, что вы все еще в порядке вызвать выход(), потому что mod_perl перекрывают выход делает:

выход

В обычном Perl кода выхода() используется, чтобы остановить поток программы и выйти из интерпретатора Perl. Однако в mod_perl мы хотим только остановить поток программы, не убивая интерпретатор Perl.

Вы не должны предпринимать никаких действий, если ваш код включает вызовы exit(), и все в порядке, чтобы продолжить их использование. mod_perl беспокоится о переопределении функции exit() со своей собственной версией, которая останавливает поток программы и выполняет все необходимые очистки, но не убивает сервер. Это делается путем переопределения:

* CORE :: GLOBAL :: exit = \ & ModPerl :: Util :: exit;

https://perl.apache.org/docs/2.0/user/coding/coding.html

+0

Я попробовал выйти, прежде чем задавать этот вопрос. Он не работает, он не делает обработчик возвратом того, что ему нужно вернуть, это то же самое, что вызвать смерть. –

+0

Тогда у вас есть еще одна проблема в коде или ваш mod_perl был изменен. mod_perl отменяет exit, как объясняется в документах, которые я связывал. –

+0

Да, он отменяет выход, потому что вы находитесь в постоянном интерпретаторе, и вы не хотите, чтобы он действительно вышел.Если вы используете реальный выход, вы фактически убиваете поток Apache. Однако тот факт, что он отменяет выход, просто завершает текущий вызов функции, но он не возвращает ничего в Apache, и в этом проблема, Apache нуждается в фактическом ответе или принимает его как отказ в запросе. –