Simplest way (or module) to tweak query in CGI server-side validation

J

Jerry Krinock

I've been working on my first perl cgi script for server-side form
validation today. I was amazed to find out that, after validating,
all I have to do is

print "Location: $redirect\n\n";

and my form gets redirected to another script. One line? No
modules? Great!

However, it looks like this simply passes through the received query
string, and now I realize I need to change a value or two in the query
after validation, for example, multiplying price by a coupon discount.

Is there any similar simple way to edit the query before sending the
redirect? Or do I need a module? Looks like

use CGI ;

has the functions I need. But I see there are other modules
available. If I need a module, what is a good one that my web host is
likely to have already installed?

Thank you,

Jerry Krinock
 
G

Gunnar Hjalmarsson

Jerry said:
I've been working on my first perl cgi script for server-side form
validation today. I was amazed to find out that, after validating,
all I have to do is

print "Location: $redirect\n\n";

and my form gets redirected to another script. One line? No
modules? Great!

However, it looks like this simply passes through the received query
string, and now I realize I need to change a value or two in the query
after validation, for example, multiplying price by a coupon discount.

Sounds like you don't want to just redirect, after all, but rather
submit a new query. The libwww-perl family of modules can do that; see
for instance LWP::UserAgent.
 
J

jerrykrinock

Sounds like you don't want to just redirect, after all, but rather
submit a new query. The libwww-perl family of modules can do that; see
for instance LWP::UserAgent.

Thank you, Gunnar. After playing with this for a couple weeks (not
full-time), I decided that I ^really^do^ want a redirect, not to
submit a new query. The reason is that I need the user to get a
response from the site that I redirected to, not my redirecting/
tweaking script. I could not find any function in LWP::UserAgent to
do a redirect, so I used CGI.

I have uploaded two "bonehead" scripts:
"Redirector.pl" redirects to "QueryHandler.pl", using CGI's
"redirect" function.
"QueryHandler.pl echoes the query back to the user, using CGI's
"Dump()" function.

Result of Experiments:

If you "go direct", entering into your web browser something like:
http://sheepsystems.com/cgi-test/sales/QueryHandler.pl?name=Jerry&color=blue
you get your query echoed back to you as expected.

But if you try and do that through my redirect, entering
http://sheepsystems.com/cgi-test/sales/Redirector.pl?name=Jerry&color=blue
it gets redirected OK but you don't get your query pairs echoed back.
This is because QueryHandler.pl does not get the query pairs. (I have
also confirmed this by writing to a log file.)

Is there any way to pass a query through a redirecting script, or am I
expecting something that is fundamentally impossible? (Recall that in
my actual application, the redirecting script will tweak some of the
values in the query.)

Thanks again,

Jerry

******** Redirector.pl *****************

#!/usr/bin/perl

use strict ;
use warnings ;
use CGI ;

my $httpQuery = new CGI;
my $redirectURL = "http://sheepsystems.com/cgi-test/sales/
QueryHandler.pl" ;
print $httpQuery->redirect($redirectURL) ;

exit() ;


******** QueryHandler.pl *****************

#!/usr/bin/perl

use strict ;
use warnings ;
use CGI ;

my $httpQuery = new CGI ;

my $returnBody .= "<p>Module CGI got query list:</p>" ;
my $cgiDump = $httpQuery->Dump() ;
if (defined($cgiDump)) {
$returnBody .= $cgiDump ;
}

# Output to client application
print "Content-type: text/html\n";
print "Status: ", 200, " \n\n";
print "<html>$returnBody</html>" ;

exit() ;
 
G

Gunnar Hjalmarsson

Thank you, Gunnar. After playing with this for a couple weeks (not
full-time), I decided that I ^really^do^ want a redirect, not to
submit a new query. The reason is that I need the user to get a
response from the site that I redirected to, not my redirecting/
tweaking script. I could not find any function in LWP::UserAgent to
do a redirect, so I used CGI.

I have uploaded two "bonehead" scripts:
"Redirector.pl" redirects to "QueryHandler.pl", using CGI's
"redirect" function.
"QueryHandler.pl echoes the query back to the user, using CGI's
"Dump()" function.

Result of Experiments:

If you "go direct", entering into your web browser something like:
http://sheepsystems.com/cgi-test/sales/QueryHandler.pl?name=Jerry&color=blue
you get your query echoed back to you as expected.

But if you try and do that through my redirect, entering
http://sheepsystems.com/cgi-test/sales/Redirector.pl?name=Jerry&color=blue
it gets redirected OK but you don't get your query pairs echoed back.
This is because QueryHandler.pl does not get the query pairs. (I have
also confirmed this by writing to a log file.)

Is there any way to pass a query through a redirecting script, or am I
expecting something that is fundamentally impossible?

<snip>

Try this variant of Redirector.pl:

#!/usr/bin/perl

use strict ;
use warnings ;
use CGI ;
use URI::Escape;

my $httpQuery = new CGI;
my $redirectURL =
"http://sheepsystems.com/cgi-test/sales/QueryHandler.pl" ;
addquery( $redirectURL );
print $httpQuery->redirect($redirectURL) ;

sub addquery {
my %params = $httpQuery->Vars;

# change the params to your liking

my %esc_params;
while ( my ($k, $v) = each %params ) {
$esc_params{ uri_escape($k) } = uri_escape($v);
}
my $query = join ';', map "$_=$esc_params{$_}", keys %esc_params;
$_[0] .= "?$query" if $query;
}

__END__
 
J

jerrykrinock

Try this variant of Redirector.pl:

Big thanks to Gunnar. Yes, it works. So, the query is ^not^
automatically carried through by CGI. I have to read in the query,
change as desired, then append it to the redirect URL, starting with
"?". Very simple!

One more thing, though. I believe that this GET request will serve my
purposes, but what if I needed to POST the parameters to the
redirect? I've read some indications that this may not be possible.

The only way I've ever seen a POST transmitted is to use an HTML
<form>. Is there a "bare metal" way to transmit a POST? In order to
^receive^ a POST from CGI using "bare metal", I know you can simply
read STDIN. By analogy, I tried to ^transmit^ a POST by simply
print()-ing out the "key1=value1;key2=value2" string before or after
print($cgi->redirect()), but that does not seem to work. I have
tested and verified that my QueryHandler.pl will handle POST as well
as GET requests from curl, but it does not echo any parameters when
handling a redirect from Redirect.pl, so modified to print() a POST.

Jerry
 
X

xhoster

Big thanks to Gunnar. Yes, it works. So, the query is ^not^
automatically carried through by CGI. I have to read in the query,
change as desired, then append it to the redirect URL, starting with
"?". Very simple!

One more thing, though. I believe that this GET request will serve my
purposes, but what if I needed to POST the parameters to the
redirect? I've read some indications that this may not be possible.

You can direct the user's web-browser to submit to another CGI via GET by
writing it into the URL you are redirecting to. This mostly works because
it is just another URL, and the web browser probably doesn't know or care
it is for CGI. Obviously you would require more active support from the
browser in order to do this with a POST rather than than a GET. And the
browser is unlikely to provide this support, both because it is extra work
and for security reasons.

If the place you are redirecting too will accept a GET instead of a POST,
you could rewrite the POST to your site into the form of a GET for
redirecting. If the place you are redirecting to will not accept GET, or
the query string is too long to be in the form of a GET, that won't work.
What I've done in the past is use LWP to have my CGI post the POST to the
other site, and have the CGI receive the response and proxy it back to the
response back to the user (adding a BASE tag to it so links resolve
properly).

Xho

--
-------------------- http://NewsReader.Com/ --------------------
The costs of publication of this article were defrayed in part by the
payment of page charges. This article must therefore be hereby marked
advertisement in accordance with 18 U.S.C. Section 1734 solely to indicate
this fact.
 
T

Tad J McClellan

The only way I've ever seen a POST transmitted is to use an HTML
<form>. Is there a "bare metal" way to transmit a POST?
^^^^
^^^^

perldoc -q form

How do I automate an HTML form submission?
 
J

jerrykrinock

You can direct the user's web-browser to submit to another CGI via GET by
writing it into the URL you are redirecting to.  This mostly works because
it is just another URL, and the web browser probably doesn't know or care
it is for CGI.  Obviously you would require more active support from the
browser in order to do this with a POST rather than than a GET.  And the
browser is unlikely to provide this support, both because it is extra work
and for security reasons.

Hmmm. I see quite a few issues there
If the place you are redirecting too will accept a GET instead of a POST,

then I will will use the solution given by Gunnar!
If [not] ...
What I've done in the past is use LWP to have my CGI post the POST to the
other site, and have the CGI receive the response and proxy it back to the
response back to the user (adding a BASE tag to it so links resolve
properly).

If I understand you correctly, believe that the address bar in the
user's web browser would then show my Redirector.pl instead of the
Redirectee.pl. That's not acceptable.

Xho, thank you very much for these ideas. After considering them, I
believe the answer to my question "What if the redirectee site won't
take GET and wants POST?" is "Well, then it's time to step back and
redefine the problem so that easier solutions will come into play!"

Jerry
 
J

jerrykrinock

 Is there a "bare metal" way to transmit a POST?
[Reference in perldoc faq which suggesting using LWP::UserAgent]

Well, a module isn't my idea of "bare metal", but the module has
source code, and that source code invokes HTTP::Request::Common, which
has source code too...

http://search.cpan.org/src/GAAS/libwww-perl-5.813/lib/HTTP/Request/Common.pm

and the "sub POST" function beginning at line 24 looks like what I
asked for, the "bare metal" of doing a POST! Hmmm...not a simple
solution, but at least now I know where to look in case I ever really
need to modify and redirect a POST.

Thank you, Tad.
 
B

Ben Morrow

Quoth (e-mail address removed):
Well, a module isn't my idea of "bare metal", but the module has
source code, and that source code invokes HTTP::Request::Common, which
has source code too...

http://search.cpan.org/src/GAAS/libwww-perl-5.813/lib/HTTP/Request/Common.pm

and the "sub POST" function beginning at line 24 looks like what I
asked for, the "bare metal" of doing a POST! Hmmm...not a simple
solution, but at least now I know where to look in case I ever really
need to modify and redirect a POST.

If you really need to know that level of detail, you'd be better off
reading RFC 2616 than the source to LWP... :)

Ben
 
J

jerrykrinock

If you really need to know that level of detail, you'd be better off
reading RFC 2616 than the source to LWP... :)

Indeed, Ben, after stepping back, reading a little of RFC 2616 and
thinking about what the hell I was doing, I realized that I was asking
form something that didn't make sense.

You cannot alter POST parameters of a redirect, because a redirect is
a body-less request that gets sent back to the client. That's why,
when people "redirect" a POST that has parameters in its body, they
have to move the query into the URL, and change the POST into a GET as
in the code Gunnar gave me. Reading in RFC 2616, sections 9.6 and
10.3, I see that this practice is discouraged and/or "out of spec" in
public applications.

But it doesn't matter, because once I understood what I was doing, the
obvious solution was to re-enter my server script and have it re-send
the form. This is probably the conventional way to get the effect I
want, and is what I have now implemented.

Thanks again to all for helping me through this.

Jerry
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,565
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top