views:

150

answers:

1

Hi everyone,

I have this old Perl script that is supposed to act as a proxy of sorts between HTTP-based clients and non-HTTP Java server: the client POSTs some data to this Perl script and the script would in turn call the Java server, get the response and return it to the client.

The Perl part calls the server like this:

$servervars = "-DREMOTE_HOST=$ENV{'REMOTE_HOST'}"; 
#(a few other server variables passed this way)

system "java $servervars -cp /var/www javaserver";

and then the Java server would go:

InputStream serverData = System.in;
serverData.read(); //and read, and read it on
//....
//print response:
System.out.print("Content-type: application/octet-stream\n\n");
System.out.write(...);

Problem is, this works just fine when the Perl script is invoked via CGI, but doesn't work at all if the Perl script is handled by mod_perl (mod_perl2 actually). Apparently the Java part doesn't get the STDIN from Perl (serverData.available() returns 0) and Perl doesn't get the STDOUT back. The latter can be remedied by doing print \java...\ (i.e. backticks) instead of system "java...", but I don't know what to do about STDIN.

The Perl script itself is able to read the POSTed data in STDIN. I've also tried to spawn a test Perl script instead of the Java application, and that doesn't get the parent script's STDIN either.

Judging by the description, spawn_proc_prog from Apache2::SubProcess could do the trick (i.e. pass the POST data as STDIN to the child process and get back the child process' output), but it doesn't seem to work if I run anything but another Perl script.

Is there any way to make the child process inherit the parent script's STDIN? I can read the stream in the Perl script and pass its contents as a command-line parameter, but I presume that would be the subject to command-line length limitations, and sometimes there can be a lot of data (like an picture), so I would really like to figure out how to inherit the stream.

+1  A: 

Wow, I hope this is a low volume load from the client. In mod_perl your stdin is tied to the socket handle from client and same with stdout. So to set your STDOUT to the java process, you need to set the *STDOUT to the Java server's socket handle, or in your case since you are opening a process do a select STDOUT and possibly also make it unbuffered by setting $|. Also when you want to stream data back to your client, you need to write either directly to the client's socket handle or reset STDOUT back to its original value.

Murali VP
Yes, I think this is meant for rather low-volume loads.Could you be more specific regarding what exactly should be done? How would a select on Perl side help - the child process is in Java, it wouldn't care about Perl's default stream.Also, the Java server doesn't have any open sockets - not explicitly at least - it reads everything it needs from STDIN (which may be implemented as sockets underneath, I don't know).
7macaw
So your Java process doesn't listen do any network communication, it is not quite a "server" then. All it does is reads from STDIN. In your perl script do this, my $sh = STDOUT; open(JFH, "|java $servervars -cp /var/www javaserver"); *STDOUT = JFH; then do all your writes from perl, since your java process reads from STDIN, it would read everything you write from perl since you opened your java process that way (the | at the beginning). After you are done writing you have reset your perl's STDOUT back to the original output file handle,which is the client's socket handle which you saved in $sh
Murali VP
Or I guess I can just do print JFH "whatever" instead of copying STDOUT to a variable.Thanks, that seems to work - although now I don't know how to get the Java's output back? I can redirect it into a file, like open(JFH, "|java $servervars -cp /var/www javaserver > /tmp/somefile.txt"); and that may be enough, but I wonder if there's a way to get it as a stream somehow.
7macaw