HTTPSocket and Apache 2.4.42

I have a Xojo web app that makes a simple call to a web service that authenticates the user. After upgrading the server from ancient Apache 2.2.15 to 2.4.41 my Xojo app could no longer receive/process the result coming back from the server. I know that I’m making an HTTP/1.0 Post operation and thus am expecting a similarly versioned response. I’ve used PAW and/or Curl to test the web service call with no issues under either version of Apache. I assumed the updated service was sending back the wrong format so I added the directive to Apache to always send back HTTP/1.0 and confirmed the response has the HTTP/1.0 headers now…and yet my Xojo program just doesn’t seem to acknowledge a response. It “times out”. Even though my Server logs indicate that the POST was received…processed…and a response was returned. If I shut down Apache 2.4.41 and restart Apache 2.2.15 – the Xojo app works fine again. Ive been comparing the raw response from Curl and see no difference in the response. Since the problem only plagues my server running Apache 2.4.x I have to assume it’s fixable by a configuration change. I don’t really want to change the Xojo program to use the HTTP 1.1 newer POST format if I don’t have to. The argument values I’m transferring are in Form Data format. Any ideas appreciated. I really need to run the more modern (security patched) Apache version.

you could try to play around with SetEnv and force-response-1.0, downgrade-1.0 or force-no-vary
Source: https://httpd.apache.org/docs/2.4/env.html

Is Apache keeping the connection alive (indicated by the response header Connection: keep-alive)? If so then try to get it to close the connection after each request (Connection: close).

I had a similar (but likely different) issue when an Apache upgrade stopped accepting duplicate Host headers - https://forum.xojo.com/55250-httpsocket-apache-and-duplicate-host-headers/0

There are good ideas in that thread (even though none of them worked for me.)

Yes, I had tried the SetEnv with force-no-vary with no success. I did use Curl to verify that the HTTP headers being returned are now HTTP/1.0 – and yet still the Xojo program was unhappy. I don’t believe the connection is being kept alive. In fact, I can shut down the new apache server and fire up the old version and the app starts working again…then I shut-down the old version and switch back to the new and it’s failing again. I’ve tried stopping and restarting the Xojo App – uncertain why that would be necessary since other apps like PAW have no problem hitting either server. The only real change I see in the HTTP response is the Apache Version. It’s very strange. The authentication web service ultimately runs a system script – which I can trace and see the request was received and processed by the server…but the Xojo app “times out” waiting on a response. (I placed a break point as soon as the result comes back) When it times out I have a nil result. It’s just crazy. Maybe I can set some sort of debug level so I can see the exact outgoing response from Apache. Figured somebody may have run into this before. I was able to reproduce the issue on Xojo versions 2017.x - 2019.x – of course all other web services on this box are working just fine. Thank you everyone for your thoughtful replies. They are all worthwhile.

There’s a similarity in our stories: my Xojo app failed while other tests (using Curl, or just a web browser) would work.

To debug it, I ended up doing a low level packet capture on macOS as described here https://support.apple.com/en-us/HT202013 Seeing the actual raw data being transfered was key to figuring out the problem.

Re-reading your description again, I have an idea: could this be Chunked transfer encoding? https://en.wikipedia.org/wiki/Chunked_transfer_encoding

here’s an example where Chunked is being sent to HTTP1.0 clients and causing trouble: https://github.com/linkerd/linkerd/issues/1847

I’m getting closer… I used the tip about trapping network packets on my Mac. The “send” operation looks fine…but I really don’t see anything returned from Apache. I built a very small test app aside from a button and a textbox on a window…this is all the code.

Dim myhttp As New HTTPSocket
Dim authserviceUrl as String
Dim runresult as String

authserviceUrl = “http://123.456.789.123/cgi-bin/wcps.account.list.cgi
runresult = myhttp.Post(authserviceUrl,10)
TextArea1.Text = runresult + " ERRORCODE:" + str(myhttp.ErrorCode)

It works perfectly with my old Apache 2.21 running on the server. Not so much on Apache 2.41 – I’m sure it’s one of the myriad of options for handling CGI. I don’t think it’s chunking because the my Curl test call with current options doesn’t return with chunking enabled. It’s something about CGI handling. I wanted to test updating my sample code to use HTTP1.1 via Xojo.Net.HttpSocket. I know that a page return is done via events (runs asynchronously). So I’m trying to modify the above code to work

myhttp is a generic object dragged from the controls and modified with a superclass of Xojo.Net.HttpSocket

Dim authserviceUrl as String
authserviceUrl = “http://139.126.108.157/cgi-bin/wcps.account.list.cgi
myhttp.Send(“POST”, authserviceUrl)

I updated the PageReceived handler to simply display the error code

TextArea1.Text = " ERRORCODE:" + str(HTTPStatus)

I know I’d have to do a little more to get a STRING out of the Xojo.Core.memoryblock. I’m missing something as it won’t compile. I do really like the asynchronous design, but have to admit that in this instance…there’s nothing wrong with waiting on a synchronous event. The timeout is a nice feature.

Okay I thought you are communicating with a stand alone webserver behind an Apache just acting as Reverse Proxy. If you are using CGIs then this is somehting different. If your attempts fail, then I would suggest to use a stand alone webserver rather than a .CGI

There were a lot of changes to cgi and authentication between 2.2 and 2.4

What I have posted below is from a working server and should be enough for a simple functional test. You will need to substitute /home/${VHOST}/cgi-bin with the path to your own cgi script folder.

Beyond that, Upgrading to 2.4 from 2.2 - Apache HTTP Server Version 2.5

Sorry, I don’t have any examples that use POST.

# Apache 2.4.6 httpd.conf extract

        #set cgi folder, params fakename "real path"
        ScriptAlias /cgi-bin/ "/home/${VHOST}/cgi-bin/"

        <Directory "/home/${VHOST}/cgi-bin">
                DirectoryIndex index.cgi
                AllowOverride None
                Options None
                Require all granted
        </Directory>
#!/usr/bin/perl
# index.cgi
print "content-type: text/html\
\
";
print "<html><body>\
";
print "<p1>cgi-bin is configured</p>\
";
print "Time at server: ";
system "date\
";
print "</body></html>\
";
// XOJO 2019r2.1 Web Edition
Dim myHttp as new HTTPSocket
Dim URL As string = "http://server.invalid/cgi-bin/index.cgi"
Dim result As String

result = myHttp.Get(URL, 10)
TextArea1.Text = result

I thought I’d let everyone know I did isolate the problem…I still don’t know why it’s a problem…but here it is…
For testing I built a very simple script that doesn’t even take any parameters. Something like this.

#!/usr/bin/perl
print "content-type: text/html

";
$reply = pwd;
print "The working directory is $reply ";

I found that the above FAILS – however…IF I perform the command before I print the html header… it works. like this (below)

#!/usr/bin/perl
$reply = pwd;
print "content-type: text/html

";
print "The working directory is $reply ";

This wasn’t an issue under my older Apache instance… but my new Apache instance doesn’t like it at all.
Perhaps because it doesn’t have the expected html and body elements. This the “working” example doesn’t have them either…and it works just fine under my new Apache instance.

Any effort to “shell-out a command” causes a failure IF I’ve already started printing the page content back. I’ve not seen any difference with chunking settings etc. I’ve tried forcing an html 1.0 response and verified the setting works…but made no difference.

A sincere thank you to everyone who contributed their thoughts and ideas. It put me on the path to a solution.

thank you for updating this thread. after reading your .cgi perl experiments I strongly advice not to use these .CGIs anymore and better switch to xojo webapps as stand alone web services behind an apache reverse proxy for security reasons. Otherwise any tampered parameter will be interpreted and run against your system e.g. http://sensitive/something?dir=%3Bcat%20/etc/passwd

Sounds like good advice Jacob, not sure I understand completely. The Xojo app itself is running as standalone, not as CGI. I’ve been passing parameters as Form Parameters or as JSON (not as URL parameters) – still since they are not being sent via HTTPS – I suppose they can be intercepted and altered. Someone could provide malformed parameters such that shelling out could cause some mayhem. Typically I encode the parameters in the script before shelling out with them…and then decode them in the shelled out command. Also, this Xojo program and associated CGI script is only used internally. The server etc is not available via the internet etc. The authentication is more about convenience for the user having their jobs stamped with their username…and alerts going to their email address (retrieved via their user credentials).

Robert, that is truly bizarre. Are you sure the two cgi files are otherwise identical? (e.g. both have 755 permissions, no invisible unicode characters in the files, etc.)

I wonder if it could be https://httpd.apache.org/docs/trunk/mod/mod_cgid.html#cgidscripttimeout that is misconfigured?

  • in the first case, the content-type header is output, and Apache starts the timer. Then the cgi script has to fork to output the pwd command, and since this takes a non-zero amount of time, mod_cgi assumes the process has died.
  • in the second case, the pwd command runs first, and so the output lines are all generated at once, so mod_cgi doesn’t think your process is dead?

Edit to add: and perhaps there’s an interaction with Connection: keep-alive that is not being sent by Xojo but is being sent by other test apps?

Of course is your Apache talking https with valid certs (e.g. lets encrypt) to your visitors
Only the reverse side of the Apache and your Xojo Webservices are internally talking unencrypted via http.

Apache really doesn’t care about HTML tags.

Apache output is heavily bufferred and similar to PHP, the recommended approach is to assemble the response and write to the buffer in one shot. Apache can be fussy about end of line delimiters too. The last two characters in the response buffer should be an LF/CR pair.

# try changing this
print "The working directory is $reply ";

# to this
print "The working directory is $reply\
"';

My actual test is just a single script with the same $reply=pwd; occurring both before and after the printing of the “Content-type…” line. I just toggle off/on the line I want. I checked for hidden characters. None found. I actually was using a newline
terminator (I just failed to copy that in my example here) – For fun I tried removing it…and it makes no real difference. I just get an extra linefeed at the end of my returned page when I add that. I also checked permission and ownership of the file. No problem there. I added the CGIDScriptTimeout option to the mod_cgid configurations. No difference there. It is very strange. I tried not even outputting the captured reply and it doesn’t work either. It seems that IF I perform a external call out …it has to be prior to the output of Page. Even something as “instant” as pwd or and echo command. I wonder if my Apache used mod_cgi and my new one uses mod_cgid — maybe there is a difference in there. I’ve figured out how to work around the problem, but still don’t know why I have a problem. It is curious, but may have to be filed under my “unknown mysteries of the universe”.

@Robert Bednar I think I may have isolated your problem but lack the time to research a resolution.

Below are a couple of dumps from Wireshark. Apache sends the response in both cases but when pwd is called within the response Apache drops the content-length header. There may be a .htaccess tweak to force the header but I don’t have time to dig into the Apache documentation at the moment.

The relevant section of the protocol spec is here
https://www.w3.org/Protocols/HTTP/1.0/spec.html#Content-Length

Use of the word ‘should’ in a protocol spec usally means ‘optional’ in the wild.

# pwd called within response - no output from Xojo
00000000  47 45 54 20 2f 63 67 69  2d 62 69 6e 2f 74 65 73   GET /cgi -bin/tes
00000010  74 31 2e 63 67 69 20 48  54 54 50 2f 31 2e 30 0d   t1.cgi H TTP/1.0.
00000020  0a 41 63 63 65 70 74 3a  20 2a 2f 2a 0d 0a 41 63   .Accept:  */*..Ac
00000030  63 65 70 74 2d 4c 61 6e  67 75 61 67 65 3a 20 65   cept-Lan guage: e
00000040  6e 0d 0a 48 6f 73 74 3a  20 xx xx xx xx xx xx xx    n..Host:  xxxxxxx
00000050  xx xx xx xx xx xx xx xx  xx xx xx 0d 0a 0d 0a      xxxxxxxx xxx....
    00000000  48 54 54 50 2f 31 2e 31  20 32 30 30 20 4f 4b 0d   HTTP/1.1  200 OK.
    00000010  0a 44 61 74 65 3a 20 57  65 64 2c 20 31 35 20 4a   .Date: W ed, 15 J
    00000020  61 6e 20 32 30 32 30 20  30 38 3a 34 38 3a 30 32   an 2020  08:48:02
    00000030  20 47 4d 54 0d 0a 53 65  72 76 65 72 3a 20 41 70    GMT..Se rver: Ap
    00000040  61 63 68 65 2f 32 2e 34  2e 36 0d 0a 43 6f 6e 6e   ache/2.4 .6..Conn
    00000050  65 63 74 69 6f 6e 3a 20  63 6c 6f 73 65 0d 0a 43   ection:  close..C
    00000060  6f 6e 74 65 6e 74 2d 54  79 70 65 3a 20 74 65 78   ontent-T ype: tex
    00000070  74 2f 68 74 6d 6c 3b 20  63 68 61 72 73 65 74 3d   t/html;  charset=
    00000080  55 54 46 2d 38 0d 0a 0d  0a                        UTF-8... .
    00000089  54 68 65 20 77 6f 72 6b  69 6e 67 20 64 69 72 65   The work ing dire
    00000099  63 74 6f 72 79 20 69 73  20 xx xx xx xx xx xx xx   ctory is  xxxxxxx
    000000A9  xx xx xx xx xx xx 2f 63  67 69 2d 62 69 6e 0a 20   xxxxxx/c gi-bin. 


# pwd called before response - Xojo processes response
00000000  47 45 54 20 2f 63 67 69  2d 62 69 6e 2f 74 65 73   GET /cgi -bin/tes
00000010  74 31 2e 63 67 69 20 48  54 54 50 2f 31 2e 30 0d   t1.cgi H TTP/1.0.
00000020  0a 41 63 63 65 70 74 3a  20 2a 2f 2a 0d 0a 41 63   .Accept:  */*..Ac
00000030  63 65 70 74 2d 4c 61 6e  67 75 61 67 65 3a 20 65   cept-Lan guage: e
00000040  6e 0d 0a 48 6f 73 74 3a  20 xx xx xx xx xx xx xx  n..Host:  xxxxxxx
00000050  xx xx xx xx xx xx xx xx  xx xx xx 0d 0a 0d 0a      xxxxxxxx xxx....
    00000000  48 54 54 50 2f 31 2e 31  20 32 30 30 20 4f 4b 0d   HTTP/1.1  200 OK.
    00000010  0a 44 61 74 65 3a 20 57  65 64 2c 20 31 35 20 4a   .Date: W ed, 15 J
    00000020  61 6e 20 32 30 32 30 20  31 37 3a 31 34 3a 30 36   an 2020  17:14:06
    00000030  20 47 4d 54 0d 0a 53 65  72 76 65 72 3a 20 41 70    GMT..Se rver: Ap
    00000040  61 63 68 65 2f 32 2e 34  2e 36 0d 0a 43 6f 6e 74   ache/2.4 .6..[b]Cont
    00000050  65 6e 74 2d 4c 65 6e 67  74 68 3a 20 34 38 0d 0a   ent-Leng th: 48..[/b]
    00000060  43 6f 6e 6e 65 63 74 69  6f 6e 3a 20 63 6c 6f 73   Connecti on: clos
    00000070  65 0d 0a 43 6f 6e 74 65  6e 74 2d 54 79 70 65 3a   e..Conte nt-Type:
    00000080  20 74 65 78 74 2f 68 74  6d 6c 3b 20 63 68 61 72    text/ht ml; char
    00000090  73 65 74 3d 55 54 46 2d  38 0d 0a 0d 0a 54 68 65   set=UTF- 8....The
    000000A0  20 77 6f 72 6b 69 6e 67  20 64 69 72 65 63 74 6f    working  directo
    000000B0  72 79 20 69 73 20 2f xx  xx xx xx xx xx xx xx xx   ry is /x xxxxxxxx
    000000C0  xx xx xx 2f 63 67 69 2d  62 69 6e 0a 20            xxx/cgi- bin. 

Good Job isolating the problem Mathew. This makes sense and explains why Xojo is having such a tough go in HTTP1.0 If the Content-Len isn’t being returned – that explains why I was getting the failure. I probably should switch over all my service calls to HTTP 1.1 — I had good luck with that in a test application. Wiresharking the packets to identify this issue is above and beyond any effort I expected from the community. I think you have exactly pinpointed the root cause of my trouble…and thankfully I have a simple enough workaround. Thanks again to the rest of the Xojo community. Sharing your ideas and helping troubleshoot is so helpful.