📄 ngx_http_perl_module.c
字号:
/* * Copyright (C) Igor Sysoev */#include <ngx_config.h>#include <ngx_core.h>#include <ngx_http.h>#include <ngx_http_perl_module.h>typedef struct { PerlInterpreter *perl; HV *nginx; ngx_str_t modules; ngx_array_t requires;} ngx_http_perl_main_conf_t;typedef struct { SV *sub; ngx_str_t handler;} ngx_http_perl_loc_conf_t;typedef struct { SV *sub; ngx_str_t handler;} ngx_http_perl_variable_t;typedef struct { SV *sv; PerlInterpreter *perl;} ngx_http_perl_cleanup_t;#if (NGX_HTTP_SSI)static ngx_int_t ngx_http_perl_ssi(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ssi_ctx, ngx_str_t **params);#endifstatic void ngx_http_perl_sleep_handler(ngx_http_request_t *r);static char *ngx_http_perl_init_interpreter(ngx_conf_t *cf, ngx_http_perl_main_conf_t *pmcf);static PerlInterpreter *ngx_http_perl_create_interpreter(ngx_conf_t *cf, ngx_http_perl_main_conf_t *pmcf);static ngx_int_t ngx_http_perl_run_requires(pTHX_ ngx_array_t *requires, ngx_log_t *log);static ngx_int_t ngx_http_perl_call_handler(pTHX_ ngx_http_request_t *r, HV *nginx, SV *sub, ngx_str_t **args, ngx_str_t *handler, ngx_str_t *rv);static void ngx_http_perl_eval_anon_sub(pTHX_ ngx_str_t *handler, SV **sv);static ngx_int_t ngx_http_perl_preconfiguration(ngx_conf_t *cf);static void *ngx_http_perl_create_main_conf(ngx_conf_t *cf);static char *ngx_http_perl_init_main_conf(ngx_conf_t *cf, void *conf);static void *ngx_http_perl_create_loc_conf(ngx_conf_t *cf);static char *ngx_http_perl_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child);static char *ngx_http_perl_require(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);static char *ngx_http_perl(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);static char *ngx_http_perl_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);#if (NGX_HAVE_PERL_MULTIPLICITY)static void ngx_http_perl_cleanup_perl(void *data);#endifstatic ngx_int_t ngx_http_perl_init_worker(ngx_cycle_t *cycle);static void ngx_http_perl_exit(ngx_cycle_t *cycle);static ngx_command_t ngx_http_perl_commands[] = { { ngx_string("perl_modules"), NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, ngx_conf_set_str_slot, NGX_HTTP_MAIN_CONF_OFFSET, offsetof(ngx_http_perl_main_conf_t, modules), NULL }, { ngx_string("perl_require"), NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, ngx_http_perl_require, NGX_HTTP_MAIN_CONF_OFFSET, 0, NULL }, { ngx_string("perl"), NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF|NGX_CONF_TAKE1, ngx_http_perl, NGX_HTTP_LOC_CONF_OFFSET, 0, NULL }, { ngx_string("perl_set"), NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE2, ngx_http_perl_set, NGX_HTTP_LOC_CONF_OFFSET, 0, NULL }, ngx_null_command};static ngx_http_module_t ngx_http_perl_module_ctx = { ngx_http_perl_preconfiguration, /* preconfiguration */ NULL, /* postconfiguration */ ngx_http_perl_create_main_conf, /* create main configuration */ ngx_http_perl_init_main_conf, /* init main configuration */ NULL, /* create server configuration */ NULL, /* merge server configuration */ ngx_http_perl_create_loc_conf, /* create location configuration */ ngx_http_perl_merge_loc_conf /* merge location configuration */};ngx_module_t ngx_http_perl_module = { NGX_MODULE_V1, &ngx_http_perl_module_ctx, /* module context */ ngx_http_perl_commands, /* module directives */ NGX_HTTP_MODULE, /* module type */ NULL, /* init master */ NULL, /* init module */ ngx_http_perl_init_worker, /* init process */ NULL, /* init thread */ NULL, /* exit thread */ NULL, /* exit process */ ngx_http_perl_exit, /* exit master */ NGX_MODULE_V1_PADDING};#if (NGX_HTTP_SSI)#define NGX_HTTP_PERL_SSI_SUB 0#define NGX_HTTP_PERL_SSI_ARG 1static ngx_http_ssi_param_t ngx_http_perl_ssi_params[] = { { ngx_string("sub"), NGX_HTTP_PERL_SSI_SUB, 1, 0 }, { ngx_string("arg"), NGX_HTTP_PERL_SSI_ARG, 0, 1 }, { ngx_null_string, 0, 0, 0 }};static ngx_http_ssi_command_t ngx_http_perl_ssi_command = { ngx_string("perl"), ngx_http_perl_ssi, ngx_http_perl_ssi_params, 0, 0, 1};#endifstatic ngx_str_t ngx_null_name = ngx_null_string;static HV *nginx_stash;static voidngx_http_perl_xs_init(pTHX){ newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, __FILE__); nginx_stash = gv_stashpv("nginx", TRUE);}static ngx_int_tngx_http_perl_handler(ngx_http_request_t *r){ /* TODO: Win32 */ if (r->zero_in_uri) { return NGX_HTTP_NOT_FOUND; } ngx_http_perl_handle_request(r); return NGX_DONE;}voidngx_http_perl_handle_request(ngx_http_request_t *r){ SV *sub; ngx_int_t rc; ngx_str_t uri, args, *handler; ngx_http_perl_ctx_t *ctx; ngx_http_perl_loc_conf_t *plcf; ngx_http_perl_main_conf_t *pmcf; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "perl handler"); ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module); if (ctx == NULL) { ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_perl_ctx_t)); if (ctx == NULL) { ngx_http_finalize_request(r, NGX_ERROR); return; } ngx_http_set_ctx(r, ctx, ngx_http_perl_module); } pmcf = ngx_http_get_module_main_conf(r, ngx_http_perl_module); { dTHXa(pmcf->perl); PERL_SET_CONTEXT(pmcf->perl); if (ctx->next == NULL) { plcf = ngx_http_get_module_loc_conf(r, ngx_http_perl_module); sub = plcf->sub; handler = &plcf->handler; } else { sub = ctx->next; handler = &ngx_null_name; ctx->next = NULL; } rc = ngx_http_perl_call_handler(aTHX_ r, pmcf->nginx, sub, NULL, handler, NULL); } if (rc > 600) { rc = NGX_OK; } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "perl handler done: %i", rc); if (ctx->redirect_uri.len) { uri = ctx->redirect_uri; args = ctx->redirect_args; } else { uri.len = 0; } ctx->filename.data = NULL; ctx->redirect_uri.len = 0; if (ctx->sleep) { ngx_add_timer(r->connection->write, (ngx_msec_t) ctx->sleep); r->write_event_handler = ngx_http_perl_sleep_handler; ctx->sleep = 0; } if (ctx->done || ctx->next) { return; } if (uri.len) { ngx_http_internal_redirect(r, &uri, &args); return; } if (rc == NGX_OK || rc == NGX_HTTP_OK) { ngx_http_send_special(r, NGX_HTTP_LAST); ctx->done = 1; } ngx_http_finalize_request(r, rc);}static voidngx_http_perl_sleep_handler(ngx_http_request_t *r){ ngx_event_t *wev; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "perl sleep handler"); wev = r->connection->write; if (wev->timedout) { wev->timedout = 0; ngx_http_perl_handle_request(r); return; } if (ngx_handle_write_event(wev, 0) == NGX_ERROR) { ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); }}static ngx_int_tngx_http_perl_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data){ ngx_http_perl_variable_t *pv = (ngx_http_perl_variable_t *) data; ngx_int_t rc; ngx_str_t value; ngx_http_perl_ctx_t *ctx; ngx_http_perl_main_conf_t *pmcf; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "perl variable handler"); ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module); if (ctx == NULL) { ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_perl_ctx_t)); if (ctx == NULL) { return NGX_ERROR; } ngx_http_set_ctx(r, ctx, ngx_http_perl_module); } pmcf = ngx_http_get_module_main_conf(r, ngx_http_perl_module); value.data = NULL; { dTHXa(pmcf->perl); PERL_SET_CONTEXT(pmcf->perl); rc = ngx_http_perl_call_handler(aTHX_ r, pmcf->nginx, pv->sub, NULL, &pv->handler, &value); } if (value.data) { v->len = value.len; v->valid = 1; v->no_cachable = 0; v->not_found = 0; v->data = value.data; } else { v->not_found = 1; } ctx->filename.data = NULL; ctx->redirect_uri.len = 0; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "perl variable done"); return rc;}#if (NGX_HTTP_SSI)static ngx_int_tngx_http_perl_ssi(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ssi_ctx, ngx_str_t **params){ SV *sv; ngx_int_t rc; ngx_str_t *handler; ngx_http_perl_ctx_t *ctx; ngx_http_perl_main_conf_t *pmcf; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "perl ssi handler"); ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module); if (ctx == NULL) { ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_perl_ctx_t)); if (ctx == NULL) { return NGX_ERROR; } ngx_http_set_ctx(r, ctx, ngx_http_perl_module); } pmcf = ngx_http_get_module_main_conf(r, ngx_http_perl_module); ctx->ssi = ssi_ctx; handler = params[NGX_HTTP_PERL_SSI_SUB]; handler->data[handler->len] = '\0'; { dTHXa(pmcf->perl); PERL_SET_CONTEXT(pmcf->perl);#if 0 /* the code is disabled to force the precompiled perl code using only */ ngx_http_perl_eval_anon_sub(aTHX_ handler, &sv); if (sv == &PL_sv_undef) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "eval_pv(\"%V\") failed", handler); return NGX_ERROR; } if (sv == NULL) { sv = newSVpvn((char *) handler->data, handler->len); }#endif sv = newSVpvn((char *) handler->data, handler->len); rc = ngx_http_perl_call_handler(aTHX_ r, pmcf->nginx, sv, ¶ms[NGX_HTTP_PERL_SSI_ARG], handler, NULL); SvREFCNT_dec(sv); } ctx->filename.data = NULL; ctx->redirect_uri.len = 0; ctx->ssi = NULL; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "perl ssi done"); return rc;}#endifstatic char *ngx_http_perl_init_interpreter(ngx_conf_t *cf, ngx_http_perl_main_conf_t *pmcf){#if (NGX_HAVE_PERL_MULTIPLICITY) ngx_pool_cleanup_t *cln; cln = ngx_pool_cleanup_add(cf->pool, 0); if (cln == NULL) { return NGX_CONF_ERROR; }#else static PerlInterpreter *perl;#endif#ifdef NGX_PERL_MODULES if (pmcf->modules.data == NULL) { pmcf->modules.data = NGX_PERL_MODULES; }#endif if (pmcf->modules.data) { if (ngx_conf_full_name(cf->cycle, &pmcf->modules) != NGX_OK) { return NGX_CONF_ERROR; } }#if !(NGX_HAVE_PERL_MULTIPLICITY) if (perl) { if (ngx_set_environment(cf->cycle, NULL) == NULL) { return NGX_CONF_ERROR; } if (ngx_http_perl_run_requires(aTHX_ &pmcf->requires, cf->log) != NGX_OK) { return NGX_CONF_ERROR; } pmcf->perl = perl; pmcf->nginx = nginx_stash; return NGX_CONF_OK; }#endif if (nginx_stash == NULL) { PERL_SYS_INIT(&ngx_argc, &ngx_argv); } pmcf->perl = ngx_http_perl_create_interpreter(cf, pmcf); if (pmcf->perl == NULL) { return NGX_CONF_ERROR; } pmcf->nginx = nginx_stash;#if (NGX_HAVE_PERL_MULTIPLICITY) cln->handler = ngx_http_perl_cleanup_perl; cln->data = pmcf->perl;#else perl = pmcf->perl;#endif return NGX_CONF_OK;}static PerlInterpreter *ngx_http_perl_create_interpreter(ngx_conf_t *cf, ngx_http_perl_main_conf_t *pmcf){ int n; STRLEN len; SV *sv;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -