Gerard has asked for the wisdom of the Perl Monks concerning the following question:

Dear Monks,
I am quite comfortable using CGI.pm for retrieval of data submitted from a form, but am not sure if I can use it for the following.
I have been asked to write a script that will be called via a webserver from an existing piece of software, passing parameters similar to some of these:
MyScript.pl?DELIVERMESSAGE MyScript.pl?MESSAGECOUNT&BRANCH=<branch> MyScript.pl?TOTALDATASIZE&BRANCH=<branch> MyScript.pl?GETMESSAGE&BRANCH=<branch>&TIMEOUT=10
So obviously when it is called I want to know if it is DELIVERMESSAGE or MESSAGECOUNT etc. and deal with it appropiately. Can I use CGI.pm to do this, or some other methodswould be more appropiate?
In addition, in the description of the desired behaviour, my manager has written "Get branch ID from HTTP header variable called “Comms-Branch”. " I am not quite sure what he means by "HTTP header variable", but as I am new in this position I don't want to appear foolish, and rather, impress. Any help greatly appreciated.

Regards,
Gerard

Replies are listed 'Best First'.
Re: CGI Parameters
by Roger (Parson) on Jan 12, 2004 at 02:52 UTC
    Yes, you can certainly do this using the CGI module. Note that you don't have to create a hash of variables, and use if (defined $cgi->param('DELIVERMESSAGE')){ ... directly, but then you will have to worry about casing - (what if the variable names are passed in lower case?)
    #!C:/Perl/bin/perl.exe -w use strict; use CGI; use Data::Dumper; my $cgi = new CGI; my @cgi_vars = $cgi->param(); if ($#cgi_vars < 0) { # handle the case of no CGI parameters # ... exit(0); } # build a (normalized) hash of CGI variables # with variable name converted to upper case my %vars = map { uc($_) => $cgi->param($_) } @cgi_vars; # debug only - display the variable hash #print Dumper(\%vars); # Handle the requests if (defined $vars{DELIVERMESSAGE}) { # do deliver message # ... } elsif (defined $vars{MESSAGECOUNT} && defined $vars{BRANCH}) { # do message count # $vars{BRANCH} is the branch name # ... } elsif (defined ..... ) { # etc. etc. }
Re: CGI Parameters
by etcshadow (Priest) on Jan 12, 2004 at 04:02 UTC
    When your manager says that "Comms-Branch" is a "HTTP header variable", he means that it is in the HTTP header. The HTTP header is a big chunk of text in the request and the reply. For example, an HTTP request might look something like this:
    GET /dir/page.pl HTTP/1.1 Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */* Referer: http://www.foo.bar/otherdir/otherpage.pl Accept-Language: en-us Content-Type: application/x-www-form-urlencoded Accept-Encoding: gzip, deflate User-Agent: Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt) Host: www.foo.bar Cookie: monster=blue; My-Other-Header: yippy yahoo!
    All of those lines except for the first one are "headers"... they basically act (sorta) like a perl hash, in that they are name-value pairs. Some of those headers have particular meaning to the web browser and web server (most of them, in fact). However, the user agent (the application making the web-service request in this case) can really put any arbitrary header in there, as long as it doesn't conflict with a name used by a real header.

    Anyway, if I wanted to find the value used by, for example, the "My-Other-Header" header... I could find it in the environment by looking at (yes, it does get driven all into uppercase): $ENV{HTTP_MY_OTHER_HEADER}. So, in your example, you could find "Comms-Branch" http header in $ENV{HTTP_COMMS_BRANCH}. For more information, you can examine the environment by putting:

    use Data::Dumper; warn Dumper \%ENV;
    in your code, and then looking at the error-log. All of the (non-special) HTTP headers get written into the subprocess's environment with the prefix HTTP, all uppercase, and with non-word characters turned to underscore.

    Anyway, hope that helps. Oh, and this should be the same whether you are using old-school CGI (not CGI.pm, mind you... but the common-gateway-interface, which CGI.pm is a wonderful tool to help you use) or under mod_perl (again... with or without CGI.pm).

    ------------ :Wq Not an editor command: Wq
Re: CGI Parameters
by cLive ;-) (Prior) on Jan 12, 2004 at 06:35 UTC
    Just to add to what the others have said, you might find this little script useful:
    #!/usr/bin/perl use strict; use warnings; use CGI; use Data::Dumper; my $q = CGI->new(); my %var = $q->Vars(); my $log_file = '/path_to_log'; open(LOG,">>$log_file") || err("Can't open log file: $!"); print LOG "URL: $ENV{REQUEST_URI}\n\n", Dumper(\%var,\%ENV)."\n\n", '=' x 60, "\n\n"; print $q->header('text/plain'). "Everything's OK"; sub err { print $q->header('text/plain'). "ERROR: $_[0]"; exit(0); } exit(0);

    Save that as MyScript.pl and set $log_file to point to a file that you can write to.

    Then, when the script is called:

    • $VAR1 will list the parameters sent - accessible through $q->param('VARNAME').
    • $VAR2 will list all environment variables, including the HTTP headers sent, accessible through $ENV{VARNAME}. (%ENV is a "special" Perl variable. You might also want to read up on that too)

    So, you can call it with various query string info to see what variables get set, and you can ask your manager to request the URL so that you can see exactly what HTTP header his request is sending.

    Hope this is useful to get you started.

    cLive ;-)

    Update: added err() sub (oops :)

      Thanks Clive,
      I was thinking that would be the smartest way to go about it, and was going to write a script to do it, but you have just saved me a whole lot of time! Thanks
      Much thanks to all for their helpful comments. Gerard.
Re: CGI Parameters
by TomDLux (Vicar) on Jan 12, 2004 at 02:45 UTC

    You need to read perldoc CGI.

    You'll find those variables in:

    param('DELIVERMESSAGE') param('MESSAGECOUNT')

    etc. I imagine it's these that your manager is refering to when he means HTTP header variables, so there's one you would access as param('Comms-Branch').

    --
    TTTATCGGTCGTTATATAGATGTTTGCA

      I'd assume that HTTP header variables means it's sent in the HTTP header or possibly as a cookie. Don't know if the CGI http() method will get you access to arbitrary header settings; perhaps it depends on what web server you are using. For cookies, see CGI.

      A quick look at the source reveals CGI's http() method just looks for environment variables starting with HTTP.

      Update: as 3dan and etcshadow say, the server uppercases the header labels and prepends HTTP_ to make them available in the environment. (I wonder if this is actually reliable for arbitrary headers on all servers.)

        The CGI->http method lets you access those environment variables starting with 'HTTP', yes. But what you seem to be missing is that those environment variables are set by the webserver to the value of the HTTP headers sent in the request. For example, if you sent this request to you CGI:

        GET /my_cgi.pl HTTP/1.1
        Host: localhost
        Foo: FOO Content here
        
        

        ...then the following code should get you the value 'FOO Content here':

        use CGI; my $q = CGI->new; my $foo_content = $q->http("Foo"); # or $q->http("HTTP_FOO")

        Update: I see that etcshadow dealt with this in full elsewhere in the thread... hey, a little repetition never hurt anybody, right?

        --
        3dan

Re: CGI Parameters
by stonecolddevin (Parson) on Jan 12, 2004 at 02:46 UTC
    If I am understanding your question correctly, yes, you can use CGI.pm to do this. Just do: $q->param('DELIVERMESSAGE') where $q is the instance of CGI. That will give you the value of DELIVERMESSAGE (in the example below, it would be "bar"), if you are using it as www.foo.com/MyScript.cgi?DELIVERMESSAGE=bar
    As for the Comms-Branch bit, I'm not sure either, are you using any sessions or cookies?

    dhoss
    "and I wonder, when I sing along with you if everything could ever feel this real forever? if anything could ever be this good again? the only thing I'll ever ask of you, you've gotta promise not to stop when I say 'when'", she sang
      Thanks for your reply. Just a quick question. What would $q->param('DELIVERMESSAGE') return if DELIVERMESSAGE is not set to equal anything?.

      ie. If the only thing that is passed is
      MyScript.pl?DELIVERMESSAGE OR MyScript.pl?MESSAGECOUNT
      How would I be able to tell whether they wanted DELIVERMESSAGE or MESSAGECOUNT??
      As for the sessions or cookies, the answer is no.
      Thanks, Gerard.
      Update: I see that roger has answered my question below. It was the defined bit that I was really missing in my understanding
        I would use $ENV{'QUERY_STRING'} then, if you don't have name/value params.

        dhoss
        "and I wonder, when I sing along with you if everything could ever feel this real forever? if anything could ever be this good again? the only thing I'll ever ask of you, you've gotta promise not to stop when I say 'when'", she sang