Skip to content

Instantly share code, notes, and snippets.

@pavel-rossinsky
Last active November 14, 2024 17:49
Show Gist options
  • Save pavel-rossinsky/582465c50e44ee22272d80995b83a680 to your computer and use it in GitHub Desktop.
Save pavel-rossinsky/582465c50e44ee22272d80995b83a680 to your computer and use it in GitHub Desktop.
The PHP script connects to a PHP-FPM service via FastCGI protocol for debugging purposes. It allows you to send a request to PHP-FPM, execute a script, and retrieve the output when other debugging tools are unavailable.
<?php
$url = '/path/to/script.php';
$env = [
'REQUEST_METHOD' => 'GET',
'SCRIPT_FILENAME' => $url,
];
$service_port = 9000;
$address = '127.0.0.1';
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
$result = socket_connect($socket, $address, $service_port);
//OPEN CONNECTION
//request to start a session with php-fpm
//parameters in the following order: version, record type (what this record will do), request id, record body length, data alignment length
socket_write($socket, pack('CCnnCx', 1, 1, 1, 8, 0));
//record body to open the connection
//parameters role, flag controlling connection closure
socket_write($socket, pack('nCxxxxx', 1, 0));
$keyValueFcgiString = '';
foreach ($env as $key => $value) {
//the length of different values is encoded differently
//if less than 128 bytes, it is one byte, if more, then four
$keyLen = strlen($key);
$lenKeyChar = $keyLen < 128 ? chr($keyLen) : pack('N', $keyLen);
$valLen = strlen($value);
$valLenChar = $valLen < 128 ? chr($valLen) : pack('N', $valLen);
$keyValueFcgiString .= $lenKeyChar . $valLenChar . $key . $value;
}
//next record, here we will send to php-fpm the parameters of which environment and which script we want to run
//I will describe the parameters I am passing
//1 - version (old), 4 - record type (new, means passing name-value pairs FCGI_PARAMS), request id (same), record body length (length of my key-value pairs), data alignment length
socket_write($socket, pack('CCnnCx', 1, 4, 1, strlen($keyValueFcgiString), 0));
//send key-value pairs to the server
socket_write($socket, $keyValueFcgiString);
//finish the request
socket_write($socket, pack('CCnnCx', 1, 4, 1, 0, 0));
$buf = '';
$arrData = [];
$len = 8;
while ($len) {
socket_recv($socket, $buf, 1, MSG_WAITALL); //receive data one byte at a time and write them into the array
$arrData[] = $buf;
$len--;
}
//interpret the header according to the 'CCnnCx' format
$protocol = unpack('C', $arrData[0]);
$type = unpack('C', $arrData[1]);
$id = unpack('n', $arrData[2] . $arrData[3]);
$dataLen = unpack('n', $arrData[4] . $arrData[5])[1]; //data length in the response, we need to receive this after the header (unpack returns an array, so we use the index)
$foo = unpack('C', $arrData[6]);
$buf2 = '';
$result = [];
while ($dataLen) {
socket_recv($socket, $buf2, 1, MSG_WAITALL);
$result[] = $buf2;
$dataLen--;
}
var_dump(implode('', $result)); //this will be what the requested script returns
socket_close($socket);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment