【发布时间】:2017-08-31 03:25:13
【问题描述】:
我在 AWS Lambda 上托管了我的 Slim 应用程序。为了让我的 PHP 应用程序正常工作,我关注了 this tutorial
在我尝试使用 POST 方法提交表单之前,我的应用程序运行良好。我的 PHP 无法从表单中获取值。当我转储 $_POST 和 file_get_contents('php://input') 时,都返回了 null。
在教程中,Chris(作者)表示,这段代码生成了子进程并设置了一堆环境变量,PHP CGI 将这些环境变量填充到 $_SERVER 超级全局变量中。
var php = spawn('./php-cgi', ['function.php'], {
env: Object.assign({
REDIRECT_STATUS: 200,
REQUEST_METHOD: requestMethod,
SCRIPT_FILENAME: 'function.php',
SCRIPT_NAME: '/function.php',
PATH_INFO: '/',
SERVER_NAME: serverName,
SERVER_PROTOCOL: 'HTTP/1.1',
REQUEST_URI: requestUri
}, headers)
});
我不熟悉子进程,所以我想问一下是否有办法我也可以填充 $_POST 超全局?因为我认为 POST 数据存在于我的处理函数中的 event 对象/变量中,这意味着(我认为)我的 NodeJS 包装器可以访问 POST 数据,但它没有将其传递给 PHP CGI ?
exports.handler = function(event, context)
这是我的 NodeJS 包装器的完整代码:
var spawn = require('child_process').spawn;
var parseHeaders, parseResponse, parseStatusLine;
parseResponse = function(responseString) {
var headerLines, line, lines, parsedStatusLine, response;
response = {};
lines = responseString.split('\r\n');
parsedStatusLine = parseStatusLine(lines.shift());
response['protocolVersion'] = parsedStatusLine['protocol'];
response['statusCode'] = parsedStatusLine['statusCode'];
response['statusMessage'] = parsedStatusLine['statusMessage'];
headerLines = [];
while (lines.length > 0) {
line = lines.shift();
if (line === "") {
break;
}
headerLines.push(line);
}
response['headers'] = parseHeaders(headerLines);
response['body'] = lines.join('\r\n');
return response;
};
parseHeaders = function(headerLines) {
var headers, key, line, parts, _i, _len;
headers = {};
for (_i = 0, _len = headerLines.length; _i < _len; _i++) {
line = headerLines[_i];
parts = line.split(":");
key = parts.shift();
headers[key] = parts.join(":").trim();
}
return headers;
};
parseStatusLine = function(statusLine) {
var parsed, parts;
parts = statusLine.match(/^(.+) ([0-9]{3}) (.*)$/);
parsed = {};
if (parts !== null) {
parsed['protocol'] = parts[1];
parsed['statusCode'] = parts[2];
parsed['statusMessage'] = parts[3];
}
return parsed;
};
exports.index = function(event, context) {
// Sets some sane defaults here so that this function doesn't fail when it's not handling a HTTP request from
// API Gateway.
var requestMethod = event.httpMethod || 'GET';
var serverName = event.headers ? event.headers.Host : '';
var requestUri = event.path || '';
var headers = {};
// Convert all headers passed by API Gateway into the correct format for PHP CGI. This means converting a header
// such as "X-Test" into "HTTP_X-TEST".
if (event.headers) {
Object.keys(event.headers).map(function (key) {
headers['HTTP_' + key.toUpperCase()] = event.headers[key];
});
}
// Spawn the PHP CGI process with a bunch of environment variables that describe the request.
var php = spawn('./php-cgi', ['slim/public/index.php'], {
env: Object.assign({
REDIRECT_STATUS: 200,
REQUEST_METHOD: requestMethod,
SCRIPT_FILENAME: 'slim/public/index.php',
SCRIPT_NAME: '/index.php',
PATH_INFO: '/',
SERVER_NAME: serverName,
SERVER_PROTOCOL: 'HTTP/1.1',
REQUEST_URI: requestUri
}, headers)
});
// Listen for output on stdout, this is the HTTP response.
var response = '';
php.stdout.on('data', function(data) {
response += data.toString('utf-8');
});
// When the process exists, we should have a complete HTTP response to send back to API Gateway.
php.on('close', function(code) {
// Parses a raw HTTP response into an object that we can manipulate into the required format.
var parsedResponse = parseResponse(response);
// Signals the end of the Lambda function, and passes the provided object back to API Gateway.
context.succeed({
statusCode: parsedResponse.statusCode || 200,
headers: parsedResponse.headers,
body: parsedResponse.body
});
});
};
【问题讨论】:
-
var_dump(file_get_contents('php://input'));怎么样? -
我也试过了。我忘了在我的问题中包括这个。它还返回了一个空值。
-
尝试将变量作为查询字符串传递?
function.php?x=y -
@OzgurGUL 我认为使用密码不安全?但我可能已经找到了解决方案。我填充了 $_SERVER 超全局元素。 QUERY_STRING 元素。我在那里分配了 event.body 以便我可以访问后端中的值。但我不知道它是否安全或有效。
标签: php node.js amazon-web-services http-post child-process