0
+ * A few functions are based on the code from mod_scgi 1.9. mod_scgi is
0
+ * Copyright (c) 2004 Corporation for National Research Initiatives; All Rights Reserved
0
#include <http_config.h>
0
#include <util_script.h>
0
#include <apr_strings.h>
0
- static ApplicationPoolPtr applicationPool;
0
+ ApplicationPoolPtr applicationPool;
0
RailsConfig *getConfig(request_rec *r) {
0
return (RailsConfig *) ap_get_module_config(r->per_dir_config, &rails_module);
0
bool verifyRailsDir(apr_pool_t *pool, const char *dir) {
0
return fileExists(pool, apr_pstrcat(pool, dir, "/../config/environment.rb", NULL));
0
+ char *http2env(apr_pool_t *p, const char *name) {
0
+ char *env_name = apr_pstrcat(p, "HTTP_", name, NULL);
0
+ for (cp = env_name + 5; *cp != 0; cp++) {
0
+ *cp = apr_toupper(*cp);
0
+ char *lookupName(apr_table_t *t, const char *name) {
0
+ const apr_array_header_t *hdrs_arr = apr_table_elts(t);
0
+ apr_table_entry_t *hdrs = (apr_table_entry_t *) hdrs_arr->elts;
0
+ for (i = 0; i < hdrs_arr->nelts; ++i) {
0
+ if (hdrs[i].key == NULL) {
0
+ if (strcasecmp(hdrs[i].key, name) == 0) {
0
+ char *lookupHeader(request_rec *r, const char *name) {
0
+ return lookupName(r->headers_in, name);
0
+ char *lookupEnv(request_rec *r, const char *name) {
0
+ return lookupName(r->subprocess_env, name);
0
+ // This code is a duplicate of what's in util_script.c. We can't use
0
+ // r->unparsed_uri because it gets changed if there was a redirect.
0
+ char *originalURI(request_rec *r) {
0
+ if (r->the_request == NULL) {
0
+ return (char *) apr_pcalloc(r->pool, 1);
0
+ first = r->the_request; // use the request-line
0
+ while (*first && !apr_isspace(*first)) {
0
+ ++first; // skip over the method
0
+ while (apr_isspace(*first)) {
0
+ ++first; // and the space(s)
0
+ while (*last && !apr_isspace(*last)) {
0
+ ++last; // end at next whitespace
0
+ return apr_pstrmemdup(r->pool, first, last - first);
0
void addHeader(apr_table_t *table, const char *name, const char *value) {
0
if (name != NULL && value != NULL) {
0
apr_table_addn(table, name, value);
0
addHeader(headers, "REMOTE_PORT", apr_psprintf(r->pool, "%d", r->connection->remote_addr->port));
0
addHeader(headers, "REMOTE_USER", r->user);
0
addHeader(headers, "REQUEST_METHOD", r->method);
0
-
//addHeader(headers, "REQUEST_URI", original_uri(r));
0
+
addHeader(headers, "REQUEST_URI", originalURI(r));
0
addHeader(headers, "QUERY_STRING", r->args ? r->args : "");
0
addHeader(headers, "SCRIPT_NAME", r->uri);
0
addHeader(headers, "SCRIPT_NAME", r->uri);
0
- //addHeader(headers, "HTTPS", lookup_env(r, "HTTPS"));
0
- //addHeader(headers, "CONTENT_TYPE", lookup_header(r, "Content-type"));
0
+ addHeader(headers, "HTTPS", lookupEnv(r, "HTTPS"));
0
+ addHeader(headers, "CONTENT_TYPE", lookupHeader(r, "Content-type"));
0
addHeader(headers, "DOCUMENT_ROOT", ap_document_root(r));
0
hdrs = (apr_table_entry_t *) hdrs_arr->elts;
0
for (i = 0; i < hdrs_arr->nelts; ++i) {
0
-
//addHeader(headers, http2env(r->pool, hdrs[i].key), hdrs[i].val);
0
+
addHeader(headers, http2env(r->pool, hdrs[i].key), hdrs[i].val);
0
MessageChannel channel(fd);
0
hdrs_arr = apr_table_elts(headers);
0
hdrs = (apr_table_entry_t*) hdrs_arr->elts;
0
for (i = 0; i < hdrs_arr->nelts; ++i) {
0
- // TODO: Internally, this creates a new list every time.
0
- // It can be optimized by using an array or a vector.
0
- channel.write(hdrs[i].key, hdrs[i].val, NULL);
0
+ // TODO: optimize this. too much copying.
0
+ entries.push_back(hdrs[i].key);
0
+ entries.push_back(hdrs[i].val);
0
- channel.write(
"", NULL);
0
+ channel.write(
entries);
0
- debug(const char *format, ...) {
0
- int size = apr_vsnprintf(message, sizeof(message), format, ap);
0
- FILE *f = fopen("/dev/pts/3", "w");
0
- fwrite(message, 1, size, f);
0
- init(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *base_server) {
0
- initDebugging("/tmp/passenger.txt");
0
- ap_add_version_component(p, "Phusion_Passenger/" PASSENGER_VERSION);
0
+ Hooks(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s) {
0
+ P_DEBUG("Initializing mod_passenger.");
0
+ ap_add_version_component(pconf, "Phusion_Passenger/" PASSENGER_VERSION);
0
const char *spawnManagerCommand = "/home/hongli/Projects/mod_rails/lib/mod_rails/spawn_manager.rb";
0
const char *logFile = "/home/hongli/Projects/mod_rails/spawner_log.txt";
0
- applicationPool = ApplicationPoolPtr(new ApplicationPool(spawnManagerCommand, logFile));
0
+ applicationPool = ApplicationPoolPtr(new ApplicationPool(spawnManagerCommand, logFile, "production"));
0
- handleRequest(request_rec *r) {
0
+ P_DEBUG("Shutting down mod_passenger.");
0
+ void initChild(apr_pool_t *pchild, server_rec *s) {
0
+ int handleRequest(request_rec *r) {
0
// The main request handler hook function.
0
RailsConfig *config = getConfig(r);
0
/* int httpStatus = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR);
0
if (httpStatus != OK) {
0
P_DEBUG("Processing HTTP request: " << r->uri);
0
ApplicationPtr app(applicationPool->get(string(railsDir) + "/.."));
0
- P_
DEBUG("Connected to application: reader FD = " << app->getReader() << ", writer FD = " << app->getWriter());
0
+ P_
TRACE("Connected to application: reader FD = " << app->getReader() << ", writer FD = " << app->getWriter());
0
sendHeaders(r, app->getWriter());
0
bb = apr_brigade_create(r->connection->pool, r->connection->bucket_alloc);
0
-ApplicationPoolPtr Hooks::applicationPool;
0
+/******************************************************************
0
+ * Below follows lightweight C wrappers around the C++ Hook class.
0
+ ******************************************************************/
0
+static Hooks *hooks = NULL;
0
+destroy_hooks(void *arg) {
0
-init(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *base_server) {
0
- return Hooks().init(p, plog, ptemp, base_server);
0
+init_module(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s) {
0
+ * 1. Apache on Unix calls the post_config hook twice, once before detach() and once
0
+ * after. On Windows it never calls detach().
0
+ * 2. When Apache is compiled to use DSO modules, the modules are unloaded between the
0
+ * two post_config hook calls.
0
+ * 3. On Unix, if the -X commandline option is given, detach() will not be called.
0
+ * Because of these 3 issues (and especially #2), we only want to intialize the second
0
+ * time the post_config hook is called.
0
+ void *firstInitCall = NULL;
0
+ apr_pool_t *processPool = s->process->pool;
0
+ apr_pool_userdata_get(&firstInitCall, "mod_passenger", processPool);
0
+ if (firstInitCall == NULL) {
0
+ apr_pool_userdata_set((const void *) 1, "mod_passenger",
0
+ apr_pool_cleanup_null, processPool);
0
+ hooks = new Hooks(pconf, plog, ptemp, s);
0
+ apr_pool_cleanup_register(pconf, NULL,
0
+ apr_pool_cleanup_null);
0
+init_child(apr_pool_t *pchild, server_rec *s) {
0
+ return hooks->initChild(pchild, s);
0
handle_request(request_rec *r) {
0
- return Hooks().handleRequest(r);
0
+ return hooks->handleRequest(r);
0
map_to_storage(request_rec *r) {
0
- return Hooks().mapToStorage(r);
0
+ return hooks->mapToStorage(r);
0
passenger_register_hooks(apr_pool_t *p) {
0
- ap_hook_post_config(init, NULL, NULL, APR_HOOK_MIDDLE);
0
+ ap_hook_post_config(init_module, NULL, NULL, APR_HOOK_MIDDLE);
0
+ ap_hook_child_init(init_child, NULL, NULL, APR_HOOK_MIDDLE);
0
ap_hook_map_to_storage(map_to_storage, NULL, NULL, APR_HOOK_FIRST);
0
ap_hook_handler(handle_request, NULL, NULL, APR_HOOK_FIRST);
Comments
No one has commented yet.