Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid

Sending application-specific XML as a string paremeter to an RPC::XML method.

by nenbrian (Acolyte)
on Mar 30, 2004 at 00:07 UTC ( #340799=perlquestion: print w/replies, xml ) Need Help??
nenbrian has asked for the wisdom of the Perl Monks concerning the following question:

Hello Perl hackers,

I am writing an application in Perl which will require the use of some sort of RPC mechanism, so I am evaluating RPC::XML, Frontier, and SOAP::Lite for this purpose. One requirement of the application is that I need to be able to transfer application-specific XML data between the client and the server. I have noticed that RPC::XML seems to get confused when I try to send this application XML data as a string paremeter to an RPC::XML method.

My question is, what is the best way to send application specific XML data between the client and the server using RPC::XML? Do I need to encode the application XML data first? Is it just a bad idea to do this in general?


Here is an example illustrating the problem. First is the output, followed by sample code:

Fetching text file small.txt Displaying response object contents: <?xml version="1.0"?> <methodResponse> <params> <param> <value> <string>This is a small text file. </string> </value> </param> </params> </methodResponse> Fetching text file small.xml Displaying response as plain text: Unknown tag encountered: Something

In the first case, the contents of a plain (non-XML) text file is sent, and the method call succeeds.

In the second case, the contents of a small XML file are sent, and the send_request() method fails with the error message "Unknown tag encountered: Something". (it returns a descriptive string on error, or an RPC::XML::response object reference on success). The string "Something" is the tag name of the root element in the sample application XML data that is sent.

RPC::XML server:

#!/usr/bin/perl -w use strict; use RPC::XML::Server; my $server = RPC::XML::Server->new(port => 9000); $server->add_method( { name => 'dump_file', version => '1.0', hidden => 0, code => \&dump_file, signature => [ 'string string' ], help => 'Dumps the contents of the specified file' } ); $server->server_loop(); sub dump_file { my $server = shift; my $fname = shift; my $buffer; print "Calling dump_file\n"; if (-f $fname) { print " Dumping contents of file $fname\n"; open(FILE, $fname); $buffer = join('', (<FILE>)); } else { print "Can't find file $fname: $!\n"; return undef; } return $buffer; }

RPC::XML client:

#!/usr/bin/perl -w use strict; use RPC::XML::Client; my $client = RPC::XML::Client->new('http://localhost:9000/'); my @files = qw(small.txt small.xml); my ($request, $response); foreach my $file (@files) { print "Fetching text file $file\n"; $request = RPC::XML::request->new('dump_file', $file); $response = $client->send_request($request); display_response($response); } sub display_response { my $response = shift; if (ref($response) && $response->can('as_string')) { print "Displaying response object contents:\n", $response->as_string(), "\n"; } else { print "Displaying response as plain text:\n", $response, "\n"; } }

Sample text file:

This is a small text file.

Sample XML file:

<Something> <SubElement> <Foo/> <Bar baz="mumble"/> </SubElement> </Something>

Edited by BazB: readmore tags added

Replies are listed 'Best First'.
Re: Sending application-specific XML as a string paremeter to an RPC::XML method.
by etcshadow (Priest) on Mar 30, 2004 at 00:18 UTC
    You just need to encode the xml string as a string so that you can include it inside of other xml... it's the xml equivalent of putting backslashes in front of your quotation marks when you put a "string" inside of a larger "string".
    $xmlstring =~ s/\&/&amp;/g; $xmlstring =~ s/\</&lt;/g; $xmlstring =~ s/\>/&gt;/g; $xmlstring =~ s/\"/&quot;/g; $xmlstring =~ s/\'/&apos;/g;
    That's all there is to it.
    ------------ :Wq Not an editor command: Wq
Re: Sending application-specific XML as a string paremeter to an RPC::XML method.
by Fletch (Chancellor) on Mar 30, 2004 at 02:12 UTC

    Not the most efficient alternative, but if you send the XML as base64 encoded text you shouldn't have any problems.

    return RPC::XML::base64->new( $buffer );

      Ok, base64 encoding looks like the way to go. This works fine for small XML documents, however, I have notced that when I try to send a large base64-encoded XML document (about 1.5 MB) in this manner, it takes an extremely long time (several minutes). I am using the loopback interface for my testing, so it is not limited by network bandwidth. Is there a more direct way to transfer large ammounts of data between the client and the server? Given that RPC::XML::Server uses HTTP::Daemon and HTTP::Response for its transport, is it possible to directly use HTTP methods such as 'GET' to transfer large documents?


        Doesn't look like it as such, but peeking under the hood what you could do is to create an RPC::XML::Server instance with no_http set to true, then have your own HTTP::Daemon code which passes the body of any XML-RPC calls off to the dispatch() method. Anything which needs to return an XML file would return a URL which your HTTP::Daemon handle itself (rather than passing off to the RPC::XML::Server).

        Hopefully that made some sort of sense. :) Read the docs for RPC::XML::Server, specifically the arguments for new() and the description of dispatch().

        Ok, the large ammount of time spent transferring base64 encoded data appears to be spent in the client, receiving (but not decoding) the encoded data. It appears to be related to the number of newlines in the data, because if I strip them, the data is transferred in a couple seconds. Is there a way to encode the data such that there are no newlines?

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://340799]
Approved by Limbic~Region
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others rifling through the Monastery: (3)
As of 2018-12-15 20:14 GMT
Find Nodes?
    Voting Booth?
    How many stories does it take before you've heard them all?

    Results (70 votes). Check out past polls.