#!/opt/bin/php -c/opt/php.ini 'Continue',101=>'Switching Protocols',102=>'Processing',200=>'OK',201=>'Created',202=>'Accepted',203=>'Non-Authoritative Information',204=>'No Content',205=>'Reset Content',206=>'Partial Content',207=>'Multi-Status',208=>'Already Reported',226=>'IM Used',300=>'Multiple Choices',301=>'Moved Permanently',302=>'Found',303=>'See Other',304=>'Not Modified',305=>'Use Proxy',306=>'Switch Proxy',307=>'Temporary Redirect',308=>'Permanent Redirect',400=>'Bad Request',401=>'Unauthorized',402=>'Payment Required',403=>'Forbidden',404=>'Not Found',405=>'Method Not Allowed',406=>'Not Acceptable',407=>'Proxy Authentication Required',408=>'Request Timeout',409=>'Conflict',410=>'Gone',411=>'Length Required',412=>'Precondition Failed',413=>'Request Entity Too Large',414=>'Request-URI Too Long',415=>'Unsupported Media Type',416=>'Requested Range Not Satisfiable',417=>'Expectation Failed',418=>'I\'m a teapot',419=>'Authentication Timeout',420=>'Enhance Your Calm',420=>'Method Failure',422=>'Unprocessable Entity',423=>'Locked',424=>'Failed Dependency',424=>'Method Failure',425=>'Unordered Collection',426=>'Upgrade Required',428=>'Precondition Required',429=>'Too Many Requests',431=>'Request Header Fields Too Large',444=>'No Response',449=>'Retry With',450=>'Blocked by Windows Parental Controls',451=>'Redirect',451=>'Unavailable For Legal Reasons',494=>'Request Header Too Large',495=>'Cert Error',496=>'No Cert',497=>'HTTP to HTTPS',499=>'Client Closed Request',500=>'Internal Server Error',501=>'Not Implemented',502=>'Bad Gateway',503=>'Service Unavailable',504=>'Gateway Timeout',505=>'HTTP Version Not Supported',506=>'Variant Also Negotiates',507=>'Insufficient Storage',508=>'Loop Detected',509=>'Bandwidth Limit Exceeded',510=>'Not Extended',511=>'Network Authentication Required',598=>'Network read timeout error',599=>'Network connect timeout error']; function start_webserver() { $SERVER_STARTUP_TIMEOUT = 1000000; // 1 second $pid = pcntl_fork(); switch($pid) { case -1: die("Failed to fork webserver process\n"); case 0: // exec the command $HANDLER = getenv('_HANDLER'); $phpMinorVersion = PHP_MINOR_VERSION; $handler_components = explode('/', $HANDLER); $handler_filename = array_pop($handler_components); $handler_path = implode('/', array_merge(['/var/task'], $handler_components)); chdir($handler_path); exec("PHP_INI_SCAN_DIR=/opt/etc/php-7.${phpMinorVersion}.d/:/var/task/php-7.${phpMinorVersion}.d/ php -S localhost:8000 -c /var/task/php.ini -d extension_dir=/opt/lib/php/7.${phpMinorVersion}/modules '$handler_filename'"); exit; default: // Wait for child server to start $start = microtime(true); do { if (microtime(true) - $start > $SERVER_STARTUP_TIMEOUT) { die("Webserver failed to start within one second\n"); } usleep(1000); $fp = @fsockopen('localhost', 8000, $errno, $errstr, 1); } while ($fp == false); fclose($fp); } } function fail($AWS_LAMBDA_RUNTIME_API, $invocation_id, $message) { $ch = curl_init("http://$AWS_LAMBDA_RUNTIME_API/2018-06-01/runtime/invocation/$invocation_id/response"); $response = array(); $response['statusCode'] = 500; $response['body'] = $message; $response_json = json_encode($response); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); curl_setopt($ch, CURLOPT_POSTFIELDS, $response_json); curl_setopt($ch, CURLOPT_HTTPHEADER, array( 'Content-Type: application/json', 'Content-Length: ' . strlen($response_json) )); curl_exec($ch); curl_close($ch); } start_webserver(); while (true) { $ch = curl_init("http://$AWS_LAMBDA_RUNTIME_API/2018-06-01/runtime/invocation/next"); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE); curl_setopt($ch, CURLOPT_FAILONERROR, TRUE); $invocation_id = ''; curl_setopt($ch, CURLOPT_HEADERFUNCTION, function ($ch, $header) use (&$invocation_id) { if (!preg_match('/:\s*/', $header)) { return strlen($header); } [$name, $value] = preg_split('/:\s*/', $header, 2); if (strtolower($name) == 'lambda-runtime-aws-request-id') { $invocation_id = trim($value); } return strlen($header); }); $body = ''; curl_setopt($ch, CURLOPT_WRITEFUNCTION, function ($ch, $chunk) use (&$body) { $body .= $chunk; return strlen($chunk); }); curl_exec($ch); if (curl_error($ch)) { die('Failed to fetch next Lambda invocation: ' . curl_error($ch) . "\n"); } if ($invocation_id == '') { die("Failed to determine Lambda invocation ID\n"); } curl_close($ch); if (!$body) { die("Empty Lambda invocation response\n"); } $event = json_decode($body, TRUE); if (!array_key_exists('requestContext', $event)) { fail($AWS_LAMBDA_RUNTIME_API, $invocation_id, 'Event is not an API Gateway request'); continue; } $uri = $event['path']; if (array_key_exists('multiValueQueryStringParameters', $event) && $event['multiValueQueryStringParameters']) { $first = TRUE; foreach ($event['multiValueQueryStringParameters'] as $name => $values) { foreach ($values as $value) { if ($first) { $uri .= "?"; $first = FALSE; } else { $uri .= "&"; } $uri .= $name; if ($value != '') { $uri .= '=' . $value; } } } } $ch = curl_init("http://localhost:8000$uri"); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, FALSE); if (array_key_exists('multiValueHeaders', $event)) { $headers = array(); foreach ($event['multiValueHeaders'] as $name => $values) { foreach ($values as $value) { array_push($headers, "${name}: ${value}"); } } curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); } curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $event['httpMethod']); if (array_key_exists('body', $event)) { $body = $event['body']; if (array_key_exists('isBase64Encoded', $event) && $event['isBase64Encoded']) { $body = base64_decode($body); } } else { $body = ''; } if (strlen($body) > 0) { curl_setopt($ch, CURLOPT_POSTFIELDS, $body); } $response = array(); $response['multiValueHeaders'] = array(); $response['body'] = ''; curl_setopt($ch, CURLOPT_HEADERFUNCTION, function ($ch, $header) use (&$response) { if (preg_match('/HTTP\/1.1 (\d+) .*/', $header, $matches)) { $response['statusCode'] = intval($matches[1]); return strlen($header); } if (!preg_match('/:\s*/', $header)) { return strlen($header); } [$name, $value] = preg_split('/:\s*/', $header, 2); $name = trim($name); $value = trim($value); if ($name == '') { return strlen($header); } if (!array_key_exists($name, $response['multiValueHeaders'])) { $response['multiValueHeaders'][$name] = array(); } array_push($response['multiValueHeaders'][$name], $value); return strlen($header); }); curl_setopt($ch, CURLOPT_WRITEFUNCTION, function ($ch, $chunk) use (&$response) { $response['body'] .= $chunk; return strlen($chunk); }); curl_exec($ch); curl_close($ch); $ch = curl_init("http://$AWS_LAMBDA_RUNTIME_API/2018-06-01/runtime/invocation/$invocation_id/response"); $isALB = array_key_exists("elb", $event['requestContext']); if ($isALB) { // Add Headers For ALB $status = $response["statusCode"]; if (array_key_exists($status, $http_codes)) { $response["statusDescription"] = "$status ". $http_codes[$status]; } else { $response["statusDescription"] = "$status Unknown"; } $response["isBase64Encoded"] = false; } $response_json = json_encode($response); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); curl_setopt($ch, CURLOPT_POSTFIELDS, $response_json); if (!$isALB){ curl_setopt($ch, CURLOPT_HTTPHEADER, array( 'Content-Type: application/json', 'Content-Length: ' . strlen($response_json) )); } curl_exec($ch); curl_close($ch); } ?>