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

Hello folks,
I am trying to troubleshoot both ends of an asp.net web "service". The provider of the service doesn't know much about what is going on. I suspect they are using something out-of-a-box. Thus, I'm left to figure out both ends myself.

The sequence of events goes like this:
1) I send a http get request with parameters to server
2) server does some processing
3) server returns a http response of raw text(no html formatting)

This works fine when I use a web browser such as IE or Firefox. However, when I send the request via LWP, I get a web service error back.

Assuming the problem is on my end, I suspect that I am sending some improper or invalid HTTP headers. To check this I sent a basic LWP request to a java servlet running on my own machine, and it shows that I sent it the following http header name-value pairs:

te: deflate,gzip;q=0.3
connection: TE, close
host: x.x.x.x
user-agent: libwww-perl/5.803


The first 2 headers appear messed up and it seems like my servlet may have had a parsing problem. My questions to the monks:

-how can I print out the entire raw LWP http request(first line, headers, and body), without having to send it elsewhere to print it?
-does LWP::UserAgent always add certain headers to be sent? How does one delete or clear out ALL headers? I have tried both

    $response = $ua->get($url);
and
    $req = new HTTP::Request("GET",$url,HTTP::Headers->new);
$response = $ua->request($req);

conventions. Both produce the same http headers/request. Lastly, my PERL code worked fine when I tested it out on a few commercial websites such as google or yahoo.

"Be proud, be a Goon"

Replies are listed 'Best First'.
Re: how to validate lwp::useragent request?
by ikegami (Patriarch) on Jun 07, 2005 at 21:11 UTC

    $request->as_string() returns the request, headers and all. However, it needs to be called AFTER the UserAgent adds its headers. You can force UserAgent to add its headers by calling the UserAgent's prepare_request. To avoid calling prepare_request a second time, substitute a call to the UserAgent's send_request method for the call to the its request method.

    In other words, replace

    $response = $ua->request($request);

    with

    $ua->prepare_request($request); print($request->as_string); # $response = $ua->send_request($request);

    Uncomment the commented line if you want to both log and send the request.

    Similarly, get is just a shortcut to return a request object and passing it to the UserAgent's request method.

    $response = $ua->get($url);

    is the same thing as

    $request = HTTP::Request::Common::GET($url); $response = $ua->request($request);

    so replace it with

    $request = HTTP::Request::Common::GET($url); $ua->prepare_request($request); print($request->as_string); # $response = $ua->send_request($request);
Re: how to validate lwp::useragent request?
by Qiang (Friar) on Jun 07, 2005 at 21:48 UTC
    you can use LWP::DebugFile to debug your script and it allows you to see what your calls to LWP are doing behind the scenes. so you get more info than the headers. for browser, I use LiveHTTPHeaders, the firefox plugin to get the header.

    sometimes, it's hard to mimic the request on the first try when remote use js,cookie,user-agent checking etc.

    inspect the difference between sending request through browser and through LWP, then fill the difference in your perl script and try again.

    oh, i found the headers_as_string is handy too. it ruturns the response header as string which may be suffice for you to check the return header. an example i use is to extract the url out of meta refresh from the response header (LWP only follow http 301,302,303,307 redirect)

    use LWP; my $br = LWP::UserAgent->new; my $resp = $br ->get('http://www.pulse24.com'); print $resp->headers_as_string"; __END__ Client-Peer: 207.61.136.40:80 Client-Response-Num: 1 REFRESH: 0;URL=http://www.pulse24.com/Front_Page/page.asp X-Meta-Robots: noindex X-Powered-By: ASP.NET
Re: how to validate lwp::useragent request?
by jhourcle (Prior) on Jun 07, 2005 at 21:58 UTC

    It's not a perl answer, but sometimes when troubleshooting it's good to just sniff the connection. There are plenty of free network sniffers out there, provided wherever you work doesn't have a policy against using them.

    (use your favorite search engine to find one for your platform)

Re: how to validate lwp::useragent request?
by jpeg (Chaplain) on Jun 07, 2005 at 22:47 UTC
    I doubt LWP is sending anything 'wrong'. It's far more likely that the server is checking the user agent. Fortunately, LWP and related HTTP::Header and HTTP::Response objects are eminently scriptable. You can set headers to whatever you'd like.

    To see all headers and values, use HTTP::Header's scan() method.

    #!/usr/bin/perl use strict; use LWP::UserAgent; my $agent = LWP::UserAgent->new; my $headers = HTTP::Headers->new('User_Agent' => 'Cyberdog/5.0', 'Accept' => 'image/gif, image/x-xbitmap, image/png, image/jpeg, */*', 'Accept-Charset' => 'iso-8859-1', 'Accept-Language' => 'en-US'); #headers before the request: $headers->scan(\&printheaders); my $response = $agent -> get('http://localhost', $headers); #and after: $response->scan(\&printheaders); sub printheaders() { my $h = shift; my $v = shift; print ("Header: $h \t Value:$v\n"); }
    You can clear all headers using HTTP::Headers' clear() method, but I don't think it's what you want.
    --
    jpg
      No, that's not right. Your method is not guaranteed to print all the headers. You're listing the headers too soon. For example, if you stopped overridding User-Agent, your method wouldn't list all the headers. See my post above for an explanation of why.
Re: how to validate lwp::useragent request?
by goonfest (Sexton) on Jun 08, 2005 at 15:14 UTC
    Well it turns out my problem was two-fold. First of all, the webservice I was attempting to access via lwp was url redirecting multiple times. I wasn't handling this properly. Secondly, as part of the headers I was ignoring any cookies that the server set. I didn't think they were necessary, but it turns out they were. I guess ASP.net requires accepting a sessionID cookie.

    Once I properly handled both of those items I was able to receive successful results. Thanks for the help printing out the headers.

    "Be proud, be a Goon"