You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modperl@perl.apache.org by B&T <80...@sympatico.ca> on 2000/04/05 04:26:09 UTC

advice/techniques: script control over page transitions

I've generally created a cgi script per page.  Is that a mistake?
(I embed the perl in my html so I can edit pages with an html editor)

I need a better technique for invoking traversals to other pages.
Right now all I can do is a redirect (internal or external).
How do you organize things so that from within a script you can either
display the associated page or invoke any other page/script instead?

    - just do redirects?
    - put all page generation in subroutines in one big .pm?
    - something else (I hope)?


Example:  My main "home" page has links to "login" and "register"
scripts/pages, both of which eventually lead to a "user" page.
With no parameters the login script displays an empty login form.
Called with get/post parameters it processes the form data;
on failure it redisplays the login form with a warning,
on success it should take you to the "user" page (my problem).
How would YOU organize this?

There are lots of tutorials on the net, but I haven't seen anything
about organization between multiple pages. 

(sorry, this is a clarified repost)

my first mod_perl works but ...

Posted by "Peter J. Schoenster" <we...@rede.com>.
Hello,

Nearly all my work has been on virtual servers and recently our 
hosting company (iserver) began to support mod_perl on their 
freebsd servers ... so other than one time in the past I have 
not had the opportunity to write code for mod_perl (except on 
our intranet where it has been for personal use).  As this code 
will be going out for public use I feel more responsiblity. I'm 
still in a situation of 'not knowing what I don't know'.  I 
would really, really appreciate criticisms (with suggestion for 
improvement) for the following code.  I would have used some of 
the modules that seem to do what this does but I did not 
like/understand them and, as  you can imagine, the client wants 
this to work asap.  Thanks.

#!/usr/local/bin/perl5 -w

$|++;

use strict;
use Apache::Request();
use Apache::Cookie();
use DBISUPPORT;
use SERMON_HTML;

use vars qw($r $debug);

$r = Apache->request; 
my $q= Apache::Request->new($r, POST_MAX => 25);
my $html = SERMON_HTML->new();
$debug = 0;


print_headers(1) if $debug;

my $level = '';
my $u = $q->param('u') || '';
my $p = $q->param('p') || '';

$level = verify_user() if (!$u && !$p);

if($level) {
	print_headers();
	print $html->graceful_snippets($level);
	print qq|Level	$level<hr>|;
}else {
	my $user_level = &db_lookup($u,$p);
	if(!$user_level) {
		print_headers();
		print $html->graceful_snippets('generic_header');
		print $html->graceful_snippets('login');
		print $html->graceful_snippets('footer');
	}else {
		print_headers(1,$user_level);
		print $html->graceful_snippets($user_level);
		print qq|Level	$user_level<hr>|;
	}
}

######################################################
##					 BEGIN SUBS						##
sub print_headers {
	my $send_cookie = shift || 0;
	my $nivel = shift || 0;
	$r->content_type("text/html"); 
	if($send_cookie && $nivel > 0) {
		$r->headers_out->add("Set-Cookie" =>qq|nivel=$nivel|); 
	}
	$r->send_http_header();
}
##
sub verify_user {
	my %headers_in = $r->headers_in;
	my $cookie = $headers_in{'Cookie'};
	my(@bites) = split /;/,$cookie;
	my $n = '';
	my $v = '';
	for(@bites) {
		($n,$v) = split /=/;
		$n =~ s/^\s+//;
		if($n eq 'nivel') {
			return $v;
		}
	}
	return undef;
}
##
sub db_lookup {
	my($username,$password) = @_;
	my $dbi= DBISUPPORT->new('this_cgi'=>'/cgi-
bin/login.pl','database'=>'xxxx','username'=>'xxxx','password'=>'
xxxx');	
	my $table = 'members';
	my $sql = qq|SELECT username,level,password FROM $table WHERE 
username = '$username' AND password = '$password'|;
	my $dbu = '';
	my $dbg = '';
	my $dbp = '';
	($dbu,$dbg,$dbp)= $dbi->{'db'}->selectrow_array( qq{ $sql });
	$dbi->{'db'}->disconnect();
	if($dbu && $dbg && $dbp) {
		return $dbg;
	}else {
		return undef;
	}
	
}
##

---------------------------
"Reality is that which, when you stop believing in it, doesn't go
away".
                -- Philip K. Dick

Re: advice/techniques: script control over page transitions

Posted by Gunther Birznieks <gu...@extropia.com>.
I tend to prefer using a library or module to handle CGI logic like this
and then drop out to the main script if the logon has been successful. The
important thing is to make sure that the workflow is separated into a
separate module. In mod_perl, you may have the option of having a mod_perl
handler put up a CGI page or redirect (internally not externally) to a CGI
script if the auth succeeded-- but I am not sure.

I tend to code my stuff for the general public on CGI first even if I have
mod_perl in mind.

Originally in Perl 4 style, I wrote a CGI based authentication library 4
years ago which provides a concrete example of how to do this... it is
loosely documented at

http://www.extropia.com/books/instant_web_scripts/chap09.html from the
Instant Web Scripts book 3 years ago.

The quality of conversion from word document to HTML is pretty poor
because we had some problems with IDG providing us the final PDFs. :(

For a Perl 5 example of doing the same thing (and it is mod_perl
compatible as well as tested with PerlEx) can be found at
http://www.extropia.com/ExtropiaObjects/. Rather than one monolithic Perl
4 library, we decided to break auth loosely into three tiers (AuthManager,
Auth, and Auth::Cache). The relevant plug in library you may wish to look
at is

Extropia::AuthManager::CGI. This is a CGI forms based way of logging on
and registering. It plugs in relatively transparently into CGI scripts and
may be replaced with Extropia::AuthManager::RemoteUser,
Extropia::AuthManager::None, or even Extropia::AuthManager::Certificate
(Client side SSL digital certs) seamlessly depending on what sort of
authentication your application ends up growing into.

Warning: I have not finished writing documentation for this new set of
modules. However, I written about the workflow and design parts in great
detail and would be willing to email you this privately if you like. I
will make the documentation for this public in another week or so.

However, these are real libraries that are working in real situations. So
you could use them if you wanted to.

Later,
   Gunther

B&T wrote:

> I've generally created a cgi script per page.  Is that a mistake?
> (I embed the perl in my html so I can edit pages with an html editor)
>
> I need a better technique for invoking traversals to other pages.
> Right now all I can do is a redirect (internal or external).
> How do you organize things so that from within a script you can either
> display the associated page or invoke any other page/script instead?
>
>     - just do redirects?
>     - put all page generation in subroutines in one big .pm?
>     - something else (I hope)?
>
> Example:  My main "home" page has links to "login" and "register"
> scripts/pages, both of which eventually lead to a "user" page.
> With no parameters the login script displays an empty login form.
> Called with get/post parameters it processes the form data;
> on failure it redisplays the login form with a warning,
> on success it should take you to the "user" page (my problem).
> How would YOU organize this?
>
> There are lots of tutorials on the net, but I haven't seen anything
> about organization between multiple pages.
>
> (sorry, this is a clarified repost)


Re: advice/techniques: script control over page transitions

Posted by Gunther Birznieks <gu...@extropia.com>.
"Jeffrey W. Baker" wrote:

> On Tue, 4 Apr 2000, B&T wrote:
>
> > I've generally created a cgi script per page.  Is that a mistake?
> > (I embed the perl in my html so I can edit pages with an html editor)
> >
> > I need a better technique for invoking traversals to other pages.
> > Right now all I can do is a redirect (internal or external).
> > How do you organize things so that from within a script you can either
> > display the associated page or invoke any other page/script instead?
> >
> >     - just do redirects?
> >     - put all page generation in subroutines in one big .pm?
> >     - something else (I hope)?
> >
> >
> > Example:  My main "home" page has links to "login" and "register"
> > scripts/pages, both of which eventually lead to a "user" page.
> > With no parameters the login script displays an empty login form.
> > Called with get/post parameters it processes the form data;
> > on failure it redisplays the login form with a warning,
> > on success it should take you to the "user" page (my problem).
> > How would YOU organize this?
>
> The way I accomplish this is to divorce the HTML display code from the
> application logic as much as possible.  On the web, once you've started
> your output, you must complete it.  In order to be able to jump to some
> other functionality, you must not start your output until the last
> moment.  Thus it is not good to have markup and code mixed together.
>

I agree with this statement completely.

>
> Suppose you have an application that has a login page, one page with a
> form, and one page that is used to report general errors.  Your handler
> might call an authentication method.  Based on the return value, the
> handler will call either the login method or the method that spits out the
> form.  Either of those methods might return an error, so the handler
> checks the return value and invokes the error handler if necessary.  In
> any case, the various methods do not actually send anything over the wire,
> they simply stash the output away in the request record's notes table.
> The handler is responsible for setting up the response when everything has
> run.
>
> You can see that this design is pretty obvious.  The handler is
> orchestrating a basic flow of events, and the methods that it invokes are
> free to invoke any other method if they wish.  This allows you to
> essentially do an internal redirect without the redirect part :)
>
> That's how I do it, for better or worse.
> -jwb

That is reasonable. In fact, you are not the only one who thinks this way.

For those of you out there who are cross-language developers, Java servlets
provides a similar mechanism.

Servlets can dispatch to other servlets within the same web server-- basically
allowing java data structures to be shared amongst servlets (ie handlers) that
can sandwich each other. Furthermore, the end result can easily dispatch to
JSPs. Thus, you can have a servlet that controls the logical flow through the
program and dispatches to the JSP handler for a particular JSP page.  Thus,
your web designers can still use their DreamWeaver's and FrontPage's whilst
you can focus on creating the logic in the core language.

I am not saying this to promote Java, but rather to provide evidence that
there are others that think the way you do even in the other language
communities.

Later,
  Gunther


Re: advice/techniques: script control over page transitions

Posted by "Jeffrey W. Baker" <jw...@acm.org>.
On Tue, 4 Apr 2000, B&T wrote:

> I've generally created a cgi script per page.  Is that a mistake?
> (I embed the perl in my html so I can edit pages with an html editor)
> 
> I need a better technique for invoking traversals to other pages.
> Right now all I can do is a redirect (internal or external).
> How do you organize things so that from within a script you can either
> display the associated page or invoke any other page/script instead?
> 
>     - just do redirects?
>     - put all page generation in subroutines in one big .pm?
>     - something else (I hope)?
> 
> 
> Example:  My main "home" page has links to "login" and "register"
> scripts/pages, both of which eventually lead to a "user" page.
> With no parameters the login script displays an empty login form.
> Called with get/post parameters it processes the form data;
> on failure it redisplays the login form with a warning,
> on success it should take you to the "user" page (my problem).
> How would YOU organize this?

The way I accomplish this is to divorce the HTML display code from the
application logic as much as possible.  On the web, once you've started
your output, you must complete it.  In order to be able to jump to some
other functionality, you must not start your output until the last
moment.  Thus it is not good to have markup and code mixed together.

Suppose you have an application that has a login page, one page with a
form, and one page that is used to report general errors.  Your handler
might call an authentication method.  Based on the return value, the
handler will call either the login method or the method that spits out the
form.  Either of those methods might return an error, so the handler
checks the return value and invokes the error handler if necessary.  In
any case, the various methods do not actually send anything over the wire,
they simply stash the output away in the request record's notes table.  
The handler is responsible for setting up the response when everything has
run.

You can see that this design is pretty obvious.  The handler is
orchestrating a basic flow of events, and the methods that it invokes are
free to invoke any other method if they wish.  This allows you to
essentially do an internal redirect without the redirect part :)

That's how I do it, for better or worse.
-jwb