Proxying request - HTTP/1.1 502 Bad Gateway

michalkraus nginx-forum at nginx.us
Wed Aug 10 11:56:54 UTC 2011


We have found out that the problem is caused by my frpc module.
Everything is OK withnout the module. This frpc module reads POST
request body and thed generates a response. In location /public/RPC2 the
module is off but some initial function of the module are carried out.
There is probably an incorrect construnction in module initialization
that doesn't allow to run proxy module.

The major part of my module's source code (C++ used):

typedef struct {
    ngx_str_t    frpc_log;
    ngx_str_t    frpc_service;
} ngx_http_ap_frpc_ctx_t;

typedef struct {
    ngx_flag_t   enable;
    ngx_int_t    gsidindex;
    ngx_str_t    services;
    ngx_str_t    controlserver;
    ngx_str_t    servertype;
} ngx_http_ap_frpc_handler_loc_conf_t;

static ngx_command_t  ngx_http_ap_frpc_handler_commands[] = {
    { ngx_string("ap_frpc"),
     
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE1,
      ngx_conf_set_flag_slot,
      NGX_HTTP_LOC_CONF_OFFSET,
      offsetof(ngx_http_ap_frpc_handler_loc_conf_t, enable),
      NULL },
    // cookie vygenerovana ap_filter modulem
    { ngx_string("ap_frpc_gsid"),
     
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE1,
      ngx_http_ap_frpc_gsid,
      NGX_HTTP_LOC_CONF_OFFSET,
      0,
      NULL },
    // seznam rozrazovanych sluzeb z konfiguracniho souboru - ostatni se
loguji do other
    { ngx_string("ap_frpc_services"),
     
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE1,
      ngx_conf_set_str_slot,
      NGX_HTTP_LOC_CONF_OFFSET,
      offsetof(ngx_http_ap_frpc_handler_loc_conf_t, services),
      NULL },
    // adresa controlserveru pro ohlasovani APcka
    { ngx_string("ap_frpc_controlserver"),
     
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE1,
      ngx_conf_set_str_slot,
      NGX_HTTP_LOC_CONF_OFFSET,
      offsetof(ngx_http_ap_frpc_handler_loc_conf_t, controlserver),
      NULL },
    // server_type pro ohlasovani na control server
    { ngx_string("ap_frpc_servertype"),
     
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE1,
      ngx_conf_set_str_slot,
      NGX_HTTP_LOC_CONF_OFFSET,
      offsetof(ngx_http_ap_frpc_handler_loc_conf_t, servertype),
      NULL },
      ngx_null_command
};
static ngx_http_module_t  ngx_http_ap_frpc_handler_module_ctx = {
    ngx_http_ap_frpc_add_variables,   /* preconfiguration */
    ngx_http_ap_frpc_init,            /* postconfiguration */
    NULL,                             /* create main configuration */
    NULL,                             /* init main configuration */
    NULL,                             /* create server configuration */
    NULL,                             /* merge server configuration */
    ngx_http_ap_frpc_handler_create_loc_conf,  /* create location
configuration */
    ngx_http_ap_frpc_handler_merge_loc_conf    /* merge location
configuration */
};

ngx_module_t  ngx_http_ap_frpc_handler_module = {
    NGX_MODULE_V1,
    &ngx_http_ap_frpc_handler_module_ctx,   /* module context */
    ngx_http_ap_frpc_handler_commands,      /* module directives */
    NGX_HTTP_MODULE,               /* module type */
    NULL,                          /* init master */
    NULL,                          /* init module */
    NULL,                          /* init process */
    NULL,                          /* init thread */
    NULL,                          /* exit thread */
    NULL,                          /* exit process */
    NULL,                          /* exit master */
    NGX_MODULE_V1_PADDING
};

static ngx_http_variable_t  ngx_http_ap_frpc_vars[] = {
      // $ap_frc_log - informace k zalogovani
    { ngx_string("ap_frpc_log"), NULL, ngx_http_ap_frpc_log_variable,
0,
     
NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0
},
    { ngx_string("ap_frpc_service"), NULL,
ngx_http_ap_frpc_service_variable, 0,
     
NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0
},

    { ngx_null_string, NULL, NULL, 0, 0, 0 }
};

static ngx_int_t ngx_http_ap_frpc_add_variables(ngx_conf_t *cf) {
    ngx_http_variable_t  *var, *v;

    for (v = ngx_http_ap_frpc_vars; v->name.len; v++) {
        var = ngx_http_add_variable(cf, &v->name, v->flags);
        if (var == NULL) {
            return NGX_ERROR;
        }

        var->get_handler = v->get_handler;
        var->data = v->data;
    }

    return NGX_OK;
}

// inicializace promenne $ap_frpc_log
static ngx_int_t ngx_http_ap_frpc_log_variable(ngx_http_request_t *r, 
        ngx_http_variable_value_t *v, uintptr_t data) {
    ngx_http_ap_frpc_ctx_t  *ctx;

    ctx = reinterpret_cast<ngx_http_ap_frpc_ctx_t*>
        (ngx_http_get_module_ctx(r, ngx_http_ap_frpc_handler_module));

    if (ctx == NULL) {
        v->not_found = 1;
        return NGX_OK;
    }

    v->len = ctx->frpc_log.len;
    v->valid = 1;
    v->no_cacheable = 0;
    v->not_found = 0;
    v->data = ctx->frpc_log.data;

    return NGX_OK;
}

static ngx_int_t ngx_http_ap_frpc_service_variable(ngx_http_request_t
*r, 
        ngx_http_variable_value_t *v, uintptr_t data) {
    ngx_http_ap_frpc_ctx_t  *ctx;

    ctx =
reinterpret_cast<ngx_http_ap_frpc_ctx_t*>(ngx_http_get_module_ctx(r,
ngx_http_ap_frpc_handler_module));

    if (ctx == NULL) {
        v->not_found = 1;
        return NGX_OK;
    }
    
    v->len = ctx->frpc_service.len;
    v->valid = 1;
    v->no_cacheable = 0;
    v->not_found = 0;
    v->data = ctx->frpc_service.data;

    return NGX_OK;
}

static ngx_int_t ngx_http_ap_frpc_init(ngx_conf_t *cf){
    ngx_http_handler_pt         *h;
    ngx_http_core_main_conf_t   *cmcf;

    cmcf =
reinterpret_cast<ngx_http_core_main_conf_t*>(ngx_http_conf_get_module_main_conf(cf,
ngx_http_core_module));

    h =
reinterpret_cast<ngx_http_handler_pt*>(ngx_array_push(&cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers));

    if (h == NULL) {
        return NGX_ERROR;
    }

    *h = ngx_http_ap_frpc_access_handler;
    return NGX_OK;
}

static ngx_int_t ngx_http_ap_frpc_access_handler(ngx_http_request_t *r)
{
    if (r->method != NGX_HTTP_POST) {
        return NGX_DECLINED;
    }
    ngx_int_t rc = ngx_http_read_client_request_body(r,
ngx_http_ap_frpc_request);
    if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) {
        return rc;
    }
    if (rc == NGX_AGAIN) {
        return NGX_DONE;
    }

    return NGX_DECLINED;
}

static void ngx_http_ap_frpc_request(ngx_http_request_t *r) {
    ngx_http_ap_frpc_ctx_t       *ctx;
    ctx =
reinterpret_cast<ngx_http_ap_frpc_ctx_t*>(ngx_http_get_module_ctx(r,
ngx_http_ap_frpc_handler_module));
    if (ctx == NULL) {
        ctx =
reinterpret_cast<ngx_http_ap_frpc_ctx_t*>(ngx_pcalloc(r->pool,
sizeof(ngx_http_ap_frpc_handler_module)));
        ngx_http_set_ctx(r, ctx, ngx_http_ap_frpc_handler_module);
    }
    ngx_http_ap_frpc(r, ctx);
    ngx_http_finalize_request(r, NGX_DONE);
}

static void *ngx_http_ap_frpc_handler_create_loc_conf(ngx_conf_t *cf)
{
    ngx_http_ap_frpc_handler_loc_conf_t  *conf;

    conf =
reinterpret_cast<ngx_http_ap_frpc_handler_loc_conf_t*>(ngx_pcalloc(cf->pool,

                sizeof(ngx_http_ap_frpc_handler_loc_conf_t)));
    if (conf == NULL) {
        return NGX_CONF_ERROR;
    }
    conf->enable = NGX_CONF_UNSET_UINT;
    conf->gsidindex = NGX_CONF_UNSET;

    return conf;
}

static char *ngx_http_ap_frpc_handler_merge_loc_conf(ngx_conf_t *cf,
void *parent, void *child)
{
    ngx_http_ap_frpc_handler_loc_conf_t *prev =
reinterpret_cast<ngx_http_ap_frpc_handler_loc_conf_t*>(parent);
    ngx_http_ap_frpc_handler_loc_conf_t *conf =
reinterpret_cast<ngx_http_ap_frpc_handler_loc_conf_t*>(child);

    ngx_conf_merge_value(conf->enable, prev->enable, 0);
    ngx_conf_merge_str_value(conf->services, prev->services, "other");
    ngx_conf_merge_str_value(conf->controlserver, prev->controlserver,
"http://skcontrol:3337/RPC2");
    ngx_conf_merge_str_value(conf->servertype, prev->servertype,
"targeting-advertproxy");
    if (conf->gsidindex == NGX_CONF_UNSET) {
        conf->gsidindex = prev->gsidindex;
    }
    return NGX_CONF_OK;
}

static char *ngx_http_ap_frpc_gsid(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf) {
    ngx_str_t                   *value;
  
    ngx_http_ap_frpc_handler_loc_conf_t   *lcf =
reinterpret_cast<ngx_http_ap_frpc_handler_loc_conf_t*>(conf);
    value = reinterpret_cast<ngx_str_t*>(cf->args->elts);

    if (value[1].data[0] == '$') {
        value[1].len--;
        value[1].data++;
        
        lcf->gsidindex = ngx_http_get_variable_index(cf, &value[1]);
        if (lcf->gsidindex == NGX_ERROR) {
            return reinterpret_cast<char*>(NGX_CONF_ERROR);
        }
    }

    return NGX_CONF_OK;
}

static ngx_int_t ngx_http_ap_frpc_parse_header(ngx_http_request_t *r) {
    if (r->headers_in.content_type != NULL) {
        if (ngx_strncmp(r->headers_in.content_type->value.data,
"text/xml", 8) == 0) {
            return 0;
        } else if (ngx_strncmp(r->headers_in.content_type->value.data,
"application/x-frpc", 18) == 0) {
            return 1;
        }
    }
    return -1;
}

static ngx_int_t ngx_http_ap_frpc_read_body(ngx_http_request_t *r,
ngx_str_t *request_body) {
    u_char       *p;
    size_t        len;
    ngx_buf_t    *buf, *next;
    ngx_chain_t  *cl;

    if (r->request_body == NULL
        || r->request_body->bufs == NULL
        || r->request_body->temp_file)
    {
        return 0;
    }

    cl = r->request_body->bufs;
    buf = cl->buf;

    if (cl->next == NULL) {
        len = buf->last - buf->pos;
        p = reinterpret_cast<u_char*>(ngx_pnalloc(r->pool, len));
        if (p == NULL) {
            return NGX_ERROR;
        }
        ngx_cpystrn(p, cl->buf->pos, len);
        
        ngx_str_set(request_body, p);
        request_body->len = len;
        return len;
    }

    next = cl->next->buf;
    len = (buf->last - buf->pos) + (next->last - next->pos);

    p =  reinterpret_cast<u_char*>(ngx_pnalloc(r->pool, len));
    if (p == NULL) {
        return NGX_ERROR;
    }
    
    request_body->data = p;

    p = ngx_cpymem(p, buf->pos, buf->last - buf->pos);
    ngx_memcpy(p, next->pos, next->last - next->pos);

    request_body->len = len;
    return len;
}

static ngx_int_t ngx_http_ap_frpc_response(ngx_http_request_t *r,
std::string *response_body, bool binary) {
    ngx_buf_t   *b;
    ngx_chain_t  out;

    b = reinterpret_cast<ngx_buf_t*>(ngx_pcalloc(r->pool,
sizeof(ngx_buf_t)));
    if (b == NULL) {
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }
    b->pos  =
reinterpret_cast<u_char*>(const_cast<char*>(response_body->c_str()));
    b->last =
reinterpret_cast<u_char*>(const_cast<char*>(response_body->c_str())) +
response_body->size();

    b->memory   = 1;
    b->last_buf = 1;
    out.buf  = b;
    out.next = NULL;

    ngx_str_t   content_type;
    if (!binary) {
        ngx_str_set(&content_type, "text/xml");
    } else {
        ngx_str_set(&content_type, "application/x-frpc");
    }
    r->headers_out.status = NGX_HTTP_OK;
    r->headers_out.content_length_n = response_body->size();
    r->headers_out.content_type.len  = content_type.len;
    r->headers_out.content_type.data = content_type.data;
    r->keepalive = 0;       // Connection: close
    
    ngx_int_t   rc = ngx_http_send_header(r);
    
    if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
        return rc;
    }

    ngx_http_output_filter(r, &out);
    ngx_pfree(r->pool, b);
    return NGX_OK;
}

static ngx_int_t ngx_http_ap_frpc(ngx_http_request_t *r,
ngx_http_ap_frpc_ctx_t *ctx)
{
    ngx_http_ap_frpc_handler_loc_conf_t  *cglcf;
    cglcf =
reinterpret_cast<ngx_http_ap_frpc_handler_loc_conf_t*>(ngx_http_get_module_loc_conf(r,

                ngx_http_ap_frpc_handler_module));

    if (cglcf->enable == 0) {
        ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"ap_frpc disable");
        return NGX_OK;
    } else {
        ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"ap_frpc enable");
    }
    // Priznak zda je spojeni xml-rpc (0) nebo fastrpc (1)
    bool binary = false;
    if (ngx_http_ap_frpc_parse_header(r) == -1) {
        return NGX_ERROR;
    }
    else { 
        binary = (ngx_http_ap_frpc_parse_header(r) == 1);
    }
    // precteni tela pozadavku
    ngx_str_t request_body;
    ngx_int_t bodyLength = ngx_http_ap_frpc_read_body(r,
&request_body);
    if (bodyLength <= 0) {
        return NGX_ERROR;
    }

  ....... process the request and generate response
}

Body of my ngx_int_t ngx_http_ap_frpc function is not important because
it is not carried out in /public/RPC2 location
Debug log:
2011/08/10 13:25:55 [debug] 22105#0: *39 http cl:1886 max:1048576
2011/08/10 13:25:55 [debug] 22105#0: *39 rewrite phase: 2
2011/08/10 13:25:55 [debug] 22105#0: *39 ap_filter enable
2011/08/10 13:25:55 [debug] 22105#0: *39 rewrite phase: 3
2011/08/10 13:25:55 [debug] 22105#0: *39 post rewrite phase: 4
2011/08/10 13:25:55 [debug] 22105#0: *39 access phase: 5
2011/08/10 13:25:55 [debug] 22105#0: *39 posix_memalign:
000000000E1143E0:4096 @16
2011/08/10 13:25:55 [debug] 22105#0: *39 http read client request body
2011/08/10 13:25:55 [debug] 22105#0: *39 recv: fd:43 1354 of 1886
2011/08/10 13:25:55 [debug] 22105#0: *39 http client request body recv
1354
2011/08/10 13:25:55 [debug] 22105#0: *39 http client request body rest
532
2011/08/10 13:25:55 [debug] 22105#0: *39 recv: fd:43 -1 of 532
2011/08/10 13:25:55 [debug] 22105#0: *39 recv() not ready (11: Resource
temporarily unavailable)
2011/08/10 13:25:55 [debug] 22105#0: *39 http client request body recv
-2
2011/08/10 13:25:55 [debug] 22105#0: *39 http client request body rest
532
2011/08/10 13:25:55 [debug] 22105#0: *39 event timer add: 43:
60000:1312975615320
2011/08/10 13:25:55 [debug] 22105#0: *39 post event 00002BA47A8CE148
2011/08/10 13:25:55 [debug] 22105#0: *39 delete posted event
00002BA47A8CE148
2011/08/10 13:25:55 [debug] 22105#0: *39 http run request:
"/public/RPC2?"
2011/08/10 13:25:55 [debug] 22105#0: *39 http read client request body
2011/08/10 13:25:55 [debug] 22105#0: *39 recv: fd:43 532 of 532
2011/08/10 13:25:55 [debug] 22105#0: *39 http client request body recv
532
2011/08/10 13:25:55 [debug] 22105#0: *39 http client request body rest
0
2011/08/10 13:25:55 [debug] 22105#0: *39 event timer del: 43:
1312975615320
2011/08/10 13:25:55 [debug] 22105#0: *39 ap_frpc disable
2011/08/10 13:25:55 [debug] 22105#0: *39 http finalize request: -4,
"/public/RPC2?" a:1, c:2
2011/08/10 13:25:55 [debug] 22105#0: *39 http request count:2 blk:0

and a part of configuration:

        location  /public/RPC2 {
            proxy_set_header X-Forwarded-For
$proxy_add_x_forwarded_for;
            proxy_pass      http://localhost:3352;
        }

        # RPC rozhrani AP pro hitovani
        location /RPC2HIT {
            ap_frpc          on;
            ap_frpc_gsid     $ap_filter_cookie_sid;
            ap_frpc_services "hp|email";
            ap_frpc_controlserver http://skcontrol:3337/RPC2;
        }

Posted at Nginx Forum: http://forum.nginx.org/read.php?2,213552,213628#msg-213628



More information about the nginx mailing list