1510Salexander.borisov@nginx.com 2510Salexander.borisov@nginx.com /* 3510Salexander.borisov@nginx.com * Copyright (C) Alexander Borisov 4510Salexander.borisov@nginx.com * Copyright (C) NGINX, Inc. 5510Salexander.borisov@nginx.com */ 6510Salexander.borisov@nginx.com 7510Salexander.borisov@nginx.com #include <perl/nxt_perl_psgi_layer.h> 8510Salexander.borisov@nginx.com 9510Salexander.borisov@nginx.com #include <nxt_main.h> 10510Salexander.borisov@nginx.com #include <nxt_router.h> 11510Salexander.borisov@nginx.com #include <nxt_runtime.h> 12510Salexander.borisov@nginx.com #include <nxt_application.h> 13510Salexander.borisov@nginx.com #include <nxt_file.h> 14510Salexander.borisov@nginx.com 15510Salexander.borisov@nginx.com 16510Salexander.borisov@nginx.com typedef struct { 17510Salexander.borisov@nginx.com PerlInterpreter *my_perl; 18510Salexander.borisov@nginx.com 19510Salexander.borisov@nginx.com nxt_task_t *task; 20510Salexander.borisov@nginx.com nxt_app_rmsg_t *rmsg; 21510Salexander.borisov@nginx.com nxt_app_wmsg_t *wmsg; 22510Salexander.borisov@nginx.com 23510Salexander.borisov@nginx.com size_t body_preread_size; 24510Salexander.borisov@nginx.com } nxt_perl_psgi_input_t; 25510Salexander.borisov@nginx.com 26510Salexander.borisov@nginx.com 27521Szelenkov@nginx.com nxt_inline nxt_int_t nxt_perl_psgi_write(nxt_task_t *task, nxt_app_wmsg_t *wmsg, 28510Salexander.borisov@nginx.com const u_char *data, size_t len, 29510Salexander.borisov@nginx.com nxt_bool_t flush, nxt_bool_t last); 30510Salexander.borisov@nginx.com 31510Salexander.borisov@nginx.com nxt_inline nxt_int_t nxt_perl_psgi_http_write_status_str(nxt_task_t *task, 32510Salexander.borisov@nginx.com nxt_app_wmsg_t *wmsg, nxt_str_t *http_status); 33510Salexander.borisov@nginx.com 34510Salexander.borisov@nginx.com static long nxt_perl_psgi_io_input_read(PerlInterpreter *my_perl, 35510Salexander.borisov@nginx.com nxt_perl_psgi_io_arg_t *arg, void *vbuf, size_t length); 36510Salexander.borisov@nginx.com static long nxt_perl_psgi_io_input_write(PerlInterpreter *my_perl, 37510Salexander.borisov@nginx.com nxt_perl_psgi_io_arg_t *arg, const void *vbuf, size_t length); 38510Salexander.borisov@nginx.com static long nxt_perl_psgi_io_input_flush(PerlInterpreter *my_perl, 39510Salexander.borisov@nginx.com nxt_perl_psgi_io_arg_t *arg); 40510Salexander.borisov@nginx.com 41510Salexander.borisov@nginx.com static long nxt_perl_psgi_io_error_read(PerlInterpreter *my_perl, 42510Salexander.borisov@nginx.com nxt_perl_psgi_io_arg_t *arg, void *vbuf, size_t length); 43510Salexander.borisov@nginx.com static long nxt_perl_psgi_io_error_write(PerlInterpreter *my_perl, 44510Salexander.borisov@nginx.com nxt_perl_psgi_io_arg_t *arg, const void *vbuf, size_t length); 45510Salexander.borisov@nginx.com static long nxt_perl_psgi_io_error_flush(PerlInterpreter *my_perl, 46510Salexander.borisov@nginx.com nxt_perl_psgi_io_arg_t *arg); 47510Salexander.borisov@nginx.com 48510Salexander.borisov@nginx.com /* 49510Salexander.borisov@nginx.com static void nxt_perl_psgi_xs_core_global_changes(PerlInterpreter *my_perl, 50510Salexander.borisov@nginx.com const char *core, const char *sub, XSUBADDR_t sub_addr); 51510Salexander.borisov@nginx.com */ 52510Salexander.borisov@nginx.com 53510Salexander.borisov@nginx.com static void nxt_perl_psgi_xs_init(pTHX); 54510Salexander.borisov@nginx.com 55510Salexander.borisov@nginx.com static SV *nxt_perl_psgi_call_var_application(PerlInterpreter *my_perl, 56510Salexander.borisov@nginx.com SV *env, nxt_task_t *task); 57510Salexander.borisov@nginx.com 58510Salexander.borisov@nginx.com /* For currect load XS modules */ 59510Salexander.borisov@nginx.com EXTERN_C void boot_DynaLoader(pTHX_ CV *cv); 60510Salexander.borisov@nginx.com 61510Salexander.borisov@nginx.com static nxt_int_t nxt_perl_psgi_io_input_init(PerlInterpreter *my_perl, 62510Salexander.borisov@nginx.com nxt_perl_psgi_io_arg_t *arg); 63510Salexander.borisov@nginx.com static nxt_int_t nxt_perl_psgi_io_error_init(PerlInterpreter *my_perl, 64510Salexander.borisov@nginx.com nxt_perl_psgi_io_arg_t *arg); 65510Salexander.borisov@nginx.com 66510Salexander.borisov@nginx.com static PerlInterpreter *nxt_perl_psgi_interpreter_init(nxt_task_t *task, 67510Salexander.borisov@nginx.com char *script); 68510Salexander.borisov@nginx.com 69510Salexander.borisov@nginx.com nxt_inline nxt_int_t nxt_perl_psgi_env_append_str(PerlInterpreter *my_perl, 70510Salexander.borisov@nginx.com HV *hash_env, const char *name, nxt_str_t *str); 71510Salexander.borisov@nginx.com nxt_inline nxt_int_t nxt_perl_psgi_env_append(PerlInterpreter *my_perl, 72510Salexander.borisov@nginx.com HV *hash_env, const char *name, void *value); 73510Salexander.borisov@nginx.com 74510Salexander.borisov@nginx.com static SV *nxt_perl_psgi_env_create(PerlInterpreter *my_perl, nxt_task_t *task, 75510Salexander.borisov@nginx.com nxt_app_rmsg_t *rmsg, size_t *body_preread_size); 76510Salexander.borisov@nginx.com 77510Salexander.borisov@nginx.com nxt_inline nxt_int_t nxt_perl_psgi_read_add_env(PerlInterpreter *my_perl, 78510Salexander.borisov@nginx.com nxt_task_t *task, nxt_app_rmsg_t *rmsg, HV *hash_env, 79510Salexander.borisov@nginx.com const char *name, nxt_str_t *str); 80510Salexander.borisov@nginx.com 81510Salexander.borisov@nginx.com static u_char *nxt_perl_psgi_module_create(nxt_task_t *task, 82510Salexander.borisov@nginx.com const char *script); 83510Salexander.borisov@nginx.com 84510Salexander.borisov@nginx.com static nxt_str_t nxt_perl_psgi_result_status(PerlInterpreter *my_perl, 85510Salexander.borisov@nginx.com SV *result); 86510Salexander.borisov@nginx.com static nxt_int_t nxt_perl_psgi_result_head(PerlInterpreter *my_perl, 87510Salexander.borisov@nginx.com SV *sv_head, nxt_task_t *task, nxt_app_wmsg_t *wmsg); 88510Salexander.borisov@nginx.com static nxt_int_t nxt_perl_psgi_result_body(PerlInterpreter *my_perl, 89510Salexander.borisov@nginx.com SV *result, nxt_task_t *task, nxt_app_wmsg_t *wmsg); 90510Salexander.borisov@nginx.com static nxt_int_t nxt_perl_psgi_result_body_ref(PerlInterpreter *my_perl, 91510Salexander.borisov@nginx.com SV *sv_body, nxt_task_t *task, nxt_app_wmsg_t *wmsg); 92510Salexander.borisov@nginx.com static nxt_int_t nxt_perl_psgi_result_array(PerlInterpreter *my_perl, 93510Salexander.borisov@nginx.com SV *result, nxt_task_t *task, nxt_app_wmsg_t *wmsg); 94510Salexander.borisov@nginx.com 95510Salexander.borisov@nginx.com static nxt_int_t nxt_perl_psgi_init(nxt_task_t *task, 96510Salexander.borisov@nginx.com nxt_common_app_conf_t *conf); 97510Salexander.borisov@nginx.com static nxt_int_t nxt_perl_psgi_run(nxt_task_t *task, 98510Salexander.borisov@nginx.com nxt_app_rmsg_t *rmsg, nxt_app_wmsg_t *wmsg); 99510Salexander.borisov@nginx.com static void nxt_perl_psgi_atexit(nxt_task_t *task); 100510Salexander.borisov@nginx.com 101510Salexander.borisov@nginx.com typedef SV *(*nxt_perl_psgi_callback_f)(PerlInterpreter *my_perl, 102510Salexander.borisov@nginx.com SV *env, nxt_task_t *task); 103510Salexander.borisov@nginx.com 104510Salexander.borisov@nginx.com static SV *nxt_perl_psgi_app; 105510Salexander.borisov@nginx.com static PerlInterpreter *nxt_perl_psgi; 106510Salexander.borisov@nginx.com static nxt_perl_psgi_io_arg_t nxt_perl_psgi_arg_input, nxt_perl_psgi_arg_error; 107510Salexander.borisov@nginx.com 108510Salexander.borisov@nginx.com static uint32_t nxt_perl_psgi_compat[] = { 109510Salexander.borisov@nginx.com NXT_VERNUM, NXT_DEBUG, 110510Salexander.borisov@nginx.com }; 111510Salexander.borisov@nginx.com 112510Salexander.borisov@nginx.com NXT_EXPORT nxt_application_module_t nxt_app_module = { 113510Salexander.borisov@nginx.com sizeof(nxt_perl_psgi_compat), 114510Salexander.borisov@nginx.com nxt_perl_psgi_compat, 115510Salexander.borisov@nginx.com nxt_string("perl"), 116*612Salexander.borisov@nginx.com PERL_VERSION_STRING, 117510Salexander.borisov@nginx.com nxt_perl_psgi_init, 118510Salexander.borisov@nginx.com nxt_perl_psgi_run, 119510Salexander.borisov@nginx.com nxt_perl_psgi_atexit, 120510Salexander.borisov@nginx.com }; 121510Salexander.borisov@nginx.com 122510Salexander.borisov@nginx.com 123510Salexander.borisov@nginx.com nxt_inline nxt_int_t 124510Salexander.borisov@nginx.com nxt_perl_psgi_write(nxt_task_t *task, nxt_app_wmsg_t *wmsg, 125510Salexander.borisov@nginx.com const u_char *data, size_t len, 126510Salexander.borisov@nginx.com nxt_bool_t flush, nxt_bool_t last) 127510Salexander.borisov@nginx.com { 128510Salexander.borisov@nginx.com nxt_int_t rc; 129510Salexander.borisov@nginx.com 130510Salexander.borisov@nginx.com rc = nxt_app_msg_write_raw(task, wmsg, data, len); 131510Salexander.borisov@nginx.com 132510Salexander.borisov@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 133510Salexander.borisov@nginx.com return rc; 134510Salexander.borisov@nginx.com } 135510Salexander.borisov@nginx.com 136510Salexander.borisov@nginx.com if (flush || last) { 137510Salexander.borisov@nginx.com rc = nxt_app_msg_flush(task, wmsg, last); 138510Salexander.borisov@nginx.com } 139510Salexander.borisov@nginx.com 140510Salexander.borisov@nginx.com return rc; 141510Salexander.borisov@nginx.com } 142510Salexander.borisov@nginx.com 143510Salexander.borisov@nginx.com 144510Salexander.borisov@nginx.com nxt_inline nxt_int_t 145510Salexander.borisov@nginx.com nxt_perl_psgi_http_write_status_str(nxt_task_t *task, nxt_app_wmsg_t *wmsg, 146510Salexander.borisov@nginx.com nxt_str_t *http_status) 147510Salexander.borisov@nginx.com { 148510Salexander.borisov@nginx.com nxt_int_t rc; 149510Salexander.borisov@nginx.com 150510Salexander.borisov@nginx.com rc = NXT_OK; 151510Salexander.borisov@nginx.com 152510Salexander.borisov@nginx.com #define RC_WRT(DATA, DATALEN, FLUSH) \ 153510Salexander.borisov@nginx.com do { \ 154510Salexander.borisov@nginx.com rc = nxt_perl_psgi_write(task, wmsg, DATA, \ 155510Salexander.borisov@nginx.com DATALEN, FLUSH, 0); \ 156510Salexander.borisov@nginx.com if (nxt_slow_path(rc != NXT_OK)) \ 157510Salexander.borisov@nginx.com return rc; \ 158510Salexander.borisov@nginx.com \ 159510Salexander.borisov@nginx.com } while (0) 160510Salexander.borisov@nginx.com 161510Salexander.borisov@nginx.com RC_WRT((const u_char *) "Status: ", (sizeof("Status: ") - 1), 0); 162510Salexander.borisov@nginx.com RC_WRT(http_status->start, http_status->length, 0); 163510Salexander.borisov@nginx.com RC_WRT((u_char *) "\r\n", (sizeof("\r\n") - 1), 0); 164510Salexander.borisov@nginx.com 165510Salexander.borisov@nginx.com #undef RC_WRT 166510Salexander.borisov@nginx.com 167510Salexander.borisov@nginx.com return rc; 168510Salexander.borisov@nginx.com } 169510Salexander.borisov@nginx.com 170510Salexander.borisov@nginx.com 171510Salexander.borisov@nginx.com static long 172510Salexander.borisov@nginx.com nxt_perl_psgi_io_input_read(PerlInterpreter *my_perl, 173510Salexander.borisov@nginx.com nxt_perl_psgi_io_arg_t *arg, void *vbuf, size_t length) 174510Salexander.borisov@nginx.com { 175510Salexander.borisov@nginx.com size_t copy_size; 176510Salexander.borisov@nginx.com nxt_perl_psgi_input_t *input; 177510Salexander.borisov@nginx.com 178510Salexander.borisov@nginx.com input = (nxt_perl_psgi_input_t *) arg->ctx; 179510Salexander.borisov@nginx.com 180510Salexander.borisov@nginx.com if (input->body_preread_size == 0) { 181510Salexander.borisov@nginx.com return 0; 182510Salexander.borisov@nginx.com } 183510Salexander.borisov@nginx.com 184510Salexander.borisov@nginx.com copy_size = nxt_min(length, input->body_preread_size); 185510Salexander.borisov@nginx.com copy_size = nxt_app_msg_read_raw(input->task, input->rmsg, 186510Salexander.borisov@nginx.com vbuf, copy_size); 187510Salexander.borisov@nginx.com 188510Salexander.borisov@nginx.com input->body_preread_size -= copy_size; 189510Salexander.borisov@nginx.com 190510Salexander.borisov@nginx.com return copy_size; 191510Salexander.borisov@nginx.com } 192510Salexander.borisov@nginx.com 193510Salexander.borisov@nginx.com 194510Salexander.borisov@nginx.com static long 195510Salexander.borisov@nginx.com nxt_perl_psgi_io_input_write(PerlInterpreter *my_perl, 196510Salexander.borisov@nginx.com nxt_perl_psgi_io_arg_t *arg, const void *vbuf, size_t length) 197510Salexander.borisov@nginx.com { 198510Salexander.borisov@nginx.com return 0; 199510Salexander.borisov@nginx.com } 200510Salexander.borisov@nginx.com 201510Salexander.borisov@nginx.com 202510Salexander.borisov@nginx.com static long 203510Salexander.borisov@nginx.com nxt_perl_psgi_io_input_flush(PerlInterpreter *my_perl, 204510Salexander.borisov@nginx.com nxt_perl_psgi_io_arg_t *arg) 205510Salexander.borisov@nginx.com { 206510Salexander.borisov@nginx.com return 0; 207510Salexander.borisov@nginx.com } 208510Salexander.borisov@nginx.com 209510Salexander.borisov@nginx.com 210510Salexander.borisov@nginx.com static long 211510Salexander.borisov@nginx.com nxt_perl_psgi_io_error_read(PerlInterpreter *my_perl, 212510Salexander.borisov@nginx.com nxt_perl_psgi_io_arg_t *arg, void *vbuf, size_t length) 213510Salexander.borisov@nginx.com { 214510Salexander.borisov@nginx.com return 0; 215510Salexander.borisov@nginx.com } 216510Salexander.borisov@nginx.com 217510Salexander.borisov@nginx.com 218510Salexander.borisov@nginx.com static long 219510Salexander.borisov@nginx.com nxt_perl_psgi_io_error_write(PerlInterpreter *my_perl, 220510Salexander.borisov@nginx.com nxt_perl_psgi_io_arg_t *arg, const void *vbuf, size_t length) 221510Salexander.borisov@nginx.com { 222510Salexander.borisov@nginx.com nxt_perl_psgi_input_t *input; 223510Salexander.borisov@nginx.com 224510Salexander.borisov@nginx.com input = (nxt_perl_psgi_input_t *) arg->ctx; 225510Salexander.borisov@nginx.com nxt_log_error(NXT_LOG_ERR, input->task->log, "Perl: %s", vbuf); 226510Salexander.borisov@nginx.com 227510Salexander.borisov@nginx.com return (long) length; 228510Salexander.borisov@nginx.com } 229510Salexander.borisov@nginx.com 230510Salexander.borisov@nginx.com 231510Salexander.borisov@nginx.com static long 232510Salexander.borisov@nginx.com nxt_perl_psgi_io_error_flush(PerlInterpreter *my_perl, 233510Salexander.borisov@nginx.com nxt_perl_psgi_io_arg_t *arg) 234510Salexander.borisov@nginx.com { 235510Salexander.borisov@nginx.com return 0; 236510Salexander.borisov@nginx.com } 237510Salexander.borisov@nginx.com 238510Salexander.borisov@nginx.com 239510Salexander.borisov@nginx.com /* In the future it will be necessary to change some Perl functions. */ 240510Salexander.borisov@nginx.com /* 241510Salexander.borisov@nginx.com static void 242510Salexander.borisov@nginx.com nxt_perl_psgi_xs_core_global_changes(PerlInterpreter *my_perl, 243510Salexander.borisov@nginx.com const char *core, const char *sub, XSUBADDR_t sub_addr) 244510Salexander.borisov@nginx.com { 245510Salexander.borisov@nginx.com GV *gv; 246510Salexander.borisov@nginx.com 247510Salexander.borisov@nginx.com gv = gv_fetchpv(core, TRUE, SVt_PVCV); 248510Salexander.borisov@nginx.com 249510Salexander.borisov@nginx.com #ifdef MUTABLE_CV 250510Salexander.borisov@nginx.com GvCV_set(gv, MUTABLE_CV(SvREFCNT_inc(get_cv(sub, TRUE)))); 251510Salexander.borisov@nginx.com #else 252510Salexander.borisov@nginx.com GvCV_set(gv, (CV *) (SvREFCNT_inc(get_cv(sub, TRUE)))); 253510Salexander.borisov@nginx.com #endif 254510Salexander.borisov@nginx.com GvIMPORTED_CV_on(gv); 255510Salexander.borisov@nginx.com 256510Salexander.borisov@nginx.com newXS(sub, sub_addr, __FILE__); 257510Salexander.borisov@nginx.com } 258510Salexander.borisov@nginx.com */ 259510Salexander.borisov@nginx.com 260510Salexander.borisov@nginx.com 261510Salexander.borisov@nginx.com XS(XS_NGINX__Unit__PSGI_exit); 262510Salexander.borisov@nginx.com XS(XS_NGINX__Unit__PSGI_exit) 263510Salexander.borisov@nginx.com { 264510Salexander.borisov@nginx.com I32 ax = POPMARK; 265510Salexander.borisov@nginx.com Perl_croak(aTHX_ (char *) NULL); 266510Salexander.borisov@nginx.com XSRETURN_EMPTY; 267510Salexander.borisov@nginx.com } 268510Salexander.borisov@nginx.com 269510Salexander.borisov@nginx.com 270510Salexander.borisov@nginx.com static void 271510Salexander.borisov@nginx.com nxt_perl_psgi_xs_init(pTHX) 272510Salexander.borisov@nginx.com { 273510Salexander.borisov@nginx.com /* 274510Salexander.borisov@nginx.com nxt_perl_psgi_xs_core_global_changes(my_perl, "CORE::GLOBAL::exit", 275510Salexander.borisov@nginx.com "NGINX::Unit::PSGI::exit", 276510Salexander.borisov@nginx.com XS_NGINX__Unit__PSGI_exit); 277510Salexander.borisov@nginx.com */ 278510Salexander.borisov@nginx.com nxt_perl_psgi_layer_stream_init(aTHX); 279510Salexander.borisov@nginx.com 280510Salexander.borisov@nginx.com /* DynaLoader for Perl modules who use XS */ 281510Salexander.borisov@nginx.com newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, __FILE__); 282510Salexander.borisov@nginx.com } 283510Salexander.borisov@nginx.com 284510Salexander.borisov@nginx.com 285510Salexander.borisov@nginx.com static SV * 286510Salexander.borisov@nginx.com nxt_perl_psgi_call_var_application(PerlInterpreter *my_perl, 287510Salexander.borisov@nginx.com SV *env, nxt_task_t *task) 288510Salexander.borisov@nginx.com { 289510Salexander.borisov@nginx.com SV *result; 290510Salexander.borisov@nginx.com 291510Salexander.borisov@nginx.com dSP; 292510Salexander.borisov@nginx.com 293510Salexander.borisov@nginx.com ENTER; 294510Salexander.borisov@nginx.com SAVETMPS; 295510Salexander.borisov@nginx.com 296510Salexander.borisov@nginx.com PUSHMARK(sp); 297510Salexander.borisov@nginx.com XPUSHs(env); 298510Salexander.borisov@nginx.com PUTBACK; 299510Salexander.borisov@nginx.com 300510Salexander.borisov@nginx.com call_sv(nxt_perl_psgi_app, G_EVAL|G_SCALAR); 301510Salexander.borisov@nginx.com 302510Salexander.borisov@nginx.com SPAGAIN; 303510Salexander.borisov@nginx.com 304510Salexander.borisov@nginx.com if (SvTRUE(ERRSV)) { 305510Salexander.borisov@nginx.com nxt_log_error(NXT_LOG_ERR, task->log, 306510Salexander.borisov@nginx.com "PSGI: Failed to run Perl Application: \n%s", 307510Salexander.borisov@nginx.com SvPV_nolen(ERRSV)); 308510Salexander.borisov@nginx.com } 309510Salexander.borisov@nginx.com 310510Salexander.borisov@nginx.com result = POPs; 311510Salexander.borisov@nginx.com SvREFCNT_inc(result); 312510Salexander.borisov@nginx.com 313510Salexander.borisov@nginx.com PUTBACK; 314510Salexander.borisov@nginx.com FREETMPS; 315510Salexander.borisov@nginx.com LEAVE; 316510Salexander.borisov@nginx.com 317510Salexander.borisov@nginx.com return result; 318510Salexander.borisov@nginx.com } 319510Salexander.borisov@nginx.com 320510Salexander.borisov@nginx.com 321510Salexander.borisov@nginx.com static u_char * 322510Salexander.borisov@nginx.com nxt_perl_psgi_module_create(nxt_task_t *task, const char *script) 323510Salexander.borisov@nginx.com { 324510Salexander.borisov@nginx.com u_char *buf, *p; 325510Salexander.borisov@nginx.com size_t length; 326510Salexander.borisov@nginx.com 327510Salexander.borisov@nginx.com static nxt_str_t prefix = nxt_string( 328510Salexander.borisov@nginx.com "package NGINX::Unit::Sandbox;" 329510Salexander.borisov@nginx.com "{my $app = do \"" 330510Salexander.borisov@nginx.com ); 331510Salexander.borisov@nginx.com 332510Salexander.borisov@nginx.com static nxt_str_t suffix = nxt_string_zero( 333510Salexander.borisov@nginx.com "\";" 334510Salexander.borisov@nginx.com "unless ($app) {" 335510Salexander.borisov@nginx.com " if($@ || $1) {die $@ || $1}" 336510Salexander.borisov@nginx.com " else {die \"File not found or compilation error.\"}" 337510Salexander.borisov@nginx.com "} " 338510Salexander.borisov@nginx.com "return $app}" 339510Salexander.borisov@nginx.com ); 340510Salexander.borisov@nginx.com 341510Salexander.borisov@nginx.com length = strlen(script); 342510Salexander.borisov@nginx.com 343510Salexander.borisov@nginx.com buf = nxt_malloc(prefix.length + length + suffix.length); 344510Salexander.borisov@nginx.com 345510Salexander.borisov@nginx.com if (nxt_slow_path(buf == NULL)) { 346510Salexander.borisov@nginx.com nxt_log_error(NXT_LOG_ERR, task->log, 347510Salexander.borisov@nginx.com "PSGI: Failed to allocate memory " 348510Salexander.borisov@nginx.com "for Perl script file %s", script); 349510Salexander.borisov@nginx.com return NULL; 350510Salexander.borisov@nginx.com } 351510Salexander.borisov@nginx.com 352510Salexander.borisov@nginx.com p = nxt_cpymem(buf, prefix.start, prefix.length); 353510Salexander.borisov@nginx.com p = nxt_cpymem(p, script, length); 354510Salexander.borisov@nginx.com nxt_memcpy(p, suffix.start, suffix.length); 355510Salexander.borisov@nginx.com 356510Salexander.borisov@nginx.com return buf; 357510Salexander.borisov@nginx.com } 358510Salexander.borisov@nginx.com 359510Salexander.borisov@nginx.com 360510Salexander.borisov@nginx.com static nxt_int_t 361510Salexander.borisov@nginx.com nxt_perl_psgi_io_input_init(PerlInterpreter *my_perl, 362510Salexander.borisov@nginx.com nxt_perl_psgi_io_arg_t *arg) 363510Salexander.borisov@nginx.com { 364510Salexander.borisov@nginx.com SV *io; 365510Salexander.borisov@nginx.com PerlIO *fp; 366510Salexander.borisov@nginx.com 367510Salexander.borisov@nginx.com fp = nxt_perl_psgi_layer_stream_fp_create(aTHX_ arg, "r"); 368510Salexander.borisov@nginx.com 369510Salexander.borisov@nginx.com if (nxt_slow_path(fp == NULL)) { 370510Salexander.borisov@nginx.com return NXT_ERROR; 371510Salexander.borisov@nginx.com } 372510Salexander.borisov@nginx.com 373510Salexander.borisov@nginx.com io = nxt_perl_psgi_layer_stream_io_create(aTHX_ fp); 374510Salexander.borisov@nginx.com 375510Salexander.borisov@nginx.com if (nxt_slow_path(io == NULL)) { 376510Salexander.borisov@nginx.com nxt_perl_psgi_layer_stream_fp_destroy(aTHX_ fp); 377510Salexander.borisov@nginx.com return NXT_ERROR; 378510Salexander.borisov@nginx.com } 379510Salexander.borisov@nginx.com 380510Salexander.borisov@nginx.com arg->io = io; 381510Salexander.borisov@nginx.com arg->fp = fp; 382510Salexander.borisov@nginx.com arg->flush = nxt_perl_psgi_io_input_flush; 383510Salexander.borisov@nginx.com arg->read = nxt_perl_psgi_io_input_read; 384510Salexander.borisov@nginx.com arg->write = nxt_perl_psgi_io_input_write; 385510Salexander.borisov@nginx.com 386510Salexander.borisov@nginx.com return NXT_OK; 387510Salexander.borisov@nginx.com } 388510Salexander.borisov@nginx.com 389510Salexander.borisov@nginx.com 390510Salexander.borisov@nginx.com static nxt_int_t 391510Salexander.borisov@nginx.com nxt_perl_psgi_io_error_init(PerlInterpreter *my_perl, 392510Salexander.borisov@nginx.com nxt_perl_psgi_io_arg_t *arg) 393510Salexander.borisov@nginx.com { 394510Salexander.borisov@nginx.com SV *io; 395510Salexander.borisov@nginx.com PerlIO *fp; 396510Salexander.borisov@nginx.com 397510Salexander.borisov@nginx.com fp = nxt_perl_psgi_layer_stream_fp_create(aTHX_ arg, "w"); 398510Salexander.borisov@nginx.com 399510Salexander.borisov@nginx.com if (nxt_slow_path(fp == NULL)) { 400510Salexander.borisov@nginx.com return NXT_ERROR; 401510Salexander.borisov@nginx.com } 402510Salexander.borisov@nginx.com 403510Salexander.borisov@nginx.com io = nxt_perl_psgi_layer_stream_io_create(aTHX_ fp); 404510Salexander.borisov@nginx.com 405510Salexander.borisov@nginx.com if (nxt_slow_path(io == NULL)) { 406510Salexander.borisov@nginx.com nxt_perl_psgi_layer_stream_fp_destroy(aTHX_ fp); 407510Salexander.borisov@nginx.com return NXT_ERROR; 408510Salexander.borisov@nginx.com } 409510Salexander.borisov@nginx.com 410510Salexander.borisov@nginx.com arg->io = io; 411510Salexander.borisov@nginx.com arg->fp = fp; 412510Salexander.borisov@nginx.com arg->flush = nxt_perl_psgi_io_error_flush; 413510Salexander.borisov@nginx.com arg->read = nxt_perl_psgi_io_error_read; 414510Salexander.borisov@nginx.com arg->write = nxt_perl_psgi_io_error_write; 415510Salexander.borisov@nginx.com 416510Salexander.borisov@nginx.com return NXT_OK; 417510Salexander.borisov@nginx.com } 418510Salexander.borisov@nginx.com 419510Salexander.borisov@nginx.com 420510Salexander.borisov@nginx.com static PerlInterpreter * 421510Salexander.borisov@nginx.com nxt_perl_psgi_interpreter_init(nxt_task_t *task, char *script) 422510Salexander.borisov@nginx.com { 423510Salexander.borisov@nginx.com int status, pargc; 424510Salexander.borisov@nginx.com char **pargv, **penv; 425510Salexander.borisov@nginx.com u_char *run_module; 426510Salexander.borisov@nginx.com PerlInterpreter *my_perl; 427510Salexander.borisov@nginx.com 428510Salexander.borisov@nginx.com static char argv[] = "\0""-e\0""0"; 429510Salexander.borisov@nginx.com static char *embedding[] = { &argv[0], &argv[1], &argv[4] }; 430510Salexander.borisov@nginx.com 431510Salexander.borisov@nginx.com pargc = 0; 432510Salexander.borisov@nginx.com pargv = NULL; 433510Salexander.borisov@nginx.com penv = NULL; 434510Salexander.borisov@nginx.com 435510Salexander.borisov@nginx.com PERL_SYS_INIT3(&pargc, &pargv, &penv); 436510Salexander.borisov@nginx.com 437510Salexander.borisov@nginx.com my_perl = perl_alloc(); 438510Salexander.borisov@nginx.com 439510Salexander.borisov@nginx.com if (nxt_slow_path(my_perl == NULL)) { 440564Svbart@nginx.com nxt_alert(task, "PSGI: Failed to allocate memory for Perl interpreter"); 441510Salexander.borisov@nginx.com return NULL; 442510Salexander.borisov@nginx.com } 443510Salexander.borisov@nginx.com 444510Salexander.borisov@nginx.com run_module = NULL; 445510Salexander.borisov@nginx.com 446510Salexander.borisov@nginx.com perl_construct(my_perl); 447510Salexander.borisov@nginx.com PERL_SET_CONTEXT(my_perl); 448510Salexander.borisov@nginx.com 449510Salexander.borisov@nginx.com status = perl_parse(my_perl, nxt_perl_psgi_xs_init, 3, embedding, NULL); 450510Salexander.borisov@nginx.com 451510Salexander.borisov@nginx.com if (nxt_slow_path(status != 0)) { 452564Svbart@nginx.com nxt_alert(task, "PSGI: Failed to parse Perl Script"); 453510Salexander.borisov@nginx.com goto fail; 454510Salexander.borisov@nginx.com } 455510Salexander.borisov@nginx.com 456510Salexander.borisov@nginx.com PL_exit_flags |= PERL_EXIT_DESTRUCT_END; 457510Salexander.borisov@nginx.com PL_origalen = 1; 458510Salexander.borisov@nginx.com 459510Salexander.borisov@nginx.com status = perl_run(my_perl); 460510Salexander.borisov@nginx.com 461510Salexander.borisov@nginx.com if (nxt_slow_path(status != 0)) { 462564Svbart@nginx.com nxt_alert(task, "PSGI: Failed to run Perl"); 463510Salexander.borisov@nginx.com goto fail; 464510Salexander.borisov@nginx.com } 465510Salexander.borisov@nginx.com 466510Salexander.borisov@nginx.com sv_setsv(get_sv("0", 0), newSVpv(script, 0)); 467510Salexander.borisov@nginx.com 468510Salexander.borisov@nginx.com run_module = nxt_perl_psgi_module_create(task, script); 469510Salexander.borisov@nginx.com 470510Salexander.borisov@nginx.com if (nxt_slow_path(run_module == NULL)) { 471510Salexander.borisov@nginx.com goto fail; 472510Salexander.borisov@nginx.com } 473510Salexander.borisov@nginx.com 474510Salexander.borisov@nginx.com status = nxt_perl_psgi_io_input_init(my_perl, &nxt_perl_psgi_arg_input); 475510Salexander.borisov@nginx.com 476510Salexander.borisov@nginx.com if (nxt_slow_path(status != NXT_OK)) { 477564Svbart@nginx.com nxt_alert(task, "PSGI: Failed to init io.psgi.input"); 478510Salexander.borisov@nginx.com goto fail; 479510Salexander.borisov@nginx.com } 480510Salexander.borisov@nginx.com 481510Salexander.borisov@nginx.com status = nxt_perl_psgi_io_error_init(my_perl, &nxt_perl_psgi_arg_error); 482510Salexander.borisov@nginx.com 483510Salexander.borisov@nginx.com if (nxt_slow_path(status != NXT_OK)) { 484564Svbart@nginx.com nxt_alert(task, "PSGI: Failed to init io.psgi.errors"); 485510Salexander.borisov@nginx.com goto fail; 486510Salexander.borisov@nginx.com } 487510Salexander.borisov@nginx.com 488510Salexander.borisov@nginx.com nxt_perl_psgi_app = eval_pv((const char *) run_module, FALSE); 489510Salexander.borisov@nginx.com 490510Salexander.borisov@nginx.com if (SvTRUE(ERRSV)) { 491564Svbart@nginx.com nxt_alert(task, "PSGI: Failed to parse script: %s\n%s", 492564Svbart@nginx.com script, SvPV_nolen(ERRSV)); 493510Salexander.borisov@nginx.com goto fail; 494510Salexander.borisov@nginx.com } 495510Salexander.borisov@nginx.com 496510Salexander.borisov@nginx.com nxt_free(run_module); 497510Salexander.borisov@nginx.com 498510Salexander.borisov@nginx.com return my_perl; 499510Salexander.borisov@nginx.com 500510Salexander.borisov@nginx.com fail: 501510Salexander.borisov@nginx.com 502510Salexander.borisov@nginx.com if (run_module != NULL) { 503510Salexander.borisov@nginx.com nxt_free(run_module); 504510Salexander.borisov@nginx.com } 505510Salexander.borisov@nginx.com 506510Salexander.borisov@nginx.com perl_destruct(my_perl); 507510Salexander.borisov@nginx.com perl_free(my_perl); 508510Salexander.borisov@nginx.com PERL_SYS_TERM(); 509510Salexander.borisov@nginx.com 510510Salexander.borisov@nginx.com return NULL; 511510Salexander.borisov@nginx.com } 512510Salexander.borisov@nginx.com 513510Salexander.borisov@nginx.com 514510Salexander.borisov@nginx.com nxt_inline nxt_int_t 515510Salexander.borisov@nginx.com nxt_perl_psgi_env_append_str(PerlInterpreter *my_perl, HV *hash_env, 516510Salexander.borisov@nginx.com const char *name, nxt_str_t *str) 517510Salexander.borisov@nginx.com { 518510Salexander.borisov@nginx.com SV **ha; 519510Salexander.borisov@nginx.com 520510Salexander.borisov@nginx.com ha = hv_store(hash_env, name, (I32) strlen(name), 521521Szelenkov@nginx.com newSVpv((const char *) str->start, (STRLEN) str->length), 0); 522510Salexander.borisov@nginx.com 523510Salexander.borisov@nginx.com if (nxt_slow_path(ha == NULL)) { 524510Salexander.borisov@nginx.com return NXT_ERROR; 525510Salexander.borisov@nginx.com } 526510Salexander.borisov@nginx.com 527510Salexander.borisov@nginx.com return NXT_OK; 528510Salexander.borisov@nginx.com } 529510Salexander.borisov@nginx.com 530510Salexander.borisov@nginx.com 531510Salexander.borisov@nginx.com nxt_inline nxt_int_t 532510Salexander.borisov@nginx.com nxt_perl_psgi_env_append(PerlInterpreter *my_perl, HV *hash_env, 533510Salexander.borisov@nginx.com const char *name, void *value) 534510Salexander.borisov@nginx.com { 535510Salexander.borisov@nginx.com SV **ha; 536510Salexander.borisov@nginx.com 537510Salexander.borisov@nginx.com ha = hv_store(hash_env, name, (I32) strlen(name), value, 0); 538510Salexander.borisov@nginx.com 539510Salexander.borisov@nginx.com if (nxt_slow_path(ha == NULL)) { 540510Salexander.borisov@nginx.com return NXT_ERROR; 541510Salexander.borisov@nginx.com } 542510Salexander.borisov@nginx.com 543510Salexander.borisov@nginx.com return NXT_OK; 544510Salexander.borisov@nginx.com } 545510Salexander.borisov@nginx.com 546510Salexander.borisov@nginx.com 547510Salexander.borisov@nginx.com nxt_inline nxt_int_t 548510Salexander.borisov@nginx.com nxt_perl_psgi_read_add_env(PerlInterpreter *my_perl, nxt_task_t *task, 549510Salexander.borisov@nginx.com nxt_app_rmsg_t *rmsg, HV *hash_env, 550510Salexander.borisov@nginx.com const char *name, nxt_str_t *str) 551510Salexander.borisov@nginx.com { 552510Salexander.borisov@nginx.com nxt_int_t rc; 553510Salexander.borisov@nginx.com 554510Salexander.borisov@nginx.com rc = nxt_app_msg_read_str(task, rmsg, str); 555510Salexander.borisov@nginx.com 556510Salexander.borisov@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 557510Salexander.borisov@nginx.com return rc; 558510Salexander.borisov@nginx.com } 559510Salexander.borisov@nginx.com 560510Salexander.borisov@nginx.com if (str->start == NULL) { 561510Salexander.borisov@nginx.com return NXT_OK; 562510Salexander.borisov@nginx.com } 563510Salexander.borisov@nginx.com 564510Salexander.borisov@nginx.com return nxt_perl_psgi_env_append_str(my_perl, hash_env, name, str); 565510Salexander.borisov@nginx.com } 566510Salexander.borisov@nginx.com 567510Salexander.borisov@nginx.com 568510Salexander.borisov@nginx.com static SV * 569510Salexander.borisov@nginx.com nxt_perl_psgi_env_create(PerlInterpreter *my_perl, nxt_task_t *task, 570510Salexander.borisov@nginx.com nxt_app_rmsg_t *rmsg, size_t *body_preread_size) 571510Salexander.borisov@nginx.com { 572510Salexander.borisov@nginx.com HV *hash_env; 573510Salexander.borisov@nginx.com AV *array_version; 574510Salexander.borisov@nginx.com u_char *colon; 575510Salexander.borisov@nginx.com size_t query_size; 576510Salexander.borisov@nginx.com nxt_int_t rc; 577510Salexander.borisov@nginx.com nxt_str_t str, value, path, target; 578510Salexander.borisov@nginx.com nxt_str_t host, server_name, server_port; 579510Salexander.borisov@nginx.com 580510Salexander.borisov@nginx.com static nxt_str_t def_host = nxt_string("localhost"); 581510Salexander.borisov@nginx.com static nxt_str_t def_port = nxt_string("80"); 582510Salexander.borisov@nginx.com 583510Salexander.borisov@nginx.com hash_env = newHV(); 584510Salexander.borisov@nginx.com 585510Salexander.borisov@nginx.com if (nxt_slow_path(hash_env == NULL)) { 586510Salexander.borisov@nginx.com return NULL; 587510Salexander.borisov@nginx.com } 588510Salexander.borisov@nginx.com 589510Salexander.borisov@nginx.com #define RC(FNS) \ 590510Salexander.borisov@nginx.com do { \ 591510Salexander.borisov@nginx.com if (nxt_slow_path((FNS) != NXT_OK)) \ 592510Salexander.borisov@nginx.com goto fail; \ 593510Salexander.borisov@nginx.com } while (0) 594510Salexander.borisov@nginx.com 595510Salexander.borisov@nginx.com #define GET_STR(ATTR) \ 596510Salexander.borisov@nginx.com RC(nxt_perl_psgi_read_add_env(my_perl, task, rmsg, \ 597510Salexander.borisov@nginx.com hash_env, ATTR, &str)) 598510Salexander.borisov@nginx.com 599510Salexander.borisov@nginx.com GET_STR("REQUEST_METHOD"); 600510Salexander.borisov@nginx.com GET_STR("REQUEST_URI"); 601510Salexander.borisov@nginx.com 602510Salexander.borisov@nginx.com target = str; 603510Salexander.borisov@nginx.com 604510Salexander.borisov@nginx.com RC(nxt_app_msg_read_str(task, rmsg, &path)); 605510Salexander.borisov@nginx.com RC(nxt_app_msg_read_size(task, rmsg, &query_size)); 606510Salexander.borisov@nginx.com 607510Salexander.borisov@nginx.com if (path.start == NULL || path.length == 0) { 608510Salexander.borisov@nginx.com path = target; 609510Salexander.borisov@nginx.com } 610510Salexander.borisov@nginx.com 611580Salexander.borisov@nginx.com RC(nxt_perl_psgi_env_append_str(my_perl, hash_env, "PATH_INFO", 612580Salexander.borisov@nginx.com &path)); 613580Salexander.borisov@nginx.com 614510Salexander.borisov@nginx.com array_version = newAV(); 615510Salexander.borisov@nginx.com 616510Salexander.borisov@nginx.com if (nxt_slow_path(array_version == NULL)) { 617510Salexander.borisov@nginx.com goto fail; 618510Salexander.borisov@nginx.com } 619510Salexander.borisov@nginx.com 620510Salexander.borisov@nginx.com av_push(array_version, newSViv(1)); 621510Salexander.borisov@nginx.com av_push(array_version, newSViv(1)); 622510Salexander.borisov@nginx.com 623580Salexander.borisov@nginx.com RC(nxt_perl_psgi_env_append(my_perl, hash_env, "psgi.version", 624580Salexander.borisov@nginx.com newRV_noinc((SV *) array_version))); 625510Salexander.borisov@nginx.com RC(nxt_perl_psgi_env_append(my_perl, hash_env, "psgi.url_scheme", 626510Salexander.borisov@nginx.com newSVpv("http", 4))); 627510Salexander.borisov@nginx.com RC(nxt_perl_psgi_env_append(my_perl, hash_env, "psgi.input", 628510Salexander.borisov@nginx.com SvREFCNT_inc(nxt_perl_psgi_arg_input.io))); 629510Salexander.borisov@nginx.com RC(nxt_perl_psgi_env_append(my_perl, hash_env, "psgi.errors", 630510Salexander.borisov@nginx.com SvREFCNT_inc(nxt_perl_psgi_arg_error.io))); 631580Salexander.borisov@nginx.com RC(nxt_perl_psgi_env_append(my_perl, hash_env, "psgi.multithread", 632580Salexander.borisov@nginx.com &PL_sv_no)); 633580Salexander.borisov@nginx.com RC(nxt_perl_psgi_env_append(my_perl, hash_env, "psgi.multiprocess", 634580Salexander.borisov@nginx.com &PL_sv_yes)); 635580Salexander.borisov@nginx.com RC(nxt_perl_psgi_env_append(my_perl, hash_env, "psgi.run_once", 636580Salexander.borisov@nginx.com &PL_sv_no)); 637580Salexander.borisov@nginx.com RC(nxt_perl_psgi_env_append(my_perl, hash_env, "psgi.nonblocking", 638580Salexander.borisov@nginx.com &PL_sv_no)); 639580Salexander.borisov@nginx.com RC(nxt_perl_psgi_env_append(my_perl, hash_env, "psgi.streaming", 640580Salexander.borisov@nginx.com &PL_sv_no)); 641510Salexander.borisov@nginx.com 642510Salexander.borisov@nginx.com if (query_size > 0) { 643510Salexander.borisov@nginx.com query_size--; 644510Salexander.borisov@nginx.com 645510Salexander.borisov@nginx.com if (nxt_slow_path(target.length < query_size)) { 646510Salexander.borisov@nginx.com goto fail; 647510Salexander.borisov@nginx.com } 648510Salexander.borisov@nginx.com 649510Salexander.borisov@nginx.com str.start = &target.start[query_size]; 650510Salexander.borisov@nginx.com str.length = target.length - query_size; 651510Salexander.borisov@nginx.com 652510Salexander.borisov@nginx.com RC(nxt_perl_psgi_env_append_str(my_perl, hash_env, 653510Salexander.borisov@nginx.com "QUERY_STRING", &str)); 654510Salexander.borisov@nginx.com } 655510Salexander.borisov@nginx.com 656510Salexander.borisov@nginx.com GET_STR("SERVER_PROTOCOL"); 657510Salexander.borisov@nginx.com GET_STR("REMOTE_ADDR"); 658510Salexander.borisov@nginx.com GET_STR("SERVER_ADDR"); 659510Salexander.borisov@nginx.com 660510Salexander.borisov@nginx.com RC(nxt_app_msg_read_str(task, rmsg, &host)); 661510Salexander.borisov@nginx.com 662510Salexander.borisov@nginx.com if (host.length == 0) { 663510Salexander.borisov@nginx.com host = def_host; 664510Salexander.borisov@nginx.com } 665510Salexander.borisov@nginx.com 666510Salexander.borisov@nginx.com colon = nxt_memchr(host.start, ':', host.length); 667510Salexander.borisov@nginx.com server_name = host; 668510Salexander.borisov@nginx.com 669510Salexander.borisov@nginx.com if (colon != NULL) { 670510Salexander.borisov@nginx.com server_name.length = colon - host.start; 671510Salexander.borisov@nginx.com 672510Salexander.borisov@nginx.com server_port.start = colon + 1; 673510Salexander.borisov@nginx.com server_port.length = host.length - server_name.length - 1; 674510Salexander.borisov@nginx.com 675510Salexander.borisov@nginx.com } else { 676510Salexander.borisov@nginx.com server_port = def_port; 677510Salexander.borisov@nginx.com } 678510Salexander.borisov@nginx.com 679510Salexander.borisov@nginx.com RC(nxt_perl_psgi_env_append_str(my_perl, hash_env, 680510Salexander.borisov@nginx.com "SERVER_NAME", &server_name)); 681510Salexander.borisov@nginx.com RC(nxt_perl_psgi_env_append_str(my_perl, hash_env, 682510Salexander.borisov@nginx.com "SERVER_PORT", &server_port)); 683510Salexander.borisov@nginx.com 684510Salexander.borisov@nginx.com GET_STR("CONTENT_TYPE"); 685510Salexander.borisov@nginx.com GET_STR("CONTENT_LENGTH"); 686510Salexander.borisov@nginx.com 687510Salexander.borisov@nginx.com for ( ;; ) { 688510Salexander.borisov@nginx.com rc = nxt_app_msg_read_str(task, rmsg, &str); 689510Salexander.borisov@nginx.com 690510Salexander.borisov@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 691510Salexander.borisov@nginx.com goto fail; 692510Salexander.borisov@nginx.com } 693510Salexander.borisov@nginx.com 694510Salexander.borisov@nginx.com if (nxt_slow_path(str.length == 0)) { 695510Salexander.borisov@nginx.com break; 696510Salexander.borisov@nginx.com } 697510Salexander.borisov@nginx.com 698510Salexander.borisov@nginx.com rc = nxt_app_msg_read_str(task, rmsg, &value); 699510Salexander.borisov@nginx.com 700510Salexander.borisov@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 701510Salexander.borisov@nginx.com break; 702510Salexander.borisov@nginx.com } 703510Salexander.borisov@nginx.com 704510Salexander.borisov@nginx.com RC(nxt_perl_psgi_env_append_str(my_perl, hash_env, 705510Salexander.borisov@nginx.com (char *) str.start, &value)); 706510Salexander.borisov@nginx.com } 707510Salexander.borisov@nginx.com 708510Salexander.borisov@nginx.com RC(nxt_app_msg_read_size(task, rmsg, body_preread_size)); 709510Salexander.borisov@nginx.com 710510Salexander.borisov@nginx.com #undef GET_STR 711510Salexander.borisov@nginx.com #undef RC 712510Salexander.borisov@nginx.com 713510Salexander.borisov@nginx.com return newRV_noinc((SV *) hash_env); 714510Salexander.borisov@nginx.com 715510Salexander.borisov@nginx.com fail: 716510Salexander.borisov@nginx.com 717510Salexander.borisov@nginx.com SvREFCNT_dec(hash_env); 718510Salexander.borisov@nginx.com 719510Salexander.borisov@nginx.com return NULL; 720510Salexander.borisov@nginx.com } 721510Salexander.borisov@nginx.com 722510Salexander.borisov@nginx.com 723510Salexander.borisov@nginx.com static nxt_str_t 724510Salexander.borisov@nginx.com nxt_perl_psgi_result_status(PerlInterpreter *my_perl, SV *result) 725510Salexander.borisov@nginx.com { 726510Salexander.borisov@nginx.com SV **sv_status; 727510Salexander.borisov@nginx.com AV *array; 728510Salexander.borisov@nginx.com nxt_str_t status; 729510Salexander.borisov@nginx.com 730510Salexander.borisov@nginx.com array = (AV *) SvRV(result); 731510Salexander.borisov@nginx.com sv_status = av_fetch(array, 0, 0); 732510Salexander.borisov@nginx.com 733510Salexander.borisov@nginx.com status.start = (u_char *) SvPV(*sv_status, status.length); 734510Salexander.borisov@nginx.com 735510Salexander.borisov@nginx.com return status; 736510Salexander.borisov@nginx.com } 737510Salexander.borisov@nginx.com 738510Salexander.borisov@nginx.com 739510Salexander.borisov@nginx.com static nxt_int_t 740510Salexander.borisov@nginx.com nxt_perl_psgi_result_head(PerlInterpreter *my_perl, SV *sv_head, 741510Salexander.borisov@nginx.com nxt_task_t *task, nxt_app_wmsg_t *wmsg) 742510Salexander.borisov@nginx.com { 743510Salexander.borisov@nginx.com AV *array_head; 744510Salexander.borisov@nginx.com SV **entry; 745510Salexander.borisov@nginx.com long i, array_len; 746510Salexander.borisov@nginx.com nxt_int_t rc; 747510Salexander.borisov@nginx.com nxt_str_t body; 748510Salexander.borisov@nginx.com 749510Salexander.borisov@nginx.com if (nxt_slow_path(SvROK(sv_head) == 0 750510Salexander.borisov@nginx.com || SvTYPE(SvRV(sv_head)) != SVt_PVAV)) 751510Salexander.borisov@nginx.com { 752510Salexander.borisov@nginx.com nxt_log_error(NXT_LOG_ERR, task->log, 753510Salexander.borisov@nginx.com "PSGI: An unsupported format was received from " 754510Salexander.borisov@nginx.com "Perl Application for head part"); 755510Salexander.borisov@nginx.com 756510Salexander.borisov@nginx.com return NXT_ERROR; 757510Salexander.borisov@nginx.com } 758510Salexander.borisov@nginx.com 759510Salexander.borisov@nginx.com array_head = (AV *) SvRV(sv_head); 760510Salexander.borisov@nginx.com array_len = av_len(array_head); 761510Salexander.borisov@nginx.com 762510Salexander.borisov@nginx.com if (array_len < 1) { 763510Salexander.borisov@nginx.com return NXT_OK; 764510Salexander.borisov@nginx.com } 765510Salexander.borisov@nginx.com 766510Salexander.borisov@nginx.com if (nxt_slow_path((array_len % 2) == 0)) { 767510Salexander.borisov@nginx.com nxt_log_error(NXT_LOG_ERR, task->log, 768510Salexander.borisov@nginx.com "PSGI: Bad format for head from " 769510Salexander.borisov@nginx.com "Perl Application"); 770510Salexander.borisov@nginx.com 771510Salexander.borisov@nginx.com return NXT_ERROR; 772510Salexander.borisov@nginx.com } 773510Salexander.borisov@nginx.com 774510Salexander.borisov@nginx.com for (i = 0; i <= array_len; i++) { 775510Salexander.borisov@nginx.com entry = av_fetch(array_head, i, 0); 776510Salexander.borisov@nginx.com 777510Salexander.borisov@nginx.com if (nxt_fast_path(entry == NULL)) { 778510Salexander.borisov@nginx.com nxt_log_error(NXT_LOG_ERR, task->log, 779510Salexander.borisov@nginx.com "PSGI: Failed to get head entry from " 780510Salexander.borisov@nginx.com "Perl Application"); 781510Salexander.borisov@nginx.com 782510Salexander.borisov@nginx.com return NXT_ERROR; 783510Salexander.borisov@nginx.com } 784510Salexander.borisov@nginx.com 785510Salexander.borisov@nginx.com body.start = (u_char *) SvPV(*entry, body.length); 786510Salexander.borisov@nginx.com 787510Salexander.borisov@nginx.com rc = nxt_app_msg_write_raw(task, wmsg, 788510Salexander.borisov@nginx.com (u_char *) body.start, body.length); 789510Salexander.borisov@nginx.com 790510Salexander.borisov@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 791510Salexander.borisov@nginx.com nxt_log_error(NXT_LOG_ERR, task->log, 792510Salexander.borisov@nginx.com "PSGI: Failed to write head " 793510Salexander.borisov@nginx.com "from Perl Application"); 794510Salexander.borisov@nginx.com return rc; 795510Salexander.borisov@nginx.com } 796510Salexander.borisov@nginx.com 797510Salexander.borisov@nginx.com if ((i % 2) == 0) { 798510Salexander.borisov@nginx.com rc = nxt_app_msg_write_raw(task, wmsg, 799510Salexander.borisov@nginx.com (u_char *) ": ", 800510Salexander.borisov@nginx.com (sizeof(": ") - 1)); 801510Salexander.borisov@nginx.com } else { 802510Salexander.borisov@nginx.com rc = nxt_app_msg_write_raw(task, wmsg, 803510Salexander.borisov@nginx.com (u_char *) "\r\n", 804510Salexander.borisov@nginx.com (sizeof("\r\n") - 1)); 805510Salexander.borisov@nginx.com } 806510Salexander.borisov@nginx.com 807510Salexander.borisov@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 808510Salexander.borisov@nginx.com nxt_log_error(NXT_LOG_ERR, task->log, 809510Salexander.borisov@nginx.com "PSGI: Failed to write head from " 810510Salexander.borisov@nginx.com "Perl Application"); 811510Salexander.borisov@nginx.com return rc; 812510Salexander.borisov@nginx.com } 813510Salexander.borisov@nginx.com } 814510Salexander.borisov@nginx.com 815510Salexander.borisov@nginx.com return NXT_OK; 816510Salexander.borisov@nginx.com } 817510Salexander.borisov@nginx.com 818510Salexander.borisov@nginx.com 819510Salexander.borisov@nginx.com static nxt_int_t 820510Salexander.borisov@nginx.com nxt_perl_psgi_result_body(PerlInterpreter *my_perl, SV *sv_body, 821510Salexander.borisov@nginx.com nxt_task_t *task, nxt_app_wmsg_t *wmsg) 822510Salexander.borisov@nginx.com { 823510Salexander.borisov@nginx.com SV **entry; 824510Salexander.borisov@nginx.com AV *body_array; 825510Salexander.borisov@nginx.com long i; 826510Salexander.borisov@nginx.com nxt_int_t rc; 827510Salexander.borisov@nginx.com nxt_str_t body; 828510Salexander.borisov@nginx.com 829510Salexander.borisov@nginx.com if (nxt_slow_path(SvROK(sv_body) == 0 830510Salexander.borisov@nginx.com || SvTYPE(SvRV(sv_body)) != SVt_PVAV)) 831510Salexander.borisov@nginx.com { 832510Salexander.borisov@nginx.com nxt_log_error(NXT_LOG_ERR, task->log, 833510Salexander.borisov@nginx.com "PSGI: An unsupported format was received from " 834510Salexander.borisov@nginx.com "Perl Application for a body part"); 835510Salexander.borisov@nginx.com 836510Salexander.borisov@nginx.com return NXT_ERROR; 837510Salexander.borisov@nginx.com } 838510Salexander.borisov@nginx.com 839510Salexander.borisov@nginx.com body_array = (AV *) SvRV(sv_body); 840510Salexander.borisov@nginx.com 841510Salexander.borisov@nginx.com for (i = 0; i <= av_len(body_array); i++) { 842510Salexander.borisov@nginx.com 843510Salexander.borisov@nginx.com entry = av_fetch(body_array, i, 0); 844510Salexander.borisov@nginx.com 845510Salexander.borisov@nginx.com if (nxt_fast_path(entry == NULL)) { 846510Salexander.borisov@nginx.com nxt_log_error(NXT_LOG_ERR, task->log, 847510Salexander.borisov@nginx.com "PSGI: Failed to get body entry from " 848510Salexander.borisov@nginx.com "Perl Application"); 849510Salexander.borisov@nginx.com return NXT_ERROR; 850510Salexander.borisov@nginx.com } 851510Salexander.borisov@nginx.com 852510Salexander.borisov@nginx.com body.start = (u_char *) SvPV(*entry, body.length); 853510Salexander.borisov@nginx.com 854510Salexander.borisov@nginx.com if (body.length == 0) { 855510Salexander.borisov@nginx.com continue; 856510Salexander.borisov@nginx.com } 857510Salexander.borisov@nginx.com 858510Salexander.borisov@nginx.com rc = nxt_app_msg_write_raw(task, wmsg, 859510Salexander.borisov@nginx.com (u_char *) body.start, body.length); 860510Salexander.borisov@nginx.com 861510Salexander.borisov@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 862510Salexander.borisov@nginx.com nxt_log_error(NXT_LOG_ERR, task->log, 863510Salexander.borisov@nginx.com "PSGI: Failed to write 'body' from " 864510Salexander.borisov@nginx.com "Perl Application"); 865510Salexander.borisov@nginx.com return rc; 866510Salexander.borisov@nginx.com } 867510Salexander.borisov@nginx.com 868510Salexander.borisov@nginx.com rc = nxt_app_msg_flush(task, wmsg, 0); 869510Salexander.borisov@nginx.com 870510Salexander.borisov@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 871510Salexander.borisov@nginx.com nxt_log_error(NXT_LOG_ERR, task->log, 872510Salexander.borisov@nginx.com "PSGI: Failed to flush data for a 'body' " 873510Salexander.borisov@nginx.com "part from Perl Application"); 874510Salexander.borisov@nginx.com return rc; 875510Salexander.borisov@nginx.com } 876510Salexander.borisov@nginx.com } 877510Salexander.borisov@nginx.com 878510Salexander.borisov@nginx.com return NXT_OK; 879510Salexander.borisov@nginx.com } 880510Salexander.borisov@nginx.com 881510Salexander.borisov@nginx.com 882510Salexander.borisov@nginx.com static nxt_int_t 883510Salexander.borisov@nginx.com nxt_perl_psgi_result_body_ref(PerlInterpreter *my_perl, SV *sv_body, 884510Salexander.borisov@nginx.com nxt_task_t *task, nxt_app_wmsg_t *wmsg) 885510Salexander.borisov@nginx.com { 886510Salexander.borisov@nginx.com IO *io; 887510Salexander.borisov@nginx.com PerlIO *fp; 888510Salexander.borisov@nginx.com SSize_t n; 889510Salexander.borisov@nginx.com nxt_int_t rc; 890510Salexander.borisov@nginx.com u_char vbuf[8192]; 891510Salexander.borisov@nginx.com 892510Salexander.borisov@nginx.com io = GvIO(SvRV(sv_body)); 893519Salexander.borisov@nginx.com 894519Salexander.borisov@nginx.com if (io == NULL) { 895519Salexander.borisov@nginx.com return NXT_OK; 896519Salexander.borisov@nginx.com } 897519Salexander.borisov@nginx.com 898510Salexander.borisov@nginx.com fp = IoIFP(io); 899510Salexander.borisov@nginx.com 900510Salexander.borisov@nginx.com for ( ;; ) { 901510Salexander.borisov@nginx.com n = PerlIO_read(fp, vbuf, 8192); 902510Salexander.borisov@nginx.com 903510Salexander.borisov@nginx.com if (n < 1) { 904510Salexander.borisov@nginx.com break; 905510Salexander.borisov@nginx.com } 906510Salexander.borisov@nginx.com 907510Salexander.borisov@nginx.com rc = nxt_app_msg_write_raw(task, wmsg, 908510Salexander.borisov@nginx.com (u_char *) vbuf, (size_t) n); 909510Salexander.borisov@nginx.com 910510Salexander.borisov@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 911510Salexander.borisov@nginx.com nxt_log_error(NXT_LOG_ERR, task->log, 912510Salexander.borisov@nginx.com "PSGI: Failed to write 'body' from " 913510Salexander.borisov@nginx.com "Perl Application"); 914510Salexander.borisov@nginx.com 915510Salexander.borisov@nginx.com return rc; 916510Salexander.borisov@nginx.com } 917510Salexander.borisov@nginx.com 918510Salexander.borisov@nginx.com rc = nxt_app_msg_flush(task, wmsg, 0); 919510Salexander.borisov@nginx.com 920510Salexander.borisov@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 921510Salexander.borisov@nginx.com nxt_log_error(NXT_LOG_ERR, task->log, 922510Salexander.borisov@nginx.com "PSGI: Failed to flush data for a body " 923510Salexander.borisov@nginx.com "part from Perl Application"); 924510Salexander.borisov@nginx.com 925510Salexander.borisov@nginx.com return rc; 926510Salexander.borisov@nginx.com } 927510Salexander.borisov@nginx.com } 928510Salexander.borisov@nginx.com 929510Salexander.borisov@nginx.com return NXT_OK; 930510Salexander.borisov@nginx.com } 931510Salexander.borisov@nginx.com 932510Salexander.borisov@nginx.com 933510Salexander.borisov@nginx.com static nxt_int_t 934510Salexander.borisov@nginx.com nxt_perl_psgi_result_array(PerlInterpreter *my_perl, SV *result, 935510Salexander.borisov@nginx.com nxt_task_t *task, nxt_app_wmsg_t *wmsg) 936510Salexander.borisov@nginx.com { 937510Salexander.borisov@nginx.com AV *array; 938510Salexander.borisov@nginx.com SV **sv_temp; 939510Salexander.borisov@nginx.com long array_len; 940510Salexander.borisov@nginx.com nxt_int_t rc; 941510Salexander.borisov@nginx.com nxt_str_t http_status; 942510Salexander.borisov@nginx.com 943510Salexander.borisov@nginx.com array = (AV *) SvRV(result); 944510Salexander.borisov@nginx.com array_len = av_len(array); 945510Salexander.borisov@nginx.com 946510Salexander.borisov@nginx.com if (nxt_slow_path(array_len < 0)) { 947510Salexander.borisov@nginx.com nxt_log_error(NXT_LOG_ERR, task->log, 948510Salexander.borisov@nginx.com "PSGI: Invalid result format from Perl Application"); 949510Salexander.borisov@nginx.com 950510Salexander.borisov@nginx.com return NXT_ERROR; 951510Salexander.borisov@nginx.com } 952510Salexander.borisov@nginx.com 953510Salexander.borisov@nginx.com http_status = nxt_perl_psgi_result_status(nxt_perl_psgi, result); 954510Salexander.borisov@nginx.com 955510Salexander.borisov@nginx.com if (nxt_slow_path(http_status.start == NULL || http_status.length == 0)) { 956510Salexander.borisov@nginx.com nxt_log_error(NXT_LOG_ERR, task->log, 957510Salexander.borisov@nginx.com "PSGI: An unexpected status was received " 958510Salexander.borisov@nginx.com "from Perl Application"); 959510Salexander.borisov@nginx.com 960510Salexander.borisov@nginx.com return NXT_ERROR; 961510Salexander.borisov@nginx.com } 962510Salexander.borisov@nginx.com 963510Salexander.borisov@nginx.com rc = nxt_perl_psgi_http_write_status_str(task, wmsg, &http_status); 964510Salexander.borisov@nginx.com 965510Salexander.borisov@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 966510Salexander.borisov@nginx.com nxt_log_error(NXT_LOG_ERR, task->log, 967510Salexander.borisov@nginx.com "PSGI: Failed to write HTTP Status"); 968510Salexander.borisov@nginx.com 969510Salexander.borisov@nginx.com return rc; 970510Salexander.borisov@nginx.com } 971510Salexander.borisov@nginx.com 972510Salexander.borisov@nginx.com if (array_len < 1) { 973510Salexander.borisov@nginx.com rc = nxt_app_msg_write_raw(task, wmsg, (u_char *) "\r\n", 974510Salexander.borisov@nginx.com (sizeof("\r\n") - 1)); 975510Salexander.borisov@nginx.com 976510Salexander.borisov@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 977510Salexander.borisov@nginx.com nxt_log_error(NXT_LOG_ERR, task->log, 978510Salexander.borisov@nginx.com "PSGI: Failed to write HTTP Headers"); 979510Salexander.borisov@nginx.com 980510Salexander.borisov@nginx.com return rc; 981510Salexander.borisov@nginx.com } 982510Salexander.borisov@nginx.com 983510Salexander.borisov@nginx.com return NXT_OK; 984510Salexander.borisov@nginx.com } 985510Salexander.borisov@nginx.com 986510Salexander.borisov@nginx.com sv_temp = av_fetch(array, 1, 0); 987510Salexander.borisov@nginx.com 988510Salexander.borisov@nginx.com if (nxt_slow_path(sv_temp == NULL)) { 989510Salexander.borisov@nginx.com nxt_log_error(NXT_LOG_ERR, task->log, 990510Salexander.borisov@nginx.com "PSGI: Failed to get head from Perl ARRAY variable"); 991510Salexander.borisov@nginx.com 992510Salexander.borisov@nginx.com return NXT_ERROR; 993510Salexander.borisov@nginx.com } 994510Salexander.borisov@nginx.com 995510Salexander.borisov@nginx.com rc = nxt_perl_psgi_result_head(nxt_perl_psgi, *sv_temp, task, wmsg); 996510Salexander.borisov@nginx.com 997510Salexander.borisov@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 998510Salexander.borisov@nginx.com return rc; 999510Salexander.borisov@nginx.com } 1000510Salexander.borisov@nginx.com 1001510Salexander.borisov@nginx.com rc = nxt_app_msg_write_raw(task, wmsg, (u_char *) "\r\n", 1002510Salexander.borisov@nginx.com (sizeof("\r\n") - 1)); 1003510Salexander.borisov@nginx.com 1004510Salexander.borisov@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 1005510Salexander.borisov@nginx.com nxt_log_error(NXT_LOG_ERR, task->log, 1006510Salexander.borisov@nginx.com "PSGI: Failed to write HTTP Headers"); 1007510Salexander.borisov@nginx.com 1008510Salexander.borisov@nginx.com return rc; 1009510Salexander.borisov@nginx.com } 1010510Salexander.borisov@nginx.com 1011510Salexander.borisov@nginx.com if (nxt_fast_path(array_len < 2)) { 1012510Salexander.borisov@nginx.com return NXT_OK; 1013510Salexander.borisov@nginx.com } 1014510Salexander.borisov@nginx.com 1015510Salexander.borisov@nginx.com sv_temp = av_fetch(array, 2, 0); 1016510Salexander.borisov@nginx.com 1017519Salexander.borisov@nginx.com if (nxt_slow_path(sv_temp == NULL || SvROK(*sv_temp) == FALSE)) { 1018510Salexander.borisov@nginx.com nxt_log_error(NXT_LOG_ERR, task->log, 1019510Salexander.borisov@nginx.com "PSGI: Failed to get body from Perl ARRAY variable"); 1020510Salexander.borisov@nginx.com 1021510Salexander.borisov@nginx.com return NXT_ERROR; 1022510Salexander.borisov@nginx.com } 1023510Salexander.borisov@nginx.com 1024510Salexander.borisov@nginx.com if (SvTYPE(SvRV(*sv_temp)) == SVt_PVAV) { 1025510Salexander.borisov@nginx.com rc = nxt_perl_psgi_result_body(nxt_perl_psgi, *sv_temp, task, wmsg); 1026510Salexander.borisov@nginx.com 1027510Salexander.borisov@nginx.com } else { 1028510Salexander.borisov@nginx.com rc = nxt_perl_psgi_result_body_ref(nxt_perl_psgi, *sv_temp, 1029510Salexander.borisov@nginx.com task, wmsg); 1030510Salexander.borisov@nginx.com } 1031510Salexander.borisov@nginx.com 1032510Salexander.borisov@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 1033510Salexander.borisov@nginx.com return rc; 1034510Salexander.borisov@nginx.com } 1035510Salexander.borisov@nginx.com 1036510Salexander.borisov@nginx.com return NXT_OK; 1037510Salexander.borisov@nginx.com } 1038510Salexander.borisov@nginx.com 1039510Salexander.borisov@nginx.com 1040510Salexander.borisov@nginx.com static nxt_int_t 1041510Salexander.borisov@nginx.com nxt_perl_psgi_init(nxt_task_t *task, nxt_common_app_conf_t *conf) 1042510Salexander.borisov@nginx.com { 1043510Salexander.borisov@nginx.com PerlInterpreter *my_perl; 1044510Salexander.borisov@nginx.com 1045510Salexander.borisov@nginx.com my_perl = nxt_perl_psgi_interpreter_init(task, conf->u.perl.script); 1046510Salexander.borisov@nginx.com 1047510Salexander.borisov@nginx.com if (nxt_slow_path(my_perl == NULL)) { 1048510Salexander.borisov@nginx.com return NXT_ERROR; 1049510Salexander.borisov@nginx.com } 1050510Salexander.borisov@nginx.com 1051510Salexander.borisov@nginx.com nxt_perl_psgi = my_perl; 1052510Salexander.borisov@nginx.com 1053510Salexander.borisov@nginx.com return NXT_OK; 1054510Salexander.borisov@nginx.com } 1055510Salexander.borisov@nginx.com 1056510Salexander.borisov@nginx.com 1057510Salexander.borisov@nginx.com static nxt_int_t 1058510Salexander.borisov@nginx.com nxt_perl_psgi_run(nxt_task_t *task, nxt_app_rmsg_t *rmsg, nxt_app_wmsg_t *wmsg) 1059510Salexander.borisov@nginx.com { 1060510Salexander.borisov@nginx.com SV *env, *result; 1061510Salexander.borisov@nginx.com size_t body_preread_size; 1062510Salexander.borisov@nginx.com nxt_int_t rc; 1063510Salexander.borisov@nginx.com nxt_perl_psgi_input_t input; 1064510Salexander.borisov@nginx.com 1065510Salexander.borisov@nginx.com dTHXa(nxt_perl_psgi); 1066510Salexander.borisov@nginx.com 1067510Salexander.borisov@nginx.com /* 1068510Salexander.borisov@nginx.com * Create environ variable for perl sub "application". 1069510Salexander.borisov@nginx.com * > sub application { 1070510Salexander.borisov@nginx.com * > my ($environ) = @_; 1071510Salexander.borisov@nginx.com */ 1072510Salexander.borisov@nginx.com env = nxt_perl_psgi_env_create(nxt_perl_psgi, task, rmsg, 1073510Salexander.borisov@nginx.com &body_preread_size); 1074510Salexander.borisov@nginx.com 1075510Salexander.borisov@nginx.com if (nxt_slow_path(env == NULL)) { 1076510Salexander.borisov@nginx.com nxt_log_error(NXT_LOG_ERR, task->log, 1077510Salexander.borisov@nginx.com "PSGI: Failed to create 'env' for Perl Application"); 1078510Salexander.borisov@nginx.com 1079510Salexander.borisov@nginx.com return NXT_ERROR; 1080510Salexander.borisov@nginx.com } 1081510Salexander.borisov@nginx.com 1082510Salexander.borisov@nginx.com input.my_perl = nxt_perl_psgi; 1083510Salexander.borisov@nginx.com input.task = task; 1084510Salexander.borisov@nginx.com input.rmsg = rmsg; 1085510Salexander.borisov@nginx.com input.wmsg = wmsg; 1086510Salexander.borisov@nginx.com input.body_preread_size = body_preread_size; 1087510Salexander.borisov@nginx.com 1088510Salexander.borisov@nginx.com nxt_perl_psgi_arg_input.ctx = &input; 1089510Salexander.borisov@nginx.com nxt_perl_psgi_arg_error.ctx = &input; 1090510Salexander.borisov@nginx.com 1091510Salexander.borisov@nginx.com /* Call perl sub and get result as SV*. */ 1092510Salexander.borisov@nginx.com result = nxt_perl_psgi_call_var_application(nxt_perl_psgi, env, task); 1093510Salexander.borisov@nginx.com 1094510Salexander.borisov@nginx.com /* 1095510Salexander.borisov@nginx.com * We expect ARRAY ref like a 1096510Salexander.borisov@nginx.com * ['200', ['Content-Type' => "text/plain"], ["body"]] 1097510Salexander.borisov@nginx.com */ 1098510Salexander.borisov@nginx.com if (nxt_slow_path(SvOK(result) == 0 || SvROK(result) == 0 1099510Salexander.borisov@nginx.com || SvTYPE(SvRV(result)) != SVt_PVAV)) 1100510Salexander.borisov@nginx.com { 1101510Salexander.borisov@nginx.com nxt_log_error(NXT_LOG_ERR, task->log, 1102510Salexander.borisov@nginx.com "PSGI: An unexpected response was received from " 1103510Salexander.borisov@nginx.com "Perl Application"); 1104510Salexander.borisov@nginx.com goto fail; 1105510Salexander.borisov@nginx.com } 1106510Salexander.borisov@nginx.com 1107510Salexander.borisov@nginx.com rc = nxt_perl_psgi_result_array(nxt_perl_psgi, result, task, wmsg); 1108510Salexander.borisov@nginx.com 1109510Salexander.borisov@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 1110510Salexander.borisov@nginx.com goto fail; 1111510Salexander.borisov@nginx.com } 1112510Salexander.borisov@nginx.com 1113510Salexander.borisov@nginx.com rc = nxt_app_msg_flush(task, wmsg, 1); 1114510Salexander.borisov@nginx.com 1115510Salexander.borisov@nginx.com if (nxt_slow_path(rc != NXT_OK)) { 1116510Salexander.borisov@nginx.com goto fail; 1117510Salexander.borisov@nginx.com } 1118510Salexander.borisov@nginx.com 1119510Salexander.borisov@nginx.com SvREFCNT_dec(result); 1120510Salexander.borisov@nginx.com SvREFCNT_dec(env); 1121510Salexander.borisov@nginx.com 1122510Salexander.borisov@nginx.com return NXT_OK; 1123510Salexander.borisov@nginx.com 1124510Salexander.borisov@nginx.com fail: 1125510Salexander.borisov@nginx.com 1126510Salexander.borisov@nginx.com SvREFCNT_dec(result); 1127510Salexander.borisov@nginx.com SvREFCNT_dec(env); 1128510Salexander.borisov@nginx.com 1129510Salexander.borisov@nginx.com return NXT_ERROR; 1130510Salexander.borisov@nginx.com } 1131510Salexander.borisov@nginx.com 1132510Salexander.borisov@nginx.com 1133510Salexander.borisov@nginx.com static void 1134510Salexander.borisov@nginx.com nxt_perl_psgi_atexit(nxt_task_t *task) 1135510Salexander.borisov@nginx.com { 1136510Salexander.borisov@nginx.com dTHXa(nxt_perl_psgi); 1137510Salexander.borisov@nginx.com 1138510Salexander.borisov@nginx.com nxt_perl_psgi_layer_stream_io_destroy(aTHX_ nxt_perl_psgi_arg_input.io); 1139510Salexander.borisov@nginx.com nxt_perl_psgi_layer_stream_fp_destroy(aTHX_ nxt_perl_psgi_arg_input.fp); 1140510Salexander.borisov@nginx.com 1141510Salexander.borisov@nginx.com nxt_perl_psgi_layer_stream_io_destroy(aTHX_ nxt_perl_psgi_arg_error.io); 1142510Salexander.borisov@nginx.com nxt_perl_psgi_layer_stream_fp_destroy(aTHX_ nxt_perl_psgi_arg_error.fp); 1143510Salexander.borisov@nginx.com 1144510Salexander.borisov@nginx.com perl_destruct(nxt_perl_psgi); 1145510Salexander.borisov@nginx.com perl_free(nxt_perl_psgi); 1146510Salexander.borisov@nginx.com PERL_SYS_TERM(); 1147510Salexander.borisov@nginx.com } 1148