Skip to content

Commit

Permalink
Add the ability to execute PHP startup code before each request.
Browse files Browse the repository at this point in the history
  • Loading branch information
cscott committed Nov 3, 2015
1 parent 3ec1589 commit 4f5a23c
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 6 deletions.
1 change: 1 addition & 0 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ var bindingPath =
binary.find(path.resolve(path.join(__dirname, '..', 'package.json')));
var bindings = require(bindingPath);
bindings.setIniPath(path.join(__dirname, 'php.ini'));
bindings.setStartupFile(path.join(__dirname, 'startup.php'));

var packageJson = require('../package.json');
var Promise = require('prfun');
Expand Down
6 changes: 6 additions & 0 deletions lib/startup.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?php
// Startup code for PHP request. This is a good place to implement
// helpers which are easier to write in PHP than in C.
namespace Js;

?>
27 changes: 24 additions & 3 deletions src/node_php_embed.cc
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ using node_php_embed::node_php_jsobject_call_method;

static void node_php_embed_ensure_init(void);

static char *node_php_embed_startup_file;

ZEND_DECLARE_MODULE_GLOBALS(node_php_embed);

/* PHP extension metadata */
Expand Down Expand Up @@ -219,12 +221,23 @@ static void node_php_embed_register_server_variables(

NAN_METHOD(setIniPath) {
TRACE(">");
REQUIRE_ARGUMENT_STRING(0, iniPath);
REQUIRE_ARGUMENT_STRING(0, ini_path);
if (php_embed_module.php_ini_path_override) {
free(php_embed_module.php_ini_path_override);
}
php_embed_module.php_ini_path_override =
(*iniPath) ? strdup(*iniPath) : nullptr;
(*ini_path) ? strdup(*ini_path) : nullptr;
TRACE("<");
}

NAN_METHOD(setStartupFile) {
TRACE(">");
REQUIRE_ARGUMENT_STRING(0, file_name);
if (node_php_embed_startup_file) {
free(node_php_embed_startup_file);
}
node_php_embed_startup_file =
(*file_name) ? strdup(*file_name) : nullptr;
TRACE("<");
}

Expand Down Expand Up @@ -256,7 +269,8 @@ NAN_METHOD(request) {

node_php_embed_ensure_init();
Nan::AsyncQueueWorker(new PhpRequestWorker(callback, source, stream,
args, server_vars, init_func));
args, server_vars, init_func,
node_php_embed_startup_file));
TRACE("<");
}

Expand Down Expand Up @@ -330,6 +344,7 @@ static void node_php_embed_ensure_init(void) {

NAN_MODULE_INIT(ModuleInit) {
TRACE(">");
node_php_embed_startup_file = NULL;
php_embed_module.php_ini_path_override = nullptr;
php_embed_module.php_ini_ignore = true;
php_embed_module.php_ini_ignore_cwd = true;
Expand All @@ -351,6 +366,7 @@ NAN_MODULE_INIT(ModuleInit) {

// Export functions
NAN_EXPORT(target, setIniPath);
NAN_EXPORT(target, setStartupFile);
NAN_EXPORT(target, request);
TRACE("<");
}
Expand All @@ -364,6 +380,11 @@ void ModuleShutdown(void *arg) {
php_embed_shutdown(TSRMLS_C);
if (php_embed_module.php_ini_path_override) {
free(php_embed_module.php_ini_path_override);
php_embed_module.php_ini_path_override = NULL;
}
if (node_php_embed_startup_file) {
free(node_php_embed_startup_file);
node_php_embed_startup_file = NULL;
}
TRACE("<");
}
Expand Down
22 changes: 20 additions & 2 deletions src/phprequestworker.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ extern "C" {
#include "Zend/zend_interfaces.h"
#include "ext/standard/head.h"
#include "ext/standard/info.h"
#include "ext/standard/php_string.h"
}

#include "src/asyncmessageworker.h"
Expand All @@ -27,10 +28,11 @@ PhpRequestWorker::PhpRequestWorker(Nan::Callback *callback,
v8::Local<v8::Object> stream,
v8::Local<v8::Array> args,
v8::Local<v8::Object> server_vars,
v8::Local<v8::Value> init_func)
v8::Local<v8::Value> init_func,
const char *startup_file)
: AsyncMessageWorker(callback), result_(), stream_(), init_func_(),
argc_(args->Length()), argv_(new char*[args->Length()]),
server_vars_() {
server_vars_(), startup_file_(startup_file) {
JsStartupMapper mapper(this);
source_.Set(&mapper, source);
stream_.Set(&mapper, stream);
Expand Down Expand Up @@ -126,6 +128,22 @@ void PhpRequestWorker::Execute(MapperChannel *channel TSRMLS_DC) {
{
ZVal source{ZEND_FILE_LINE_C}, result{ZEND_FILE_LINE_C};
zend_first_try {
// First execute startup code.
if (startup_file_) {
int nlen = 0;
char *f = php_addslashes(const_cast<char*>(startup_file_),
strlen(startup_file_),
&nlen, 0 TSRMLS_CC);
char *buf = new char[11 + nlen];
char startup_msg[] = { "startup" };
nlen = snprintf(buf, 11 + nlen, "require '%s'", f);
zend_eval_stringl_ex(buf, nlen, *result, startup_msg, false
TSRMLS_CC);
result.SetNull();
delete[] buf;
efree(f);
}
// Now execute the user's source.
char eval_msg[] = { "request" }; // This shows up in error messages.
source_.ToPhp(channel, source TSRMLS_CC);
assert(Z_TYPE_P(*source) == IS_STRING);
Expand Down
4 changes: 3 additions & 1 deletion src/phprequestworker.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ class PhpRequestWorker : public AsyncMessageWorker {
PhpRequestWorker(Nan::Callback *callback, v8::Local<v8::String> source,
v8::Local<v8::Object> stream, v8::Local<v8::Array> args,
v8::Local<v8::Object> server_vars,
v8::Local<v8::Value> init_func);
v8::Local<v8::Value> init_func,
const char *startup_file);
virtual ~PhpRequestWorker();
const inline Value &GetStream() { return stream_; }
const inline Value &GetInitFunc() { return init_func_; }
Expand All @@ -50,6 +51,7 @@ class PhpRequestWorker : public AsyncMessageWorker {
uint32_t argc_;
char **argv_;
std::unordered_map<std::string, std::string> server_vars_;
const char *startup_file_;
};

} // namespace node_php_embed
Expand Down

0 comments on commit 4f5a23c

Please sign in to comment.