You need to include a valid CGI header response, not an HTTP response, if calling a script via CGI through Apache. I think in essence (detail below) you need to remove "Status: 200 OK" from your file, and it might work.
There is a good article by Apache themselves (https://httpd.apache.org/docs/2.2/howto/cgi.html) which shows you the minimum to achive a valid response.
An example header received by the client might be as follows:
HTTP/1.x 200 OK
Transfer-Encoding: chunked
Date: Tue, 06 Dec 2021 19:58:00 GMT
Server: My_Bash_Script
Connection: close
X-Powered-By: My_Bash_Script
Pragma: public
Expires: Tue, 06 Dec 2021 20:58:00 GMT
Cache-Control: max-age=3600, public
Last-Modified: Tue, 06 Dec 2021 20:58:00 GMT
Content-Encoding: gzip
Vary: Accept-Encoding, Cookie, User-Agent
Content-Type: text/html; charset=UTF-8
<!DOCTYPE html>
<head><title>Under construction</title>
<body><p>Under construction.</p></body>
</html>
But your CGI, only needs to send from "Content-Type: text/html; charset=UTF-8" down.
A rather good article can be found here explaining the headers:
https://code.tutsplus.com/tutorials/http-headers-for-dummies--net-8039
With regards to a served PHP file via Apache, there are several layers of communication:
- A request is made of Apache on a TCP port. This includes a request header if via HTTP.
- Apache runs any rules (e.g. mod_rewrite) and handles any SSL connections / handshakes required.
- Apache then detects the file extension as PHP and calls the PHP script through the PHP interpreter.
- The PHP code is interpreted, and turned into a static string (hopefully :-) which is returned to Apache and contains the HTML code.
- Apache then adds the header information to the HTML page, along with any other outbound processing.
- This is serialised and piped back over the TCP connection to the client.
Another good way to explore the headers is to use Firefox / Chrome Developer Tools (pressing F12 in Firefox opens them). Goto the Network Tab once Developer Tools are open and reload the page (Ctrl + R on Windows/Linux). There is a "Raw" option where you can see the exact data that was send and received.
Finally, if you find a website, or even that your CGI is being served over http rather than https, you can install Wireshark (https://www.wireshark.org) and easily monitor the traffic conversations to learn the differential between what you are sending that is being misunderstood and what a normal static html page conversatin looks like served by Apache.
P.S. (In 2022,) If you are indeed running Apache 2.2: