Last active
November 14, 2024 17:49
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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