|
|
|
@ -278,6 +278,8 @@ typedef struct {
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
fcgi_exts *exts;
|
|
|
|
|
|
|
|
|
|
array *ext_mapping;
|
|
|
|
|
|
|
|
|
|
int debug;
|
|
|
|
|
} plugin_config;
|
|
|
|
@ -679,6 +681,7 @@ FREE_FUNC(mod_fastcgi_free) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fastcgi_extensions_free(s->exts);
|
|
|
|
|
array_free(s->ext_mapping);
|
|
|
|
|
|
|
|
|
|
free(s);
|
|
|
|
|
}
|
|
|
|
@ -1082,6 +1085,7 @@ SETDEFAULTS_FUNC(mod_fastcgi_set_defaults) {
|
|
|
|
|
config_values_t cv[] = {
|
|
|
|
|
{ "fastcgi.server", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
|
|
|
|
|
{ "fastcgi.debug", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
|
|
|
|
|
{ "fastcgi.map-extensions", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
|
|
|
|
|
{ NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
@ -1094,9 +1098,11 @@ SETDEFAULTS_FUNC(mod_fastcgi_set_defaults) {
|
|
|
|
|
s = malloc(sizeof(plugin_config));
|
|
|
|
|
s->exts = fastcgi_extensions_init();
|
|
|
|
|
s->debug = 0;
|
|
|
|
|
s->ext_mapping = array_init();
|
|
|
|
|
|
|
|
|
|
cv[0].destination = s->exts;
|
|
|
|
|
cv[1].destination = &(s->debug);
|
|
|
|
|
cv[2].destination = s->ext_mapping;
|
|
|
|
|
|
|
|
|
|
p->config_storage[i] = s;
|
|
|
|
|
ca = ((data_config *)srv->config_context->data[i])->value;
|
|
|
|
@ -1529,6 +1535,7 @@ static int fcgi_reconnect(server *srv, handler_ctx *hctx) {
|
|
|
|
|
if (hctx->proc) {
|
|
|
|
|
hctx->proc->load--;
|
|
|
|
|
fcgi_proclist_sort_down(srv, hctx->host, hctx->proc);
|
|
|
|
|
hctx->host->load--;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* perhaps another host gives us more luck */
|
|
|
|
@ -2898,6 +2905,7 @@ static handler_t fcgi_write_request(server *srv, handler_ctx *hctx) {
|
|
|
|
|
/* ok, we have the connection */
|
|
|
|
|
|
|
|
|
|
hctx->proc->load++;
|
|
|
|
|
hctx->host->load++;
|
|
|
|
|
hctx->proc->last_used = srv->cur_ts;
|
|
|
|
|
hctx->got_proc = 1;
|
|
|
|
|
|
|
|
|
@ -3039,7 +3047,7 @@ SUBREQUEST_FUNC(mod_fastcgi_handle_subrequest) {
|
|
|
|
|
for (k = 0, ndx = -1; k < hctx->ext->used; k++) {
|
|
|
|
|
host = hctx->ext->hosts[k];
|
|
|
|
|
|
|
|
|
|
/* we should have at least one proc that can do somthing */
|
|
|
|
|
/* we should have at least one proc that can do something */
|
|
|
|
|
if (host->active_procs == 0) continue;
|
|
|
|
|
|
|
|
|
|
if (used == -1 || host->load < used) {
|
|
|
|
@ -3368,6 +3376,7 @@ static int fcgi_patch_connection(server *srv, connection *con, plugin_data *p) {
|
|
|
|
|
|
|
|
|
|
PATCH(exts);
|
|
|
|
|
PATCH(debug);
|
|
|
|
|
PATCH(ext_mapping);
|
|
|
|
|
|
|
|
|
|
/* skip the first, the global context */
|
|
|
|
|
for (i = 1; i < srv->config_context->used; i++) {
|
|
|
|
@ -3385,6 +3394,8 @@ static int fcgi_patch_connection(server *srv, connection *con, plugin_data *p) {
|
|
|
|
|
PATCH(exts);
|
|
|
|
|
} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("fastcgi.debug"))) {
|
|
|
|
|
PATCH(debug);
|
|
|
|
|
} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("fastcgi.map-extensions"))) {
|
|
|
|
|
PATCH(ext_mapping);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -3414,34 +3425,75 @@ static handler_t fcgi_check_extension(server *srv, connection *con, void *p_d, i
|
|
|
|
|
s_len = fn->used - 1;
|
|
|
|
|
|
|
|
|
|
fcgi_patch_connection(srv, con, p);
|
|
|
|
|
|
|
|
|
|
/* check if extension matches */
|
|
|
|
|
for (k = 0; k < p->conf.exts->used; k++) {
|
|
|
|
|
|
|
|
|
|
/* fastcgi.map-extensions maps extensions to existing fastcgi.server entries
|
|
|
|
|
*
|
|
|
|
|
* fastcgi.map-extensions = ( ".php3" => ".php" )
|
|
|
|
|
*
|
|
|
|
|
* fastcgi.server = ( ".php" => ... )
|
|
|
|
|
*
|
|
|
|
|
* */
|
|
|
|
|
|
|
|
|
|
/* check if extension-mapping matches */
|
|
|
|
|
for (k = 0; k < p->conf.ext_mapping->used; k++) {
|
|
|
|
|
data_string *ds = (data_string *)p->conf.ext_mapping->data[k];
|
|
|
|
|
size_t ct_len; /* length of the config entry */
|
|
|
|
|
|
|
|
|
|
extension = p->conf.exts->exts[k];
|
|
|
|
|
if (ds->key->used == 0) continue;
|
|
|
|
|
|
|
|
|
|
if (extension->key->used == 0) continue;
|
|
|
|
|
|
|
|
|
|
ct_len = extension->key->used - 1;
|
|
|
|
|
ct_len = ds->key->used - 1;
|
|
|
|
|
|
|
|
|
|
if (s_len < ct_len) continue;
|
|
|
|
|
|
|
|
|
|
/* check extension in the form "/fcgi_pattern" */
|
|
|
|
|
if (*(extension->key->ptr) == '/' && strncmp(fn->ptr, extension->key->ptr, ct_len) == 0) {
|
|
|
|
|
break;
|
|
|
|
|
} else if (0 == strncmp(fn->ptr + s_len - ct_len, extension->key->ptr, ct_len)) {
|
|
|
|
|
/* check extension in the form ".fcg" */
|
|
|
|
|
/* found a mapping */
|
|
|
|
|
if (0 == strncmp(fn->ptr + s_len - ct_len, ds->key->ptr, ct_len)) {
|
|
|
|
|
/* check if we know the extension */
|
|
|
|
|
|
|
|
|
|
/* we can reuse k here */
|
|
|
|
|
for (k = 0; k < p->conf.exts->used; k++) {
|
|
|
|
|
extension = p->conf.exts->exts[k];
|
|
|
|
|
|
|
|
|
|
if (buffer_is_equal(ds->value, extension->key)) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (k == p->conf.exts->used) {
|
|
|
|
|
/* found nothign */
|
|
|
|
|
extension = NULL;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* extension doesn't match */
|
|
|
|
|
if (k == p->conf.exts->used) {
|
|
|
|
|
return HANDLER_GO_ON;
|
|
|
|
|
|
|
|
|
|
if (extension == NULL) {
|
|
|
|
|
/* check if extension matches */
|
|
|
|
|
for (k = 0; k < p->conf.exts->used; k++) {
|
|
|
|
|
size_t ct_len; /* length of the config entry */
|
|
|
|
|
|
|
|
|
|
extension = p->conf.exts->exts[k];
|
|
|
|
|
|
|
|
|
|
if (extension->key->used == 0) continue;
|
|
|
|
|
|
|
|
|
|
ct_len = extension->key->used - 1;
|
|
|
|
|
|
|
|
|
|
if (s_len < ct_len) continue;
|
|
|
|
|
|
|
|
|
|
/* check extension in the form "/fcgi_pattern" */
|
|
|
|
|
if (*(extension->key->ptr) == '/' && strncmp(fn->ptr, extension->key->ptr, ct_len) == 0) {
|
|
|
|
|
break;
|
|
|
|
|
} else if (0 == strncmp(fn->ptr + s_len - ct_len, extension->key->ptr, ct_len)) {
|
|
|
|
|
/* check extension in the form ".fcg" */
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* extension doesn't match */
|
|
|
|
|
if (k == p->conf.exts->used) {
|
|
|
|
|
return HANDLER_GO_ON;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* get best server */
|
|
|
|
|
/* check if we have at least one server for this extension up and running */
|
|
|
|
|
for (k = 0; k < extension->used; k++) {
|
|
|
|
|
host = extension->hosts[k];
|
|
|
|
|
|
|
|
|
|