解析http请求->在后台运行任务->任务完成时返回响应

时间:2019-01-17 16:47:59

标签: c nginx

正如标题所述,我正在为nginx开发http处理程序模块,在该模块中我想解析http请求,在后台运行任务,并在完成时想返回响应。

我尝试让http内容处理程序使用线程池来运行任务。在解析请求时,我增加了r-> main-> count,并在任务完成处理程序中将其减少了。另外,在任务完成处理程序中,我调用ngx_http_send_header和ngx_http_output_filter返回结果。这适用于10ish请求,然后阻止了nginx。它不再处理http请求。(日志中没有任何内容)。在我的开发环境中,为了简化调试,我在运行nginx时关闭了deamon,关闭了主进程,并且只有一个工作进程。

我还尝试将处理程序附加到PREACCESS和REWRITE PHASE中,然后在生成线程时返回NGX_DONE,希望nginx再次调用我的处理程序,但从未成功。

有什么想法我在做什么错吗?

谢谢!

static ngx_int_t ngx_http_image_render_handler(ngx_http_request_t *r)
{
    ngx_http_image_render_ctx_t   *ctx;
    ngx_http_image_render_loc_conf_t  *plcf;

    plcf = (ngx_http_image_render_loc_conf_t*)ngx_http_get_module_loc_conf(r, ngx_http_image_render_module);

    ctx = (ngx_http_image_render_ctx_t*)ngx_http_get_module_ctx(r, ngx_http_image_render_module);

    if(ctx != NULL)
    {
        if(ctx->done != 1)
        {
            ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "ctx already here! AGAIN");
            return NGX_DONE;
        }

        return send_image(ctx->image_render_ctx);
    }

    ctx = (ngx_http_image_render_ctx_t*)ngx_pcalloc(r->pool, sizeof(ngx_http_image_render_ctx_t));
    if (ctx == NULL) {
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "NGX_HTTP_INTERNAL_SERVER_ERROR");
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }
    ctx->request = r;
    ctx->done = 0;

    ngx_http_set_ctx(r, ctx, ngx_http_image_render_module);

    image_render_ctx_t    *image_render_ctx;
    ngx_thread_task_t  *task;

    task = ngx_thread_task_alloc(r->pool, sizeof(image_render_ctx_t));
    if (task == NULL) {
        return NGX_ERROR;
    }

    image_render_ctx = (image_render_ctx_t*)task->ctx;

    ctx->image_render_ctx = image_render_ctx;

    if(ngx_http_parse_image_request(r, image_render_ctx) != NGX_OK )
    {
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "error parsing request");
        return NGX_ERROR;
    }

    image_render_ctx->db_util = plcf->db_util;


    task->handler = image_render_func;
    task->event.handler = image_render_completion;
    task->event.data = image_render_ctx;

    if (ngx_thread_task_post((ngx_thread_pool_t*)plcf->pool, task) != NGX_OK) {
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "error posting to pool");
        return NGX_ERROR;
    }

    r->main->count++;

    ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "RECEIVED REQUEST!");

  return NGX_DONE;
}

static int send_image(image_render_ctx_t* trc)
{
    ngx_buf_t    *b;
    ngx_chain_t   out;

    u_char* image = (u_char*)trc->image_data.data();
    size_t image_size = trc->image_data.length();


    ngx_http_request_t *r = trc->r;

    b = ngx_create_temp_buf(r->pool, image_size);

    out.buf = b;
    out.next = NULL;

    ngx_memcpy(b->pos, image, image_size);

    b->last = b->pos + image_size;
    b->memory = 1;
    b->last_buf = 1;


    r->main->count--;

    r->headers_out.content_type.len = sizeof("image/png") - 1;
    r->headers_out.content_type.data = (u_char *) "image/png";

    r->headers_out.status = NGX_HTTP_OK;
    r->headers_out.content_length_n = image_size;

    ngx_http_send_header(r);

    return ngx_http_output_filter(r, &out);;
}

//Attach our handler
static ngx_int_t ngx_http_image_render_init(ngx_conf_t *cf)
{
    ngx_http_handler_pt        *h;
    ngx_http_core_main_conf_t  *cmcf;

    cmcf = (ngx_http_core_main_conf_t*)ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);

    h = (ngx_http_handler_pt*)ngx_array_push(&cmcf->phases[NGX_HTTP_PREACCESS_PHASE].handlers);
    if (h == NULL) {
        return NGX_ERROR;
    }

    *h = (ngx_http_handler_pt)ngx_http_image_render_handler;

    return NGX_OK;
}

static void
image_render_completion(ngx_event_t *ev)
{
    image_render_ctx_t *ctx = (image_render_ctx_t*)ev->data;

    ngx_log_error(NGX_LOG_ERR, ctx->r->connection->log, 0, "sending back image!!!");

    ngx_http_image_render_ctx_t   *rctx;
    rctx = (ngx_http_image_render_ctx_t*)ngx_http_get_module_ctx(ctx->r, ngx_http_image_render_module);

    rctx->done = 1;
}

0 个答案:

没有答案