http://qs321.pair.com?node_id=216347

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

Greetings once again!

I am faced with a slight problem, that I don't know how to attack. I need direct access to the client's socket after an HTTP request to an apache server. Let me explain further what I mean:

A client (not a web-browser, a script of some sort), opens up a connection to port 80 on some box where I have apache running, and then it requests a resource. This is part of the problem, as I don't know whether POST, or PUT would be most reasonable (and I can guarantee you that finding examples of PUT handling CGI scripts are *not* easy...) So, it executes a command along the lines of:

POST (or PUT) http://server/cgi-bin/my-script.cgi HTTP/1.1 host: server ???????????????

The fact of the matter is that the ?????'s are being dynamically generated by the client over a potentially long time, so I would like for the server to be in some sort of read loop, handing chunks to the CGI script for partial processing. Just reading from standard in isn't cutting the mustard, nor is doing a multi-part file upload, as it seems like Apache wants to verify the completeness of the entire HTTP request before it passes it off to a handler...

So, oh great knowledgable monks... how do I handle a situation such as this? Is there a way in mod_perl or even normal CGI to get the "data" in some sort of request (POST, PUT, whatever...) before it's been totally completed? And on another note, if anyone has access to a PUT cgi that actually works, I'd be curious to see it...

Replies are listed 'Best First'.
•Re: Direct access to client socket in CGI/mod_perl?
by merlyn (Sage) on Nov 28, 2002 at 17:14 UTC
    It's been my experience that the POST data to Apache mod_cgi-based programs is delivered "live" and not buffered. (As an aside, that's why you can't rely on reading "content-length" number of bytes, because that's only what the browser suggested it was going to send.)

    However, I have to ask the next question: how will your CGI know when the data is actually finished then?

    Also, if there are any proxies in between, all bets are off.

    -- Randal L. Schwartz, Perl hacker
    Be sure to read my standard disclaimer if this is a reply.

      that prob would make pipelined requests kinda difficult. :) would it be better to allow the client to do some sort of client-pull operation, ie, send some sort of meta refresh response to the client, allowing them to poll the server for updates?

      See... having you tell me was exactly what I needed... because I was 99.9% certain that long ago, when I wrote CGI for the first time (before I was sucked into the world of Java app servers and crap like that), POST data arrived as soon as Apache got ahold of it. But, here I was, with my newly installed Redhat Linux 8.0 box... and I'll be damned if that didn't work!

      It would appear, and I don't actually have any documentation to back this up, but the stock Redhat 8 Apache 2.0.40 with it's bundled mod_cgi is somehow "broken." I am making this bold statement due to the fact that on other boxes where I am either using older Apaches, or even similar apaches which *I* compiled, the behavior was as expected. So, thank you!

Re: Direct access to client socket in CGI/mod_perl?
by DapperDan (Pilgrim) on Nov 28, 2002 at 21:24 UTC
    In a cgi environment such as that created by Apache's mod_cgi, the only real difference between a POST request and a PUT request is the contents of $ENV{REQUEST_METHOD}. Do a PUT and a POST request to /cgi-bin/printenv.pl (in a stock Apache deployment) and diff the responses to see what I mean.

    merlyn has already said that mod_cgi gives you a live connection to the socket, so you just read from STDIN in your CGI program as you would normally. People almost always want decoded form/url-encoded name/value pairs so you will see them use CGI.pm, but there is technically nothing to stop you reading STDIN directly. I use this in CGI programs that support machine/non-human HTTP clients, which POST and PUT XML and YAML in the body of the request, rather than the usual form data. (The contents of the Content-type: header change to "text/xml" or whatever to reflect this, obviously.)

    HTH, HAND.