Hi Scott

Thank you for the extensive explanation of your problem. I'm certainly interested in reviewing your patch

Why using the usual command ::rivet::var_post (see https://tcl.apache.org/rivet/manual3.2/var.html) to retrieve the posted data didn't work for you?

 -- Massimo


On 09/04/23 01:55, Scott Pitcher wrote:
Hi,

I've been writing a system for our website using Rivet as the foundation. I'd written a proc for running CGI programs from the client request, or, passing the request over. This works well but I'd recently started to incorporate some fossil archives in the website. The fossil CGI method worked except when I tried to clone the repo from a shell. Fossil would report an error code and clone would fail.

I examined the website logs and it Fossil makes a POST request to the CGI program. With wireshark I could see around 100 or so binary bytes in the body of the POST request, below the headers:

0000   50 4f 53 54 20 2f 66 6f 73 73 2f 75 6e 69 6d 61   POST /foss/unima 0010   6b 65 73 63 72 69 70 74 73 2e 63 67 69 2f 69 6e kescripts.cgi/in 0020   64 65 78 20 48 54 54 50 2f 31 2e 30 0d 0a 48 6f   dex HTTP/1.0..Ho 0030   73 74 3a 20 77 77 77 2e 73 65 72 76 65 72 32 2e   st: www.server2. 0040   73 76 70 74 73 0d 0a 55 73 65 72 2d 41 67 65 6e   svpts..User-Agen 0050   74 3a 20 46 6f 73 73 69 6c 2f 32 2e 32 30 20 28   t: Fossil/2.20 ( 0060   32 30 32 32 2d 31 31 2d 31 36 20 31 38 3a 34 36   2022-11-16 18:46 0070   3a 33 32 20 5b 32 31 30 65 38 39 61 30 35 39 5d   :32 [210e89a059] 0080   29 0d 0a 43 6f 6e 74 65 6e 74 2d 54 79 70 65 3a   )..Content-Type: 0090   20 61 70 70 6c 69 63 61 74 69 6f 6e 2f 78 2d 66    application/x-f 00a0   6f 73 73 69 6c 0d 0a 43 6f 6e 74 65 6e 74 2d 4c   ossil..Content-L 00b0   65 6e 67 74 68 3a 20 31 30 30 0d 0a 0d 0a 00 00   ength: 100...... 00c0   00 61 78 da 05 c1 41 0a 80 20 10 00 c0 bb af 58   .axÚ.ÁA.. ..À»¯X 00d0   e8 1c ec 6e ba e9 d1 4c ff 21 21 11 94 86 45 ef   è.ìnºéÑLÿ!!...Eï 00e0   6f e6 ee 79 bf 32 6c e7 51 ea 3b 7e a5 3f 47 ab   oæîy¿2lçQê;~¥?G« 00f0   c0 8c 88 c0 c8 4c 44 02 64 b5 4c ac b6 b3 d5 02   À..ÀÈLD.dµL¬¶³Õ. 0100   13 90 1a 20 a1 5d 30 08 e9 e0 8c 8e 5e 4b 8c 22   ... ¡]0.éà..^K." 0110 c6 27 f4 f3 6c 53 10 71 d6 38 b7 92 fa 01 36 4f   Æ'ôólS.qÖ8·.ú.6O 0120   18 9a

I was able to retrieve the headers using ::rivet::apache_table array_get headers_in. I wasn't able to retrieve the body of the POST request. I tried ::rivet::raw_post but it returns an empty string each time.

I checked out the Rivet source and delved into src/mod_rivet_ng and the Rivet_RawPost() function, and traced down to apache_request.h and ApacheRequest_get_raw_post().

The problem is that Rivet_RawPost() uses Tcl_NewStringObj() to pass the body back to Tcl, and given that the first 3 bytes are NUL, we end with an empty string. I changed it to Tcl_NewByteArrayObj() and added a length parameter which was passed by address all the way down to ApacheRequest_get_raw_post():

    data = TclWeb_GetRawPost(private->req, &length);     if (!data) {         data = "";     }     retval = Tcl_NewByteArrayObj((const unsigned char *)data, length);     Tcl_SetObjResult(interp, retval);

... and added a raw_length field to the ApacheRequest structure:

const char* temp_dir; char* raw_post; /* Raw post data. */ int raw_length; request_rec* r; int nargs; } ApacheRequest;

The ApacheRequest_parse_urlencoded() function will fill this field in just after filling in the raw_post pointer, and util_read needed a length pointer parameter as well to get that working:

int ApacheRequest_parse_urlencoded(ApacheRequest *req) { ..... if ((rc = util_read(req, &data, &length)) != OK) { return rc; } if (data) { req->raw_post = (char*) data; /* Give people a way of getting at the raw data. */ req->raw_length = length; split_to_parms(req, data); } } return OK; }

I went to the effort because it's a simple change and I think it completes raw_post , if that function can return the complete body.

That's just my opinion. It's important to me because I have a website structure that can handle content, both HTTP and HTTPS at the same time, as well as user base with login and differentiation between local and remote access. It's been developed so we can include private content for our business only and host files for customers both public (e.g. documentation) and private (firmware and software downloads).

I really wanted to get fossil working under it as it streamlines that part of the development for us. I was going to give up and host the fossil archives separately but I persisted and came up with this. I still haven't had time to pass the POST request into fossil but I'll do so when I have time this weekend, but I do expect it to work, one way or another.

Anyway. That's my situation and if it's at all any use to anyone, I'd be more than happy to give you a patch. It's a really a minor set of changes but they give raw_post a bit more utility.

Further: I'd really like Rivet to have a kind of "run_cgi" method, but I've coded one in tcl at the moment and that's good for testing. At some stage I'll write a Rivet command for doing the same which might make environment setup and processing of the CGI output, headers etc, a bit more efficient.

Kind regards, Scott Pitcher



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to