1<?php 2 3function http_server_skipif($socket_string) { 4 5 if (!function_exists('pcntl_fork')) die('skip pcntl_fork() not available'); 6 if (!function_exists('posix_kill')) die('skip posix_kill() not available'); 7 if (!stream_socket_server($socket_string)) die('skip stream_socket_server() failed'); 8} 9 10/* Minimal HTTP server with predefined responses. 11 * 12 * $socket_string is the socket to create and listen on (e.g. tcp://127.0.0.1:1234) 13 * $files is an array of files containing N responses for N expected requests. Server dies after N requests. 14 * $output is a stream on which everything sent by clients is written to 15 */ 16function http_server($socket_string, array $files, &$output = null) { 17 18 pcntl_alarm(60); 19 20 $server = stream_socket_server($socket_string, $errno, $errstr); 21 if (!$server) { 22 return false; 23 } 24 25 if ($output === null) { 26 $output = tmpfile(); 27 if ($output === false) { 28 return false; 29 } 30 } 31 32 $pid = pcntl_fork(); 33 if ($pid == -1) { 34 die('could not fork'); 35 } else if ($pid) { 36 return $pid; 37 } 38 39 foreach($files as $file) { 40 41 $sock = stream_socket_accept($server); 42 if (!$sock) { 43 exit(1); 44 } 45 46 // read headers 47 48 $content_length = 0; 49 50 stream_set_blocking($sock, 0); 51 while (!feof($sock)) { 52 53 list($r, $w, $e) = array(array($sock), null, null); 54 if (!stream_select($r, $w, $e, 1)) continue; 55 56 $line = stream_get_line($sock, 8192, "\r\n"); 57 if ($line === b'') { 58 fwrite($output, b"\r\n"); 59 break; 60 } else if ($line !== false) { 61 fwrite($output, b"$line\r\n"); 62 63 if (preg_match(b'#^Content-Length\s*:\s*([[:digit:]]+)\s*$#i', $line, $matches)) { 64 $content_length = (int) $matches[1]; 65 } 66 } 67 } 68 stream_set_blocking($sock, 1); 69 70 // read content 71 72 if ($content_length > 0) { 73 stream_copy_to_stream($sock, $output, $content_length); 74 } 75 76 // send response 77 78 $fd = fopen($file, 'rb'); 79 stream_copy_to_stream($fd, $sock); 80 81 fclose($sock); 82 } 83 84 exit(0); 85} 86 87function http_server_kill($pid) { 88 posix_kill($pid, SIGTERM); 89 pcntl_waitpid($pid, $status); 90} 91 92?> 93