ngx_int_t ngx_mrb_run(ngx_http_request_t *r, ngx_mrb_state_t *state, ngx_flag_t cached) { ngx_mruby_ctx_t *ctx; rputs_chain_list_t *chain; if (state == NGX_CONF_UNSET_PTR) { return NGX_DECLINED; } if ((ctx = ngx_pcalloc(r->pool, sizeof(*ctx))) == NULL) { ngx_log_error(NGX_LOG_ERR , r->connection->log , 0 , "failed to allocate memory from r->pool %s:%d" , __FUNCTION__ , __LINE__ ); return NGX_ERROR; } ngx_http_set_ctx(r, ctx, ngx_http_mruby_module); ngx_mrb_push_request(r); mrb_run(state->mrb, mrb_proc_new(state->mrb, state->mrb->irep[state->n]), mrb_nil_value()); if (state->mrb->exc) { if (state->code_type == NGX_MRB_CODE_TYPE_FILE) { ngx_mrb_raise_file_error(state->mrb, mrb_obj_value(state->mrb->exc), r, state->code.file); } else { ngx_mrb_raise_error(state->mrb, mrb_obj_value(state->mrb->exc), r); } } mrb_gc_arena_restore(state->mrb, state->ai); if (!cached) { ngx_mrb_irep_clean(state); } if (ngx_http_get_module_ctx(r, ngx_http_mruby_module) != NULL) { chain = ctx->rputs_chain; if (r->headers_out.status == NGX_HTTP_OK || !(*chain->last)->buf->last_buf) { r->headers_out.status = NGX_HTTP_OK; (*chain->last)->buf->last_buf = 1; ngx_http_send_header(r); ngx_http_output_filter(r, chain->out); ngx_http_set_ctx(r, NULL, ngx_http_mruby_module); return NGX_OK; } else { return r->headers_out.status; } } return NGX_OK; }
ngx_int_t ngx_mrb_run_body_filter(ngx_http_request_t *r, ngx_mrb_state_t *state, ngx_mrb_code_t *code, ngx_flag_t cached, ngx_http_mruby_ctx_t *ctx) { mrb_value ARGV, mrb_result; ARGV = mrb_ary_new_capa(state->mrb, 1); mrb_ary_push(state->mrb, ARGV, mrb_str_new(state->mrb, (char *)ctx->body, ctx->body_length)); mrb_define_global_const(state->mrb, "ARGV", ARGV); mrb_result = mrb_run(state->mrb, mrb_proc_new(state->mrb, state->mrb->irep[code->n]), mrb_top_self(state->mrb)); if (state->mrb->exc) { if (code->code_type == NGX_MRB_CODE_TYPE_FILE) { ngx_mrb_raise_file_error(state->mrb, mrb_obj_value(state->mrb->exc), r, code->code.file); } else { ngx_mrb_raise_error(state->mrb, mrb_obj_value(state->mrb->exc), r); } mrb_gc_arena_restore(state->mrb, state->ai); if (!cached) { ngx_mrb_irep_clean(r, state, code); ngx_mrb_state_clean(r, state); } return NGX_ERROR; } if (mrb_type(mrb_result) != MRB_TT_STRING) { mrb_result = mrb_funcall(state->mrb, mrb_result, "to_s", 0, NULL); } ctx->body = (u_char *)RSTRING_PTR(mrb_result); ctx->body_length = ngx_strlen(ctx->body); mrb_gc_arena_restore(state->mrb, state->ai); if (!cached) { ngx_mrb_irep_clean(r, state, code); ngx_mrb_state_clean(r, state); } return NGX_OK; }
ngx_int_t ngx_mrb_run(ngx_http_request_t *r, ngx_mrb_state_t *state, ngx_mrb_code_t *code, ngx_flag_t cached, ngx_str_t *result) { int result_len; mrb_value mrb_result; ngx_http_mruby_ctx_t *ctx; ngx_mrb_rputs_chain_list_t *chain; if (state == NGX_CONF_UNSET_PTR || code == NGX_CONF_UNSET_PTR) { return NGX_DECLINED; } ctx = ngx_http_get_module_ctx(r, ngx_http_mruby_module); if (ctx == NULL && (ctx = ngx_pcalloc(r->pool, sizeof(*ctx))) == NULL) { ngx_log_error(NGX_LOG_ERR , r->connection->log , 0 , "failed to allocate memory from r->pool %s:%d" , __FUNCTION__ , __LINE__ ); return NGX_ERROR; } ngx_http_set_ctx(r, ctx, ngx_http_mruby_module); ngx_mrb_push_request(r); if (!cached) { state->ai = mrb_gc_arena_save(state->mrb); } ngx_log_error(NGX_LOG_INFO , r->connection->log , 0 , "%s INFO %s:%d: mrb_run info: irep_n=%d arena_idx=%d" , MODULE_NAME , __func__ , __LINE__ , code->n , state->ai ); mrb_result = mrb_run(state->mrb, mrb_proc_new(state->mrb, state->mrb->irep[code->n]), mrb_top_self(state->mrb)); if (state->mrb->exc) { if (code->code_type == NGX_MRB_CODE_TYPE_FILE) { ngx_mrb_raise_file_error(state->mrb, mrb_obj_value(state->mrb->exc), r, code->code.file); } else { ngx_mrb_raise_error(state->mrb, mrb_obj_value(state->mrb->exc), r); } } if (result != NULL) { if (mrb_nil_p(mrb_result)) { result->data = NULL; result->len = 0; } else { if (mrb_type(mrb_result) != MRB_TT_STRING) { mrb_result = mrb_funcall(state->mrb, mrb_result, "to_s", 0, NULL); } result_len = ngx_strlen((u_char *)RSTRING_PTR(mrb_result)); result->data = ngx_palloc(r->pool, result_len); if (result->data == NULL) { return NGX_ERROR; } ngx_memcpy(result->data, (u_char *)RSTRING_PTR(mrb_result), result_len); result->len = result_len; ngx_log_error(NGX_LOG_INFO , r->connection->log , 0 , "%s INFO %s:%d: mrb_run info: irep_n=(%d) return value=(%s)" , MODULE_NAME , __func__ , __LINE__ , code->n , RSTRING_PTR(mrb_result) ); } } mrb_gc_arena_restore(state->mrb, state->ai); if (!cached) { ngx_mrb_irep_clean(r, state, code); ngx_mrb_state_clean(r, state); } // TODO: Support rputs by multi directive if (ngx_http_get_module_ctx(r, ngx_http_mruby_module) != NULL) { chain = ctx->rputs_chain; if (chain == NULL) { ngx_log_error(NGX_LOG_INFO , r->connection->log , 0 , "%s INFO %s:%d: mrb_run info: irep_n=(%d) rputs_chain is null and return NGX_OK" , MODULE_NAME , __func__ , __LINE__ , code->n ); return NGX_OK; } if (r->headers_out.status == NGX_HTTP_OK || !(*chain->last)->buf->last_buf) { r->headers_out.status = NGX_HTTP_OK; (*chain->last)->buf->last_buf = 1; ngx_http_send_header(r); ngx_http_output_filter(r, chain->out); ngx_http_set_ctx(r, NULL, ngx_http_mruby_module); return NGX_OK; } else { return r->headers_out.status; } } return NGX_OK; }