Created
March 4, 2014 08:38
-
-
Save leeight/9342507 to your computer and use it in GitHub Desktop.
edp-webserver-php-handler
This file contains hidden or 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
/*************************************************************************** | |
* | |
* Copyright (c) 2014 Baidu.com, Inc. All Rights Reserved | |
* $Id$ | |
* | |
**************************************************************************/ | |
/** | |
* php.handler.js ~ 2014/02/28 12:07:51 | |
* @author leeight([email protected]) | |
* @version $Revision$ | |
* @description | |
* | |
**/ | |
/** | |
* edp-webserver处理php | |
* | |
* 在`edp-webserver-config.js`中配置: | |
* ```javascript | |
* { | |
* location: /^.*$/, | |
* handler: [ | |
* // 或者直接将php-cgi添加到环境变量中 | |
* php('/usr/local/php/bin/php-cgi') | |
* ] | |
* } | |
* ``` | |
* 调试状态下请打开`php.ini`的`error_reporting`。 | |
* | |
* @param {?string} handler php-cgi可执行文件路径 | |
*/ | |
module.exports = exports = function(handler, suffix, forwardPathName) { | |
return function(context) { | |
var request = context.request; | |
var targetURL = request.url; | |
var targetPathName = request.pathname; | |
// url改换 | |
if (forwardPathName) { | |
targetPathName = forwardPathName(context); | |
if (targetPathName) { | |
targetURL = request.headers.host | |
+ targetPathName + (request.search || ''); | |
console.log( | |
'PHP try forwarding request' + (request.url) | |
+ ' to ' + (targetURL) | |
); | |
} | |
else { | |
targetPathName = request.pathname; | |
} | |
} | |
suffix = suffix || 'php'; | |
if (!/\.php($|\?)/.test(targetURL)) { | |
return; | |
} | |
// 挂起 | |
context.stop(); | |
console.log( | |
'PHP request' + (targetURL) + ' | ' + (targetPathName) | |
); | |
var path = require('path'); | |
var docRoot = context.conf.documentRoot; | |
var request = context.request; | |
var scriptName = targetPathName; | |
var scriptFileName = path.normalize( | |
docRoot + targetPathName | |
); | |
var query = require('url').parse(request.url).query; | |
// @see: http://www.cgi101.com/book/ch3/text.html | |
var host = (request.headers.host || '').split(':'); | |
var env = { | |
PATH: process.env.PATH, | |
GATEWAY_INTERFACE: 'CGI/1.1', | |
SERVER_PROTOCOL: 'HTTP/1.1', | |
SERVER_ROOT: docRoot, | |
DOCUMENT_ROOT: docRoot, | |
SERVER_NAME: host[0], | |
SERVER_PORT: host[1] || 80, | |
REDIRECT_STATUS: 200, | |
SCRIPT_NAME: scriptName, //docroot上的文件 | |
REQUEST_URI: targetURL, | |
SCRIPT_FILENAME: scriptFileName, //物理文件 | |
REQUEST_METHOD: request.method, | |
QUERY_STRING: query || '' | |
}; | |
// expose request headers | |
for (var header in request.headers) { | |
var name = 'HTTP_' + header.toUpperCase().replace(/-/g, '_'); | |
env[name] = request.headers[header]; | |
} | |
if ('content-length' in request.headers) { | |
env.CONTENT_LENGTH = request.headers['content-length']; | |
} | |
if ('content-type' in request.headers) { | |
env.CONTENT_TYPE = request.headers['content-type']; | |
} | |
var child = require('child_process').spawn( | |
handler || 'php-cgi', | |
[], | |
{ | |
env: env | |
} | |
); | |
var bodyBuffer = []; | |
var isBodyData = false; | |
var headers = {}; | |
var line = []; | |
child.on( | |
'exit', | |
done | |
); | |
child.stderr | |
.on( | |
'end', | |
function () { | |
console.log('php error end [' + [].slice.call(arguments) + ']'); | |
} | |
) | |
.on( | |
'data', | |
function () { | |
console.log('php error data [' + [].slice.call(arguments) + ']'); | |
} | |
); | |
child.stdout | |
.on( | |
'end', | |
done | |
) | |
.on( | |
'data', | |
function(buf) { | |
for (var i = 0; i < buf.length; i++) { | |
// 如果是主体数据内容 | |
if (isBodyData) { | |
return bodyBuffer.push(buf); | |
} | |
// 取出header | |
var c = buf[i]; | |
if (c == 0xA) { // 如果是\n,则一行读取完毕 | |
if (!line.length) { // 如果读取到一个空行 | |
isBodyData = true; | |
bodyBuffer.push( | |
buf.slice(i + 1) | |
); | |
return; | |
} | |
var s = line.join(''); | |
line = []; | |
var idx = s.indexOf(':'); | |
headers[s.slice(0, idx)] = s.slice(idx + 1).trim(); | |
} else if (c != 0xD) { //如果不是\n,也不是\r,说明一行还未读取结束 | |
line.push(String.fromCharCode(c)); | |
} | |
} | |
} | |
); | |
// 将php解析后的结果填充到context中 | |
function done(code) { | |
if (code === undefined) { | |
return; | |
} | |
for(var i in headers) { | |
if (headers.hasOwnProperty(i)) { | |
context.header[i] = headers[i]; | |
} | |
} | |
context.content = bodyBuffer.join(''); | |
// 如果code非零,也不一定不能运行 | |
// if (code) { | |
// context.status = 500; | |
// } | |
// 标志php成功返回 | |
context.phpOK = true; | |
context.start(); | |
} | |
}; | |
}; | |
/* vim: set ts=4 sw=4 sts=4 tw=100: */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment