Solved

CGI/Perl script doesn't work after server migration

Posted on 2004-04-08
8
156 Views
Last Modified: 2013-12-25
I'm having some problems with a script that operates on the posted returns from Authorize.net after a successful transaction. We've recently migrated servers and in the process, the version of Perl was upgraded from 5.005_03 to 5.8.

Note: The script in question worked fine for about 2 years on the old server and no code has been changed before being placed on this new server.

Now that we're on the new server, the scripts are taking about 5-15 minutes to execute AFTER the response is received back from Authorize.net. We've been tracing it on the server and are absolutely sure that the response is back from Authorize.net almost immediately. The script eventually completes properly, with the receipt emails being sent out and the results of the order inserted into a mySQL database, but this is far, far longer than the script took on the old server (normally about 10-20 seconds from submission as opposed to 5-15 minutes now).
 
By inserting debug commands that write times out to a log file every other line, we've tracked this issue down to one line which is requiring extremely long processing times, which then results in the scripts pausing for an extremely long time. Once this line is passed, the rest of the script executes in less than 1 second.
 
The problematic line is here:
 
my $s_combined_name = "$s_firstname $s_lastname";
 
We've discovered that the script is able to jump past this line to contine on if the variables $s_firstname and $s_lastname are set with a static value in advance, but if they are not set (in other words, they're blank) in the post back from Authorize.net, the the script hangs. These lines refer to shipping address information. Sometimes this info is not set because the shipping address is the same as billing so the customer does not enter any shipping info. If information is entered for shipping first name ($s_firstname) and shipping last name ($s_lastname), the script runs quickly. Without entries for shipping address, though, it takes forever. I've pasted the full code up to the line in question down below.

Is this something you've seen before? Is this a result of some strict configuration of perl that does not allow blank variables to be parsed or used in an equation? A weird variable scope issue? Something that has to do with the param() method of reading in a POST? We have explored this in great depth over the past two days and are not coming up with an explanation.
 
Again, this script worked fine on the old version of perl, version 5.005_03 built for i386-freebsd. The code has not been changed except for the debugging and tracking code which has now been inserted for troubleshooting purposes.

Thanks!

-------------------------------------------

#!/usr/bin/perl -w

$|=1;           # Switch off buffering


require("xxx-lib.pl");
use strict;
use CGI qw(:standard); #import shortcuts

######################################
#  BEGIN VARIABLES FROM PAGE         #
######################################
#order information
my $itemsOrdered = param("itemsOrdered");
my $total = param("total");
my $clientEmail = param("email");

#customer information
my $firstname = param("firstname");
my $lastname = param("lastname");
my $addressLine1 = param("addressLine1");
my $addressLine2 = param("addressLine2");
my $city = param("city");
my $state = param("state");
my $zipCode = param("zipCode");
my $country = param("country");
my $phone = param("phone");

my $s_firstname = param("shipToFirstName");
my $s_lastname = param("shipToLastName");
my $s_addressLine1 = param("shipToAddressLine1");
my $s_addressLine2 = param("shipToAddressLine2");
my $s_city = param("shipToCity");
my $s_state = param("shipToState");
my $s_zipCode = param("shipToZipCode");
my $s_country = param("shipToCountry");
my $s_phone = param("shipToPhone");
my $s_clientEmail = param("shipToEmail");

my $shipping = param("shipping");
my $shipping_option = param("shipping_option");
my $coupon = param("Coupon");
my $creditCardName = param("creditCardName");
my $creditCardNumber = param("creditCardNumber");
my $expirationMonth = param("expirationMonth");
my $expirationYear = param("expirationYear");
my $hiddenSubTotal = param("hiddenSubTotal");
my $tax = param("tax");

######################################
#  BEGIN LOCAL SCRIPT VARIABLES      #
######################################

my $serverEmail = "xxx\@xxx.com";
my $combined_name = "$firstname $lastname";
my $s_combined_name = "$s_firstname $s_lastname";

my $mailprog = "/usr/sbin/sendmail";
my $discount = "0";
my $coupon_usage = param("coupon_usage");

my $x_response_code = param("x_response_code");
my $order_num;

if ( param("x_response_code") )
{

# AUTHORIZE.NET IS SENDING BACK A RESPONSE CODE, SO CALL
# THE SUBROUTINES TO FINISH UP THE ORDER AND REDIRECT

      &processOrder();
      exit;

}

<snipped the end of the script>


-------------------------------------------
0
Comment
Question by:Bill_B
  • 3
  • 3
  • 2
8 Comments
 
LVL 2

Accepted Solution

by:
healthstatus earned 500 total points
ID: 10792511
Probably the easiest thing to try immediately is change:
my $s_firstname = param("shipToFirstName");
my $s_lastname = param("shipToLastName");

to

my $s_firstname = param("shipToFirstName") || '';
my $s_lastname = param("shipToLastName")|| '';

or even

my $s_firstname = param("shipToFirstName") || $firstname ;
my $s_lastname = param("shipToLastName")|| $lastname ;


and

my $s_combined_name = "$s_firstname $s_lastname";

to

my $s_combined_name = $s_firstname . " " . $s_lastname;

param("shipToFirstName")  is probably coming in undefined from CGI, and that is causing the system to spend extra cycles trying to figure out what you mean.
0
 

Author Comment

by:Bill_B
ID: 10795110
Thanks. I'll give this a shot. This is exactly the type of thing I was fishing for, but on first attempt it doesn't appear to be fixing the issue. I'll explore further and let you know.

The strange thing is that I can move the script back and forth between one box (old version of Perl) and another (new version of Perl) and it will work without fail on one but always have problems on the other.
0
 
LVL 2

Expert Comment

by:healthstatus
ID: 10795194
I would really like you to think about going to the object oriented version of CGI, and making things a little slicker, along the lines of:

UNTESTED CODE FOLLOWS
# object def
my $input = CGI->new;
# get an array of all the parameters with stuff in them
my @what_i_got_back = $input->param();

#create a hash of the return parameters to use and the corresponding variable name
my %i_need = (
firstname => '$firstname',
lastname => '$lastname',
shipToFirstName => '$s_firstname',
 shipToLastName => '$s_lastname',
etc....
);

# go through the array one at a time
foreach my $param (@what_i_got_back){
      if(exists $i_need{$param}){    # if the parameter is in your %i_need hash
            ${$i_need{$param}} = $input->param($param) ;  # put the value in the named variable
            }
      }

You may have an old version of CGI with the 5.005 which handles timing differently than the more current ones.
0
 
LVL 48

Expert Comment

by:Tintin
ID: 10809770
healthstatus.

You can simply do

use CGI;
my $q = new CGI;
my %param = $q->Vars;

to popular the param hash.
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 2

Expert Comment

by:healthstatus
ID: 10810180
Yes, but the param names don't match the variable names below, by setting a hash that cross references the input params with the variables he can keep the rest of the program as is.....
0
 
LVL 48

Expert Comment

by:Tintin
ID: 10810235
Whoops.  Didn't look at the code carefully enough.
0
 

Author Comment

by:Bill_B
ID: 10817056
Thanks so much for the help HealthStatus (and TinTin). Your posts were quite informative and helpful.

In the end, I believe that part of the problem was when a variable would end up being undefined and so your

  $param("variablename") || '';

fix helped the speed of the cycling.

The big thing that was really going on, though, was that the code was repeatedly re-declaring global variables. Sometimes from within subroutines, sometimes it would just declare a global variable again for no reason on the next line. I assume the old version of Perl ignored this, but the new version is more strict on syntax and variable scope.

In the end, I went through the whole thing one subroutine at a time, analyzed what was going on and removed excessive declarations. That speeded it up quite a bit.

Thanks!
0
 

Author Comment

by:Bill_B
ID: 10817080
By the way, that debugging that pointed to a pause at a certain line may or may not have been helpful. In retrospective, it doesn't seem to have been pointing to the real problem. When I'm less burnt out, maybe I'll go back and see if the tests really point to what was going on.
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

This article is meant to give a basic understanding of how to use R Sweave as a way to merge LaTeX and R code seamlessly into one presentable document.
This article will show, step by step, how to integrate R code into a R Sweave document
The viewer will learn the basics of jQuery, including how to invoke it on a web page. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery.: (CODE)
In this fifth video of the Xpdf series, we discuss and demonstrate the PDFdetach utility, which is able to list and, more importantly, extract attachments that are embedded in PDF files. It does this via a command line interface, making it suitable …

744 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now