Das folgende Skript 1 ist ein Bash-Skript und befindet sich bei https://example.com/cgi-bin/test
. Es erzeugt die Ausgabe „In Bearbeitung“, wenn es abgerufen wird. Es gibt Status
Header Content-type
und etwas HTML aus. Wenn ich stattdessen versuche, ein ganzes HTML-Dokument auszugeben, beschwert sich Apache nur über einen ungültigen Header.
Das folgende Skript 2 ist PHP und befindet sich unter https://example.com/cgi-bin/test2.php
. Anders als das Bash-Skript gibt dieses ein HTML-Dokument zurück.
Wie kann es sein, dass Skript 2 ein vollständiges HTML-Dokument senden kann, Skript 1 jedoch nicht?
Skript 1
#!/bin/bash
cat <<'EOF'
Status: 200 OK
Content-type: text/html
<p>Under construction.</p>
EOF
Skript 2
<?php
print <<<EOF
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
...etc
</head>
<body>
...etc
</body>
</html>
EOF;
?>
BEARBEITEN
php
gibt es in 2 Varianten: die CLI- und CGI-Versionen. Wenn Sie Skript 2 einfach von der Kommandozeile aus ausführen, php test2.php
dannnurDie von erzeugte Ausgabe php
ist genau das, was Sie sehen: das HTML-Dokument php-cgi
ist die CGI-Version (unter Ubuntu/Deb installieren als apt install php-cgi
). Apache führt (tatsächlich) die CGI-Version aus (in Wirklichkeit macht es das etwas anders, aber mit den gleichen Ergebnissen):
$ php-cgi test2.php
Content-type: text/html; charset=UTF-8
<!DOCTYPE html>
...rest of doc
CGI-Skripte müssen mindestens Content-type
zu Apache zurückkehren (können aber weitere Header zurückgeben, einschließlich Status
). Die Antwort lautet also:beideSkripte funktionieren, weil Skript 1 explizit zurückgibt Content-type
, während die verborgene CGI-Version von dasselbe php
tut.
Das Bash-Skript kann das gesamte HTML-Dokument zurückgeben, solange es auch das zurückgibt Content-type
.
Antwort1
In CGI müssen Sie den Inhaltstyp senden. PHP generiert ihn für Sie. (Überprüfen Sie die Ausgabe in einem Browser. Sie werden sie sehen, auch wenn sie in Ihrem Code nicht zu sehen ist.
Ich habe ein CGI, das ich in C erstellt habe, und Sie benötigen wirklich den Inhaltstyp;
In meinem Fall zum Beispiel;
printf("Inhaltstyp: text/html;Zeichensatz=us-ascii\n\n");
Wenn Sie den Header in PHP ändern müssen, müssen Sie den Header am Anfang Ihres Skripts aufrufen.
dh;
Header('Inhaltstyp: application/json');
Antwort2
PHP und CGI sind in diesem Zusammenhang zwei verschiedene Dinge.
CGI ist eine Schnittstelle zwischen einem Programm (in diesem Fall einem Bash-Skript) und dem Webserver. Diese Schnittstelle spezifiziert die Kommunikation zwischen dem Webserver und dem Programm.
Dieser Standard erfordert, dass das Programm zurückgibtalleHeader, einschließlich Statusheader, vor dem eigentlichen Inhalt. In HTTP werden Header und Body durch eine einzelne Zeile getrennt - daher das Format, in dem Sie
Header
Header
Content
Nach den Headern können Sie ein vollständiges HTML-Dokument oder beliebige andere Daten einfügen, die zu den von Ihnen gesendeten Headern passen.
PHP trifft einige Annahmen für Sie und legt Inhaltstyp, Statuscode usw. automatisch fest, sofern Sie diese nicht überschreiben.
Antwort3
Sie müssen eine gültige CGI-Header-Antwort einschließen, keine HTTP-Antwort, wenn Sie ein Skript über CGI über Apache aufrufen. Ich denke, im Wesentlichen (Details unten) müssen Sie „Status: 200 OK“ aus Ihrer Datei entfernen, und dann könnte es funktionieren.
Es gibt einen guten Artikel von Apache selbst (https://httpd.apache.org/docs/2.2/howto/cgi.html), das Ihnen das Minimum zum Erreichen einer gültigen Antwort anzeigt.
Ein Beispiel für einen vom Client empfangenen Header könnte wie folgt aussehen:
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>
Aber Ihr CGI muss nur von „Content-Type: text/html; charset=UTF-8“ nach unten senden.
Hier finden Sie einen recht guten Artikel, der die Header erklärt: https://code.tutsplus.com/tutorials/http-headers-for-dummies--net-8039
In Bezug auf eine über Apache bereitgestellte PHP-Datei gibt es mehrere Kommunikationsebenen:
- Über einen TCP-Port wird eine Anfrage an Apache gestellt. Bei HTTP enthält diese einen Anfrageheader.
- Apache führt alle Regeln aus (z. B. mod_rewrite) und verarbeitet alle erforderlichen SSL-Verbindungen/Handshakes.
- Apache erkennt dann die Dateierweiterung als PHP und ruft das PHP-Skript über den PHP-Interpreter auf.
- Der PHP-Code wird interpretiert und in einen statischen String umgewandelt (hoffentlich :-), der an Apache zurückgegeben wird und den HTML-Code enthält.
- Apache fügt dann zusammen mit allen anderen ausgehenden Verarbeitungsvorgängen die Header-Informationen zur HTML-Seite hinzu.
- Dies wird serialisiert und über die TCP-Verbindung an den Client zurückgesendet.
Eine weitere gute Möglichkeit, die Header zu untersuchen, ist die Verwendung der Firefox-/Chrome-Entwicklertools (durch Drücken von F12 in Firefox werden sie geöffnet). Gehen Sie zur Registerkarte „Netzwerk“, sobald die Entwicklertools geöffnet sind, und laden Sie die Seite neu (Strg + R unter Windows/Linux). Es gibt eine „Raw“-Option, mit der Sie die genauen Daten anzeigen können, die gesendet und empfangen wurden.
Wenn Sie feststellen, dass eine Website oder Ihr CGI über http statt über https bereitgestellt wird, können Sie Wireshark installieren (https://www.wireshark.org) und überwachen Sie einfach die Verkehrskonversationen, um den Unterschied zwischen dem, was Sie senden und was missverstanden wird, und dem Aussehen einer normalen statischen HTML-Seitenkonversation, die von Apache bereitgestellt wird, zu erkennen.
PS (im Jahr 2022), wenn Sie tatsächlich Apache 2.2 ausführen:
- Möglicherweise entgehen Ihnen andere Funktionen in Apache 2.4, die Ihnen dabei helfen könnten, Ihr Ziel schneller zu erreichen:https://httpd.apache.org/docs/2.4/new_features_2_4.html
- Und bitte beachten Sie, dass Apache 2.2 EOL ist (seit 2017) und eine Reihe von Schwachstellen enthält:https://httpd.apache.org/security/vulnerabilities_22.html