El script 1 a continuación es bash y está en https://example.com/cgi-bin/test
. Produce el resultado 'En construcción' cuando se recupera. Tiene ecos Status
y Content-type
encabezados, y algo de HTML. Si, en cambio, intento hacer eco de un documento HTML completo, Apache simplemente se queja de un encabezado no válido.
El script 2 a continuación es php y está en https://example.com/cgi-bin/test2.php
. A diferencia del script bash, éste devuelve un documento HTML.
¿Cómo es que el script 2 puede enviar un documento HTML completo, pero el script 1 no?
Guión 1
#!/bin/bash
cat <<'EOF'
Status: 200 OK
Content-type: text/html
<p>Under construction.</p>
EOF
Guión 2
<?php
print <<<EOF
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
...etc
</head>
<body>
...etc
</body>
</html>
EOF;
?>
EDITAR
php
Viene en 2 versiones: las versiones CLI y CGI. Si simplemente ejecuta el Script 2 desde la línea de comando, php test2.php
entonces elsoloEl resultado producido por php
es exactamente lo que ve: el documento HTML. php-cgi
es la versión CGI (instalar en Ubuntu/Deb como apt install php-cgi
). Apache (efectivamente) ejecuta la versión CGI (en la vida real, lo hace de manera ligeramente diferente, pero con los mismos resultados):
$ php-cgi test2.php
Content-type: text/html; charset=UTF-8
<!DOCTYPE html>
...rest of doc
Los scripts CGI deben regresar al menos Content-type
a Apache (pero pueden devolver más encabezados, incluido Status
). Entonces la respuesta es queambosLos scripts funcionan porque el script 1 devuelve explícitamente Content-type
, mientras que la versión CGI interna de php
hace lo mismo.
El script bash puede devolver el documento HTML completo, siempre que también devuelva el archivo Content-type
.
Respuesta1
En CGI necesitas enviar el tipo de contenido. PHP lo genera por ti. (verifique el resultado a través de un navegador, lo verá incluso si no lo ve en su código.
Tengo un CGI que hice en C y realmente necesitas el tipo de contenido;
En mi caso por ejemplo;
printf("Tipo de contenido: texto/html;charset=us-ascii\n\n");
Si necesita cambiar el encabezado en php, debe llamar al encabezado al comienzo de su secuencia de comandos.
es decir;
header('Tipo de contenido: aplicación/json');
Respuesta2
PHP y CGI son dos cosas diferentes en este contexto.
CGI es una interfaz entre un programa (en este caso un script bash) y el servidor web. Esta interfaz especifica la comunicación entre el servidor web y el programa.
Este estándar requiere que el programa devuelvatodoencabezados, incluidos los encabezados de estado, antes del contenido real. En HTTP, los encabezados y el cuerpo están separados por una sola línea; de ahí el formato en el que tiene
Header
Header
Content
Después de los encabezados, puedes incluir un documento HTML completo o cualquier otro tipo de datos que coincidan con los encabezados que envías.
PHP hace algunas suposiciones por usted y, a menos que las anule, establece el tipo de contenido, el código de estado, etc., automáticamente.
Respuesta3
Debe incluir una respuesta de encabezado CGI válida, no una respuesta HTTP, si llama a un script mediante CGI a través de Apache. Creo que, en esencia (detallado a continuación), debes eliminar "Estado: 200 OK" de tu archivo y podría funcionar.
Hay un buen artículo escrito por los propios Apache (https://httpd.apache.org/docs/2.2/howto/cgi.html) que le muestra el mínimo para lograr una respuesta válida.
Un encabezado de ejemplo recibido por el cliente podría ser el siguiente:
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>
Pero su CGI solo necesita enviarse desde "Tipo de contenido: texto/html; charset=UTF-8" hacia abajo.
Puede encontrar un artículo bastante bueno aquí que explica los encabezados: https://code.tutsplus.com/tutorials/http-headers-for-dummies--net-8039
Con respecto a un archivo PHP servido a través de Apache, existen varias capas de comunicación:
- Se realiza una solicitud a Apache en un puerto TCP. Esto incluye un encabezado de solicitud si se realiza a través de HTTP.
- Apache ejecuta todas las reglas (por ejemplo, mod_rewrite) y maneja las conexiones/apretones de manos SSL necesarios.
- Luego, Apache detecta la extensión del archivo como PHP y llama al script PHP a través del intérprete PHP.
- El código PHP se interpreta y se convierte en una cadena estática (con suerte :-) que se devuelve a Apache y contiene el código HTML.
- Luego, Apache agrega la información del encabezado a la página HTML, junto con cualquier otro procesamiento saliente.
- Esto se serializa y se canaliza de regreso a través de la conexión TCP al cliente.
Otra buena forma de explorar los encabezados es utilizar las herramientas de desarrollo de Firefox/Chrome (al presionar F12 en Firefox se abren). Vaya a la pestaña Red una vez que las Herramientas de desarrollo estén abiertas y vuelva a cargar la página (Ctrl + R en Windows/Linux). Hay una opción "Sin procesar" donde puede ver los datos exactos que se enviaron y recibieron.
Finalmente, si encuentra un sitio web, o incluso si su CGI se sirve a través de http en lugar de https, puede instalar Wireshark (https://www.wireshark.org) y monitoree fácilmente las conversaciones de tráfico para conocer la diferencia entre lo que envía y que no se entiende bien y cómo se ve una conversación normal en una página HTML estática servida por Apache.
PD (en 2022) Si realmente está ejecutando Apache 2.2:
- Quizás te estés perdiendo otras características de Apache2.4 que pueden ayudarte a llegar a donde deseas un poco más rápido:https://httpd.apache.org/docs/2.4/new_features_2_4.html
- Y tenga en cuenta que Apache 2.2 está en EOL (desde 2017) y contiene una serie de vulnerabilidades:https://httpd.apache.org/security/vulnerabilities_22.html