static ngx_int_t ngx_http_memcached_handler(ngx_http_request_t *r) { ngx_int_t rc; ngx_http_upstream_t *u; ngx_http_memcached_ctx_t *ctx; ngx_http_memcached_loc_conf_t *mlcf; if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) { return NGX_HTTP_NOT_ALLOWED; } rc = ngx_http_discard_request_body(r); if (rc != NGX_OK) { return rc; } if (ngx_http_set_content_type(r) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (ngx_http_upstream_create(r) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } u = r->upstream; ngx_str_set(&u->schema, "memcached://"); u->output.tag = (ngx_buf_tag_t) &ngx_http_memcached_module; mlcf = ngx_http_get_module_loc_conf(r, ngx_http_memcached_module); u->conf = &mlcf->upstream; u->create_request = ngx_http_memcached_create_request; u->reinit_request = ngx_http_memcached_reinit_request; u->process_header = ngx_http_memcached_process_header; u->abort_request = ngx_http_memcached_abort_request; u->finalize_request = ngx_http_memcached_finalize_request; ctx = ngx_palloc(r->pool, sizeof(ngx_http_memcached_ctx_t)); if (ctx == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } ctx->request = r; ngx_http_set_ctx(r, ctx, ngx_http_memcached_module); u->input_filter_init = ngx_http_memcached_filter_init; u->input_filter = ngx_http_memcached_filter; u->input_filter_ctx = ctx; r->main->count++; ngx_http_upstream_init(r); return NGX_DONE; }
static ngx_int_t ngx_http_mytest_handler(ngx_http_request_t *r) { //首先建立http上下文结构体ngx_http_mytest_ctx_t ngx_http_mytest_ctx_t *myctx = ngx_http_get_module_ctx(r,ngx_http_mytest_module); if(myctx == NULL){ myctx = ngx_palloc(r->pool,sizeof(ngx_http_mytest_ctx_t)); if(myctx == NULL){ return NGX_ERROR; } //将新建的上下文与请求关联起来 ngx_http_set_ctx(r,myctx,ngx_http_mytest_module); } if(ngx_http_upstream_create(r) != NGX_OK){ ngx_log_error(NGX_LOG_ERR,r->connection->log,0,"ngx_http_upstream_create() failed"); return NGX_ERROR; } //得到配置结构体ngx_http_mytest_conf_t ngx_http_mytest_conf_t *mycf = (ngx_http_mytest_conf_t*)ngx_http_get_module_loc_conf(r,ngx_http_mytest_module); ngx_http_upstream_t *u = r->upstream; //这里用配置文件中的结构体来赋给r->upstream->conf成员 u->conf = &mycf->upstream; u->buffering = mycf->upstream.buffering; //初始化resolved结构体,用来保存上游服务器的地址 u->resolved = (ngx_http_upstream_resolved_t*)ngx_pcalloc(r->pool,sizeof(ngx_http_upstream_resolved_t)); if(u->resolved == NULL){ ngx_log_error(NGX_LOG_ERR,r->connection->log,0,"ngx_pcalloc resolved error. %s.",strerror(errno)); return NGX_ERROR; } static struct sockaddr_in backendSockAddr; struct hostent *pHost = gethostbyname((char*)"www.mmkuaipai.com"); if(pHost == NULL) { ngx_log_error(NGX_LOG_ERR,r->connection->log,0,"gethostbyname fail. %s",strerror(errno)); return NGX_ERROR; } backendSockAddr.sin_family = AF_INET; backendSockAddr.sin_port = htons((in_port_t)80); char* pDmsIP = inet_ntoa(*(struct in_addr*)(pHost->h_addr_list[0])); backendSockAddr.sin_addr.s_addr = inet_addr(pDmsIP); //myctx->backendServer.data = (u_char*)pDmsIP; //myctx->backendServer.len = strlen(pDmsIP); u->resolved->sockaddr = (struct sockaddr*)&backendSockAddr; u->resolved->socklen = sizeof(struct sockaddr_in); u->resolved->naddrs = 1; u->create_request = mytest_upstream_create_request; u->process_header = mytest_process_status_line; u->finalize_request = mytest_upstream_finalize_request; r->main->count++; ngx_http_upstream_init(r); return NGX_DONE; }
static ngx_int_t ngx_http_mytest_handler(ngx_http_request_t *r) { //全局变量 ngx_http_mytest_ctx_t* myctx = ngx_http_get_module_ctx(r, ngx_http_mytest_module); if (myctx == NULL) { myctx = ngx_palloc(r->pool, sizeof(ngx_http_mytest_ctx_t)); if (myctx == NULL) return NGX_ERROR; ngx_http_set_ctx(r, myctx, ngx_http_mytest_module); } //创建upstream结构 if (ngx_http_upstream_create(r) != NGX_OK) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "[jseanj] ngx_http_upstream_create() failed"); return NGX_ERROR; } //获得conf ngx_http_mytest_conf_t *mycf = (ngx_http_mytest_conf_t *) ngx_http_get_module_loc_conf(r, ngx_http_mytest_module); ngx_http_upstream_t *u = r->upstream; u->conf = &mycf->upstream; //conf指定了upstream的运行方式,其中的配置都很重要,它们会影响访问上游服务器的方式 u->buffering = mycf->upstream.buffering; u->resolved = (ngx_http_upstream_resolved_t*) ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_resolved_t)); if (u->resolved == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "[jseanj] ngx_pcalloc resolved error. %s.", strerror(errno)); return NGX_ERROR; } static struct sockaddr_in backendSockAddr; //struct hostent *pHost = gethostbyname((char*)"www.google.com"); struct hostent *pHost = gethostbyname((char*) "www.baidu.com"); if (pHost == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "[jseanj] gethostbyname fail. %s.", strerror(errno)); return NGX_ERROR; } backendSockAddr.sin_family = AF_INET; backendSockAddr.sin_port = htons((in_port_t) 80); char* pDmsIP = inet_ntoa(*(struct in_addr*) (pHost->h_addr_list[0])); backendSockAddr.sin_addr.s_addr = inet_addr(pDmsIP); //myctx->backendServer.data = (u_char*)pDmsIP; //myctx->backendServer.len = strlen(pDmsIP); u->resolved->sockaddr = (struct sockaddr *) &backendSockAddr; u->resolved->socklen = sizeof(struct sockaddr_in); u->resolved->naddrs = 1; u->create_request = mytest_upstream_create_request; u->process_header = mytest_process_status_line; u->finalize_request = mytest_upstream_finalize_request; r->main->count++; ngx_http_upstream_init(r); return NGX_DONE; }
static ngx_int_t ngx_http_mcset_module_init_cache_request( ngx_http_request_t *r ) { ngx_http_mcset_module_conf_t* mscf; ngx_http_upstream_t *u; ngx_mcset_module_ctx_t* ctx; mscf = ngx_http_get_module_loc_conf( r, ngx_http_mcset_module ); ctx = ngx_http_get_module_ctx( r, ngx_http_mcset_module ); if ( ctx == NULL ) { ctx = ngx_pcalloc( r->pool, sizeof( ngx_mcset_module_ctx_t ) ); if ( ctx == NULL ) { return NGX_ERROR; } ctx->cache_id.len = 32; ctx->cache_id.data = ngx_pcalloc( r->pool, ctx->cache_id.len ); ctx->r = r; ngx_http_set_ctx( r, ctx, ngx_http_mcset_module ); } if ( ngx_http_upstream_create( r ) != NGX_OK ) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } u = r->upstream; ngx_str_set( &u->schema, "memcached://" ); u->conf = &mscf->upstream; u->create_request = ngx_http_mcset_cache_create_request; u->reinit_request = ngx_http_mcset_cache_reinit_request; u->process_header = ngx_http_mcset_cache_process_header; u->abort_request = ngx_http_mcset_cache_abort_request; u->finalize_request = ngx_http_mcset_cache_finalize_request; u->input_filter_init = ngx_http_mcset_module_filter_init; u->input_filter = ngx_http_mcset_module_filter; u->input_filter_ctx = ctx; r->subrequest_in_memory = 1; r->main->count++; ngx_http_upstream_init( r ); return NGX_OK; }
static void ngx_http_poller_event(ngx_event_t *ev) { ngx_http_poller_t *poller = ev->data; ngx_http_request_t *r; ngx_time_t *tp; if (ngx_exiting) { return; } tp = ngx_timeofday(); poller->poll_start = tp->sec * 1000 + tp->msec; r = ngx_http_poller_request(poller); if (r != NULL) { ngx_http_upstream_init(r); } }
static ngx_int_t ngx_http_proxy_connect_upstream(ngx_http_request_t *r) { ngx_http_upstream_t *u; ngx_http_proxy_connect_ctx_t *ctx; ngx_http_proxy_connect_loc_conf_t *mlcf; if (ngx_http_upstream_create(r) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } mlcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_connect_module); ctx = ngx_http_get_module_ctx(r,ngx_http_proxy_connect_module); if (ngx_http_proxy_connect_eval(r, ctx, mlcf) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } ctx->request = r; u = r->upstream; ngx_str_set(&u->schema, "proxy_connect://"); u->output.tag = (ngx_buf_tag_t) &ngx_http_proxy_connect_module; mlcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_connect_module); u->conf = &mlcf->upstream; u->create_request = ngx_http_proxy_connect_create_request; u->reinit_request = ngx_http_proxy_connect_reinit_request; u->process_header = ngx_http_proxy_connect_process_header; u->abort_request = ngx_http_proxy_connect_abort_request; u->finalize_request = ngx_http_proxy_connect_finalize_request; u->input_filter_init = NULL; u->input_filter = NULL; u->input_filter_ctx = ctx; ngx_http_upstream_init(r); return NGX_DONE; }
static ngx_int_t ngx_http_mogilefs_handler(ngx_http_request_t *r) { ngx_int_t rc; ngx_http_upstream_t *u; ngx_http_mogilefs_ctx_t *ctx; ngx_http_mogilefs_loc_conf_t *mgcf; mgcf = ngx_http_get_module_loc_conf(r, ngx_http_mogilefs_module); if (mgcf->location_type == NGX_MOGILEFS_MAIN) { if(!(r->method & mgcf->methods)) { return NGX_HTTP_NOT_ALLOWED; } if(r->method & NGX_HTTP_PUT) { return NGX_DECLINED; } } switch(r->method) { case NGX_HTTP_GET: if (ngx_http_set_content_type(r) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } /* fall through */ case NGX_HTTP_DELETE: rc = ngx_http_discard_request_body(r); if (rc != NGX_OK) { return rc; } break; default: break; } u = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_t)); if (u == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } u->peer.log = r->connection->log; u->peer.log_error = NGX_ERROR_ERR; #if (NGX_THREADS) u->peer.lock = &r->connection->lock; #endif u->output.tag = (ngx_buf_tag_t) &ngx_http_mogilefs_module; u->conf = &mgcf->upstream; u->create_request = ngx_http_mogilefs_create_request; u->reinit_request = ngx_http_mogilefs_reinit_request; u->process_header = ngx_http_mogilefs_process_header; u->abort_request = ngx_http_mogilefs_abort_request; u->finalize_request = ngx_http_mogilefs_finalize_request; r->upstream = u; ctx = ngx_http_get_module_ctx(r, ngx_http_mogilefs_module); if(ctx == NULL) { ctx = ngx_palloc(r->pool, sizeof(ngx_http_mogilefs_ctx_t)); if (ctx == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } ctx->peer_addr = NULL; ctx->peer_addr_len = 0; ctx->num_paths_returned = -1; ctx->aux_params = NULL; ctx->status = 0; ngx_array_init(&ctx->sources, r->pool, 1, sizeof(ngx_http_mogilefs_src_t)); if(ngx_http_mogilefs_eval_key(r, &ctx->key) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } ngx_http_set_ctx(r, ctx, ngx_http_mogilefs_module); } u->input_filter_init = ngx_http_mogilefs_filter_init; u->input_filter = ngx_http_mogilefs_filter; u->input_filter_ctx = ctx; if (mgcf->tracker_lengths != 0) { if (ngx_http_mogilefs_eval_tracker(r, mgcf) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } } if(ngx_http_mogilefs_set_cmd(r, ctx) != NGX_OK) { return NGX_ERROR; } #if defined nginx_version && nginx_version >= 8011 r->main->count++; #endif ngx_http_upstream_init(r); return NGX_DONE; }
/* echo 处理handler */ static ngx_int_t ngx_http_echo_handler(ngx_http_request_t* r) { ngx_http_echov4_loc_conf_t* echo_conf; ngx_int_t rc; u_char* post_content = NULL; size_t post_content_len = 0; ngx_http_echov4_request_ctx_t* echo_ctx; ngx_http_upstream_t* u; echo_conf = ngx_http_get_module_loc_conf(r, ngx_http_echov4_module); // 我们模块运行时的上下文,如果没有的话,我们将进行初始化工作 echo_ctx = (ngx_http_echov4_request_ctx_t*) ngx_http_get_module_ctx(r, ngx_http_echov4_module); if (!echo_ctx){ //初始化 echo_ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_echov4_request_ctx_t)); /* 实际上calloc 已经把结构体里的数值设置为0 */ echo_ctx->current_echo_times = 0; echo_ctx->post_content = ngx_pcalloc(r->pool, sizeof(ngx_str_t)); ngx_http_set_ctx(r, echo_ctx, ngx_http_echov4_module); } rc = ngx_http_read_client_request_body(r, ngx_http_echov4_request_post_handler); if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { return rc; } if (!(r->method &(NGX_HTTP_POST))) { return NGX_HTTP_NOT_ALLOWED; } ngx_http_dump_request_headers(r); // 将post_content的数值赋值给结构体 post_content_len = ngx_http_dump_request_body(r, /* out */(void*) &post_content); echo_ctx->post_content->len = post_content_len; echo_ctx->post_content->data = post_content; u = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_t)); if (u == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } u->schema.len = sizeof("echo://") - 1; u->schema.data = (u_char *) "echo://"; u->peer.log = r->connection->log; u->peer.log_error = NGX_ERROR_ERR; #if (NGX_THREADS) u->peer.lock = &r->connection->lock; #endif u->output.tag = (ngx_buf_tag_t) &ngx_http_echov4_module; u->conf = &echo_conf->upstream; u->create_request = ngx_http_echo_create_request; u->reinit_request = ngx_http_echo_reinit_request; u->process_header = ngx_http_echo_process_header; u->abort_request = ngx_http_echo_abort_request; u->finalize_request = ngx_http_echo_finalize_request; r->upstream = u; ngx_http_upstream_init(r); return NGX_DONE; }
static ngx_int_t ngx_http_upstreamTest_handler(ngx_http_request_t *r) { static ngx_int_t visited_times = 0; ngx_http_upstreamTest_ctx_t *upstreamctx = ngx_http_get_module_ctx(r,ngx_http_upstreamTest_module); if(upstreamctx == NULL) { upstreamctx = ngx_pcalloc(r->pool,sizeof(ngx_http_upstreamTest_ctx_t)); if(upstreamctx == NULL) { return NGX_ERROR; } ngx_http_set_ctx(r,upstreamctx,ngx_http_upstream_module); } if(ngx_http_upstream_create(r) != NGX_OK) { ngx_log_error(NGX_LOG_ERR,r->connection->log,0,"ngx_http_upstream_create() failed"); return NGX_ERROR; } ngx_http_upstreamTest_conf_t *upstreamconf = (ngx_http_upstreamTest_conf_t *)ngx_http_get_module_loc_conf(r,ngx_http_upstreamTest_module); ngx_http_upstream_t *u = r->upstream; u->conf = &upstreamconf->upstream; u->buffering = upstreamconf->upstream.buffering; u->resolved = (ngx_http_upstream_resolved_t*)ngx_pcalloc(r->pool,sizeof(ngx_http_upstream_resolved_t)); if(u->resolved == NULL) { ngx_log_error(NGX_LOG_ERR,r->connection->log,0,"ngx_pcalloc resolved error. %s",strerror(errno)); return NGX_ERROR; } // static struct sockaddr_in backendSockAddr; // backendSockAddr.sin_family = AF_INET; // backendSockAddr.sin_port = htons((in_port_t)7777); // backendSockAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); // u->resolved->sockaddr = (struct sockaddr *)&backendSockAddr; // u->resolved->socklen = sizeof(struct sockaddr_in); // u->resolved->naddrs = 1; u->create_request = ngx_http_upstreamTest_create_request; u->process_header = ngx_http_upstreamTest_process_status_line; u->finalize_request = ngx_http_upstreamTest_finalize_request; // r->main->count++; // ngx_http_upstream_init(r); if(!(r->method & (NGX_HTTP_GET | NGX_HTTP_HEAD))) return NGX_HTTP_NOT_ALLOWED; u_char ngx_upstream_string[1024]; ngx_sprintf(ngx_upstream_string,"Visited times: %d",++visited_times); ngx_log_error(NGX_LOG_EMERG,r->connection->log,0,"ngx_upstream_string: %s",ngx_upstream_string); ngx_uint_t content_length = ngx_strlen(ngx_upstream_string); ngx_int_t rc; if(!(r->method & (NGX_HTTP_GET | NGX_HTTP_HEAD))) return NGX_HTTP_NOT_ALLOWED; rc = ngx_http_discard_request_body(r); if(rc != NGX_OK) { ngx_log_error(NGX_LOG_EMERG,r->connection->log,0,"discard requst_body failed!"); return rc; } ngx_str_set(&r->headers_out.content_type,"text/html"); if(r->method == NGX_HTTP_HEAD) { r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_length_n = content_length; ngx_log_error(NGX_LOG_EMERG,r->connection->log,0,"send respond head!"); return ngx_http_send_header(r); } ngx_buf_t *b; b = ngx_pcalloc(r->pool,sizeof(ngx_buf_t)); if(b == NULL) return NGX_HTTP_INTERNAL_SERVER_ERROR; ngx_chain_t out; out.buf = b; out.next = NULL; b->pos = ngx_upstream_string; b->last = ngx_upstream_string + content_length; b->memory = 1; b->last_buf = 1; r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_length_n = content_length; rc = ngx_http_send_header(r); if(rc == NGX_ERROR || rc > NGX_OK || r->header_only) return rc; ngx_http_output_filter(r,&out); r->main->count++; ngx_http_upstream_init(r); return NGX_OK; }
static ngx_int_t ngx_http_token_handler(ngx_http_request_t *r) { ngx_http_upstream_t *u; ngx_http_token_ctx_t *ctx; ngx_http_token_loc_conf_t *tlcf; if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) { return NGX_HTTP_NOT_ALLOWED; } tlcf = ngx_http_get_module_loc_conf(r, ngx_http_token_module); ngx_str_t args = r->args; ngx_str_t key = tlcf->key; ngx_uint_t i = 0; if ( args.len > (tlcf->token_len + key.len)){ for (; i < args.len; i++){ if (args.data[i] == '=' && i >= key.len && ngx_strncmp(args.data + i - key.len, key.data, key.len) == 0 && (args.data[i + tlcf->token_len + 1] == '&' || (i + tlcf->token_len + 1) == args.len)){ break; } } } if ( i < key.len || (args.len - i) < tlcf->token_len){ ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, "token:%V pos:%d args:%V.", &tlcf->key, i, &args); return NGX_HTTP_FORBIDDEN; } u = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_t)); if (u == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } u->schema = tlcf->upstream.schema; u->peer.log = r->connection->log; u->peer.log_error = NGX_ERROR_ERR; #if (NGX_THREADS) u->peer.lock = &r->connection->lock; #endif u->output.tag = (ngx_buf_tag_t) &ngx_http_token_module; u->conf = &tlcf->upstream; u->create_request = ngx_http_token_create_request; u->process_header = ngx_http_token_process_header; u->abort_request = ngx_http_token_abort_request; u->finalize_request = ngx_http_token_finalize_request; ctx = ngx_palloc(r->pool, sizeof(ngx_http_token_ctx_t)); if (ctx == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } r->upstream = u; ctx->rest = NGX_HTTP_MEMCACHED_END; ctx->request = r; ctx->index = i; ngx_http_set_ctx(r, ctx, ngx_http_token_module); ngx_http_upstream_init(r); return NGX_DONE; }
//在ngx_http_mytest_handler方法中启动upstream static ngx_int_t ngx_http_mytest_handler(ngx_http_request_t *r) { //首先建立HTTP上下文结构体 ngx_http_mytest_ctx_t *myctx = ngx_http_get_module_ctx(r, ngx_http_mytest_module); if(myctx == NULL){ myctx = ngx_palloc(r->pool, sizeof(ngx_http_mytest_ctx_t)); if(myctx == NULL){ return NGX_ERROR; } //将新建的上下文与请求联系起来 ngx_http_set_ctx(r, myctx, ngx_http_mytest_module); } //对每一个要使用upstream的请求,必须调用且只能调用一次ngx_http_upstream_create方法, //它会初始化r->upstream成员 if(ngx_http_upstream_create(r) != NGX_OK){ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "ngx_http_upstream_create() failed"); return NGX_ERROR; } //得到配置结构体ngx_http_mytest_conf_t ngx_http_mytest_conf_t *mycf = (ngx_http_mytest_conf_t *) ngx_http_get_module_loc_conf(r, ngx_http_mytest_module); ngx_http_upstream_t *u = r->upstream; //这里用配置文件中的结构体来赋值给r->upstream->conf成员 u->conf = &mycf->upstream; u->buffering = mycf->upstream.buffering; //以下代码开始初始化resolved结构体,用来保存上游服务器的地址 u->resolved = (ngx_http_upstream_resolved_t *)ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_resolved_t)); if(u->resolved == NULL){ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "ngx_pcalloc resolved error. %s.", strerror(errno)); return NGX_ERROR; } //这里的上游服务器是www.bing.com static struct sockaddr_in backendSockAddr; struct hostent *pHost = gethostbyname((char*)"bing.com"); if(pHost == NULL){ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "gethostbyname fail. %s.", strerror(errno)); return NGX_ERROR; } //访问上游服务器的80端口 backendSockAddr.sin_family = AF_INET; backendSockAddr.sin_port = htons((in_port_t)80); char *pDmsIP = inet_ntoa(*(struct in_addr*)(pHost->h_addr_list[0])); backendSockAddr.sin_addr.s_addr = inet_addr(pDmsIP); //myctx->backendServer.data = (u_char*)pDmsIP; //myctx->backendServer.len = strlen(pDmsIP); //将地址设置到resolved成员中 u->resolved->sockaddr = (struct sockaddr *)&backendSockAddr; u->resolved->socklen = sizeof(struct sockaddr_in); u->resolved->naddrs = 1; //设置三个必须实现的回调方法 u->create_request = mytest_upstream_create_request; u->process_header = mytest_process_status_line; u->finalize_request = mytest_upstream_finalize_request; //这里必须将count成员加1 r->main->count++; //启动upstream ngx_http_upstream_init(r); //必须返回NGX_DONE return NGX_DONE; }
ngx_int_t ngx_http_redis2_handler(ngx_http_request_t *r) { ngx_int_t rc; ngx_http_upstream_t *u; ngx_http_redis2_ctx_t *ctx; ngx_http_redis2_loc_conf_t *rlcf; ngx_str_t target; ngx_url_t url; rc = ngx_http_discard_request_body(r); if (rc != NGX_OK) { return rc; } if (ngx_http_set_content_type(r) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (ngx_http_upstream_create(r) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } u = r->upstream; rlcf = ngx_http_get_module_loc_conf(r, ngx_http_redis2_module); if (rlcf->complex_target) { /* variables used in the redis2_pass directive */ if (ngx_http_complex_value(r, rlcf->complex_target, &target) != NGX_OK) { return NGX_ERROR; } if (target.len == 0) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "handler: empty \"redis2_pass\" target"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } url.host = target; url.port = 0; url.no_resolve = 1; rlcf->upstream.upstream = ngx_http_redis2_upstream_add(r, &url); if (rlcf->upstream.upstream == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "redis2: upstream \"%V\" not found", &target); return NGX_HTTP_INTERNAL_SERVER_ERROR; } } ngx_str_set(&u->schema, "redis2://"); u->output.tag = (ngx_buf_tag_t) &ngx_http_redis2_module; u->conf = &rlcf->upstream; u->create_request = ngx_http_redis2_create_request; u->reinit_request = ngx_http_redis2_reinit_request; u->process_header = ngx_http_redis2_process_header; u->abort_request = ngx_http_redis2_abort_request; u->finalize_request = ngx_http_redis2_finalize_request; ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_redis2_ctx_t)); if (ctx == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } ctx->request = r; ctx->state = NGX_ERROR; ngx_http_set_ctx(r, ctx, ngx_http_redis2_module); u->input_filter_init = ngx_http_redis2_filter_init; u->input_filter = ngx_http_redis2_filter; u->input_filter_ctx = ctx; r->main->count++; ngx_http_upstream_init(r); return NGX_DONE; }
static ngx_int_t ngx_http_redis_handler(ngx_http_request_t *r) { ngx_int_t rc; ngx_http_upstream_t *u; ngx_http_redis_ctx_t *ctx; ngx_http_redis_loc_conf_t *rlcf; if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) { return NGX_HTTP_NOT_ALLOWED; } rc = ngx_http_discard_request_body(r); if (rc != NGX_OK) { return rc; } if (ngx_http_set_content_type(r) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } #if defined nginx_version && nginx_version >= 8011 if (ngx_http_upstream_create(r) != NGX_OK) { #else rlcf = ngx_http_get_module_loc_conf(r, ngx_http_redis_module); u = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_t)); if (u == NULL) { #endif return NGX_HTTP_INTERNAL_SERVER_ERROR; } #if defined nginx_version && nginx_version >= 8011 u = r->upstream; #endif #if defined nginx_version && nginx_version >= 8037 ngx_str_set(&u->schema, "redis://"); #else u->schema.len = sizeof("redis://") - 1; u->schema.data = (u_char *) "redis://"; #endif #if defined nginx_version && nginx_version >= 8011 u->output.tag = (ngx_buf_tag_t) &ngx_http_redis_module; #else u->peer.log = r->connection->log; u->peer.log_error = NGX_ERROR_ERR; #endif #if defined nginx_version && nginx_version >= 8011 rlcf = ngx_http_get_module_loc_conf(r, ngx_http_redis_module); #else u->output.tag = (ngx_buf_tag_t) &ngx_http_redis_module; #endif u->conf = &rlcf->upstream; u->create_request = ngx_http_redis_create_request; u->reinit_request = ngx_http_redis_reinit_request; u->process_header = ngx_http_redis_process_header; u->abort_request = ngx_http_redis_abort_request; u->finalize_request = ngx_http_redis_finalize_request; #if defined nginx_version && nginx_version < 8011 r->upstream = u; #endif ctx = ngx_palloc(r->pool, sizeof(ngx_http_redis_ctx_t)); if (ctx == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } ctx->rest = NGX_HTTP_REDIS_END; ctx->request = r; ngx_http_set_ctx(r, ctx, ngx_http_redis_module); u->input_filter_init = ngx_http_redis_filter_init; u->input_filter = ngx_http_redis_filter; u->input_filter_ctx = ctx; #if defined nginx_version && nginx_version >= 8011 r->main->count++; #endif ngx_http_upstream_init(r); return NGX_DONE; } static ngx_int_t ngx_http_redis_create_request(ngx_http_request_t *r) { size_t len, i; ngx_buf_t *b; ngx_chain_t *cl; ngx_http_redis_ctx_t *ctx; ngx_http_variable_value_t *vv[2]; ngx_http_redis_loc_conf_t *rlcf; //The start of the unified protocol GET request const char *get_request_start = "*2\r\n$3\r\nGET\r\n$"; //Buffer to store the char version of the key - max size char key_len_buf[8]; //Bad code //TODO: use ngx_get_num_size( to remove the need for this const char* key_len_ptr = &key_len_buf[0]; int key_len; rlcf = ngx_http_get_module_loc_conf(r, ngx_http_redis_module); vv[0] = ngx_http_get_indexed_variable(r, ngx_http_redis_db_index); /* * If user do not select redis database in nginx.conf by redis_db * variable, just add size of "select 0" to request. This is add * some overhead in talk with redis, but this way simplify parsing * the redis answer in ngx_http_redis_process_header(). */ if (vv[0] == NULL || vv[0]->not_found || vv[0]->len == 0) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "select 0 redis database" ); len = sizeof("select 0") - 1; } else { len = sizeof("select ") - 1 + vv[0]->len; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "select %s redis database", vv[0]->data); } len += sizeof(CRLF) - 1; vv[1] = ngx_http_get_indexed_variable(r, rlcf->index); /* If nginx.conf have no redis_key return error. */ if (vv[1] == NULL || vv[1]->not_found || vv[1]->len == 0) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "the \"$redis_key\" variable is not set"); return NGX_ERROR; } key_len = sprintf(key_len_buf,"%d",vv[1]->len); //Work out how long the request is going to be //14 = length of request_start len += 14 + key_len + sizeof(CRLF) - 1 + vv[1]->len + sizeof(CRLF) - 1; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "redis request length: %d", len); /* Create temporary buffer for request with size len. */ b = ngx_create_temp_buf(r->pool, len); if (b == NULL) { return NGX_ERROR; } cl = ngx_alloc_chain_link(r->pool); if (cl == NULL) { return NGX_ERROR; } cl->buf = b; cl->next = NULL; r->upstream->request_bufs = cl; /* Add "select " for request. */ *b->last++ = 's'; *b->last++ = 'e'; *b->last++ = 'l'; *b->last++ = 'e'; *b->last++ = 'c'; *b->last++ = 't'; *b->last++ = ' '; /* Get context redis_db from configuration file. */ ctx = ngx_http_get_module_ctx(r, ngx_http_redis_module); ctx->key.data = b->last; /* * Add "0" as redis number db to request if redis_db undefined, * othervise add real number from context. */ if (vv[0] == NULL || vv[0]->not_found || vv[0]->len == 0) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "select 0 redis database" ); *b->last++ = '0'; } else { b->last = ngx_copy(b->last, vv[0]->data, vv[0]->len); ctx->key.len = b->last - ctx->key.data; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "select %V redis database", &ctx->key); } /* Add "\r\n". */ *b->last++ = CR; *b->last++ = LF; /* Add "get" command with space. */ for(i=0;i<14;i++){ *b->last++ = get_request_start[i]; } /* Add length */ while(key_len != 0){ *b->last++ = *key_len_ptr; key_len--; key_len_ptr ++; } /* Add one more "\r\n". */ *b->last++ = CR; *b->last++ = LF; /* Get context redis_key from nginx.conf. */ ctx = ngx_http_get_module_ctx(r, ngx_http_redis_module); ctx->key.data = b->last; /* Copy the key into the request buffer */ b->last = ngx_copy(b->last, vv[1]->data, vv[1]->len); ctx->key.len = b->last - ctx->key.data; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http redis request: \"%V\"", &ctx->key); /* Add one more "\r\n". */ *b->last++ = CR; *b->last++ = LF; /* * Summary, the request looks like this: * "select $redis_db\r\nget $redis_key\r\n", where * $redis_db and $redis_key are variable's values. */ return NGX_OK; }
static ngx_int_t ngx_http_memcached_handler(ngx_http_request_t *r) { ngx_int_t rc; ngx_http_upstream_t *u; ngx_http_memcached_ctx_t *ctx; ngx_http_memcached_loc_conf_t *mlcf; if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) { return NGX_HTTP_NOT_ALLOWED; } rc = ngx_http_discard_request_body(r); if (rc != NGX_OK) { return rc; } if (ngx_http_set_content_type(r) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } mlcf = ngx_http_get_module_loc_conf(r, ngx_http_memcached_module); u = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_t)); if (u == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } u->schema.len = sizeof("memcached://") - 1; u->schema.data = (u_char *) "memcached://"; u->peer.log = r->connection->log; u->peer.log_error = NGX_ERROR_ERR; #if (NGX_THREADS) u->peer.lock = &r->connection->lock; #endif u->output.tag = (ngx_buf_tag_t) &ngx_http_memcached_module; u->conf = &mlcf->upstream; u->create_request = ngx_http_memcached_create_request; u->reinit_request = ngx_http_memcached_reinit_request; u->process_header = ngx_http_memcached_process_header; u->abort_request = ngx_http_memcached_abort_request; u->finalize_request = ngx_http_memcached_finalize_request; r->upstream = u; ctx = ngx_palloc(r->pool, sizeof(ngx_http_memcached_ctx_t)); if (ctx == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } ctx->rest = NGX_HTTP_MEMCACHED_END; ctx->request = r; ngx_http_set_ctx(r, ctx, ngx_http_memcached_module); u->input_filter_init = ngx_http_memcached_filter_init; u->input_filter = ngx_http_memcached_filter; u->input_filter_ctx = ctx; ngx_http_upstream_init(r); return NGX_DONE; }
static ngx_int_t ngx_http_memcached_handler(ngx_http_request_t *r) { ngx_int_t rc; ngx_http_upstream_t *u; ngx_http_memcached_ctx_t *ctx; ngx_http_memcached_loc_conf_t *mlcf; u_char *cmd; ngx_int_t type; /* GET for get/delete */ /* POST for set/add/replace */ if (r->method & (NGX_HTTP_GET | NGX_HTTP_HEAD)) { if (NGX_OK != (rc = ngx_http_discard_request_body(r))) return rc; } else if (!(r->method & NGX_HTTP_POST)) return NGX_HTTP_NOT_ALLOWED; /* last unit of uri is command of memcache */ for (cmd = r->uri.data + r->uri.len; r->uri.data < cmd;) if (*--cmd == '/') break; if (cmd == r->uri.data) return NGX_HTTP_BAD_REQUEST; ++cmd; if (!(ngx_memcmp(cmd, "get", sizeof("get") - 1) && ngx_memcmp(cmd, "gets", sizeof("gets") - 1))) type = NGX_HTTP_MEMCACHED_GET; else if (!(ngx_memcmp(cmd, "set", sizeof("set") - 1) && ngx_memcmp(cmd, "add", sizeof("add") - 1) && ngx_memcmp(cmd, "replace", sizeof("replace") - 1))) type = NGX_HTTP_MEMCACHED_SET; else if (!ngx_memcmp(cmd, "delete", sizeof("delete") - 1)) type = NGX_HTTP_MEMCACHED_DEL; else if (!ngx_memcmp(cmd, "cas", sizeof("cas") - 1)) type = NGX_HTTP_MEMCACHED_CAS; else return NGX_HTTP_BAD_REQUEST; if (NGX_OK != ngx_http_set_content_type(r)) return NGX_HTTP_INTERNAL_SERVER_ERROR; if (NGX_OK != ngx_http_upstream_create(r)) return NGX_HTTP_INTERNAL_SERVER_ERROR; u = r->upstream; ngx_str_set(&u->schema, "memcached://"); u->output.tag = (ngx_buf_tag_t)&ngx_http_memcached_module; mlcf = ngx_http_get_module_loc_conf(r, ngx_http_memcached_module); u->conf = &mlcf->upstream; u->create_request = ngx_http_memcached_create_request; u->reinit_request = ngx_http_memcached_reinit_request; u->process_header = ngx_http_memcached_process_header; u->abort_request = ngx_http_memcached_abort_request; u->finalize_request = ngx_http_memcached_finalize_request; /* context */ if (!(ctx = ngx_palloc(r->pool, sizeof(ngx_http_memcached_ctx_t)))) return NGX_HTTP_INTERNAL_SERVER_ERROR; ctx->request = r; ctx->cmd.data = cmd; ctx->cmd.len = r->uri.len - (ctx->cmd.data - r->uri.data); ctx->type = type; ngx_http_set_ctx(r, ctx, ngx_http_memcached_module); u->input_filter_init = ngx_http_memcached_filter_init; u->input_filter = ngx_http_memcached_filter; u->input_filter_ctx = ctx; if (r->method & NGX_HTTP_POST) { /* POST */ if (NGX_HTTP_SPECIAL_RESPONSE <= (rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init))) return rc; } else { /* GET */ ++r->main->count; ngx_http_upstream_init(r); } return NGX_DONE; }
static ngx_int_t ngx_http_redis_handler(ngx_http_request_t *r) { ngx_int_t rc; ngx_http_upstream_t *u; ngx_http_redis_ctx_t *ctx; ngx_http_redis_loc_conf_t *rlcf; if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) { return NGX_HTTP_NOT_ALLOWED; } rc = ngx_http_discard_request_body(r); if (rc != NGX_OK) { return rc; } if (ngx_http_set_content_type(r) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } #if defined nginx_version && nginx_version >= 8011 if (ngx_http_upstream_create(r) != NGX_OK) { #else rlcf = ngx_http_get_module_loc_conf(r, ngx_http_redis_module); u = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_t)); if (u == NULL) { #endif return NGX_HTTP_INTERNAL_SERVER_ERROR; } #if defined nginx_version && nginx_version >= 8011 u = r->upstream; #endif #if defined nginx_version && nginx_version >= 8037 ngx_str_set(&u->schema, "redis://"); #else u->schema.len = sizeof("redis://") - 1; u->schema.data = (u_char *) "redis://"; #endif #if defined nginx_version && nginx_version >= 8011 u->output.tag = (ngx_buf_tag_t) &ngx_http_redis_module; #else u->peer.log = r->connection->log; u->peer.log_error = NGX_ERROR_ERR; #endif #if defined nginx_version && nginx_version >= 8011 rlcf = ngx_http_get_module_loc_conf(r, ngx_http_redis_module); #else u->output.tag = (ngx_buf_tag_t) &ngx_http_redis_module; #endif u->conf = &rlcf->upstream; u->create_request = ngx_http_redis_create_request; u->reinit_request = ngx_http_redis_reinit_request; u->process_header = ngx_http_redis_process_header; u->abort_request = ngx_http_redis_abort_request; u->finalize_request = ngx_http_redis_finalize_request; #if defined nginx_version && nginx_version < 8011 r->upstream = u; #endif ctx = ngx_palloc(r->pool, sizeof(ngx_http_redis_ctx_t)); if (ctx == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } ctx->rest = NGX_HTTP_REDIS_END; ctx->request = r; ngx_http_set_ctx(r, ctx, ngx_http_redis_module); u->input_filter_init = ngx_http_redis_filter_init; u->input_filter = ngx_http_redis_filter; u->input_filter_ctx = ctx; #if defined nginx_version && nginx_version >= 8011 r->main->count++; #endif ngx_http_upstream_init(r); return NGX_DONE; } static ngx_int_t ngx_http_redis_create_request(ngx_http_request_t *r) { size_t len; uintptr_t escape; ngx_buf_t *b; ngx_chain_t *cl; ngx_http_redis_ctx_t *ctx; ngx_http_variable_value_t *vv[2]; ngx_http_redis_loc_conf_t *rlcf; rlcf = ngx_http_get_module_loc_conf(r, ngx_http_redis_module); vv[0] = ngx_http_get_indexed_variable(r, ngx_http_redis_db_index); /* * If user do not select redis database in nginx.conf by redis_db * variable, just add size of "select 0" to request. This is add * some overhead in talk with redis, but this way simplify parsing * the redis answer in ngx_http_redis_process_header(). */ if (vv[0] == NULL || vv[0]->not_found || vv[0]->len == 0) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "select 0 redis database" ); len = sizeof("select 0") - 1; } else { len = sizeof("select ") - 1 + vv[0]->len; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "select %s redis database", vv[0]->data); } len += sizeof(CRLF) - 1; vv[1] = ngx_http_get_indexed_variable(r, rlcf->index); /* If nginx.conf have no redis_key return error. */ if (vv[1] == NULL || vv[1]->not_found || vv[1]->len == 0) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "the \"$redis_key\" variable is not set"); return NGX_ERROR; } /* Count have space required escape symbols. */ escape = 2 * ngx_escape_uri(NULL, vv[1]->data, vv[1]->len, NGX_ESCAPE_REDIS); len += sizeof("get ") - 1 + vv[1]->len + escape + sizeof(CRLF) - 1; /* Create temporary buffer for request with size len. */ b = ngx_create_temp_buf(r->pool, len); if (b == NULL) { return NGX_ERROR; } cl = ngx_alloc_chain_link(r->pool); if (cl == NULL) { return NGX_ERROR; } cl->buf = b; cl->next = NULL; r->upstream->request_bufs = cl; /* Add "select " for request. */ *b->last++ = 's'; *b->last++ = 'e'; *b->last++ = 'l'; *b->last++ = 'e'; *b->last++ = 'c'; *b->last++ = 't'; *b->last++ = ' '; /* Get context redis_db from configuration file. */ ctx = ngx_http_get_module_ctx(r, ngx_http_redis_module); ctx->key.data = b->last; /* * Add "0" as redis number db to request if redis_db undefined, * othervise add real number from context. */ if (vv[0] == NULL || vv[0]->not_found || vv[0]->len == 0) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "select 0 redis database" ); *b->last++ = '0'; } else { b->last = ngx_copy(b->last, vv[0]->data, vv[0]->len); ctx->key.len = b->last - ctx->key.data; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "select %V redis database", &ctx->key); } /* Add "\r\n". */ *b->last++ = CR; *b->last++ = LF; /* Add "get" command with space. */ *b->last++ = 'g'; *b->last++ = 'e'; *b->last++ = 't'; *b->last++ = ' '; /* Get context redis_key from nginx.conf. */ ctx = ngx_http_get_module_ctx(r, ngx_http_redis_module); ctx->key.data = b->last; /* * If no escape symbols then copy data as is, othervise use * escape-copy function. */ if (escape == 0) { b->last = ngx_copy(b->last, vv[1]->data, vv[1]->len); } else { b->last = (u_char *) ngx_escape_uri(b->last, vv[1]->data, vv[1]->len, NGX_ESCAPE_REDIS); } ctx->key.len = b->last - ctx->key.data; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http redis request: \"%V\"", &ctx->key); /* Add one more "\r\n". */ *b->last++ = CR; *b->last++ = LF; /* * Summary, the request looks like this: * "select $redis_db\r\nget $redis_key\r\n", where * $redis_db and $redis_key are variable's values. */ return NGX_OK; }
static ngx_int_t ngx_http_cwinux_handler(ngx_http_request_t *r) { ngx_int_t rc; ngx_http_upstream_t *u; ngx_http_cwinux_ctx_t *ctx; ngx_http_cwinux_loc_conf_t *mlcf; if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_POST))){ ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, "ngx_cwinux: method %V doesn't support ", &r->method_name); return NGX_HTTP_BAD_REQUEST; } mlcf = ngx_http_get_module_loc_conf(r, ngx_http_cwinux_module); if (ngx_http_set_content_type(r) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } #if defined(nginx_version) && \ ((nginx_version >= 7063 && nginx_version < 8000) \ || nginx_version >= 8007) if (ngx_http_upstream_create(r) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } u = r->upstream; #else /* 0.7.x < 0.7.63, 0.8.x < 0.8.7 */ u = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_t)); if (u == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } u->peer.log = r->connection->log; u->peer.log_error = NGX_ERROR_ERR; # if (NGX_THREADS) u->peer.lock = &r->connection->lock; # endif r->upstream = u; #endif u->schema.len = sizeof("cwinux://") - 1; u->schema.data = (u_char *) "cwinux://"; u->output.tag = (ngx_buf_tag_t) &ngx_http_cwinux_module; u->conf = &mlcf->upstream; ctx = ngx_palloc(r->pool, sizeof(ngx_http_cwinux_ctx_t)); if (ctx == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } ngx_gettimeofday(&ctx->start_time); ctx->header = false; ctx->finish = false; ctx->request = r; ngx_http_set_ctx(r, ctx, ngx_http_cwinux_module); u->create_request = ngx_http_cwinux_create_request; u->process_header = ngx_http_cwinux_process_header; u->input_filter_init = ngx_http_cwinux_empty_filter_init; u->input_filter = ngx_http_cwinux_empty_filter; u->reinit_request = ngx_http_cwinux_reinit_request; u->abort_request = ngx_http_cwinux_abort_request; u->finalize_request = ngx_http_cwinux_finalize_request; u->input_filter_ctx = ctx; if (NGX_HTTP_POST == r->method){ rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init); if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { return rc; } return NGX_DONE; } rc = ngx_http_discard_request_body(r); if (rc != NGX_OK) { return rc; } #if defined(nginx_version) && nginx_version >= 8011 r->main->count++; #endif ngx_http_upstream_init(r); return NGX_DONE; }
static ngx_int_t ngx_http_redis_handler(ngx_http_request_t *r) { ngx_int_t rc; ngx_http_upstream_t *u; ngx_http_redis_ctx_t *ctx; ngx_http_redis_loc_conf_t *rlcf; if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) { return NGX_HTTP_NOT_ALLOWED; } rc = ngx_http_discard_request_body(r); if (rc != NGX_OK) { return rc; } if (ngx_http_set_content_type(r) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } #if defined nginx_version && nginx_version >= 8011 if (ngx_http_upstream_create(r) != NGX_OK) { #else rlcf = ngx_http_get_module_loc_conf(r, ngx_http_redis_module); u = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_t)); if (u == NULL) { #endif return NGX_HTTP_INTERNAL_SERVER_ERROR; } #if defined nginx_version && nginx_version >= 8011 u = r->upstream; #endif u->schema.len = sizeof("redis://") - 1; u->schema.data = (u_char *) "redis://"; #if defined nginx_version && nginx_version >= 8011 u->output.tag = (ngx_buf_tag_t) &ngx_http_redis_module; #else u->peer.log = r->connection->log; u->peer.log_error = NGX_ERROR_ERR; #endif #if defined nginx_version && nginx_version >= 8011 rlcf = ngx_http_get_module_loc_conf(r, ngx_http_redis_module); #else u->output.tag = (ngx_buf_tag_t) &ngx_http_redis_module; #endif u->conf = &rlcf->upstream; u->create_request = ngx_http_redis_create_request; u->reinit_request = ngx_http_redis_reinit_request; u->process_header = ngx_http_redis_process_header; u->abort_request = ngx_http_redis_abort_request; u->finalize_request = ngx_http_redis_finalize_request; #if defined nginx_version && nginx_version < 8011 r->upstream = u; #endif ctx = ngx_palloc(r->pool, sizeof(ngx_http_redis_ctx_t)); if (ctx == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } ctx->rest = NGX_HTTP_REDIS_END; ctx->request = r; ngx_http_set_ctx(r, ctx, ngx_http_redis_module); u->input_filter_init = ngx_http_redis_filter_init; u->input_filter = ngx_http_redis_filter; u->input_filter_ctx = ctx; #if defined nginx_version && nginx_version >= 8011 r->main->count++; #endif ngx_http_upstream_init(r); return NGX_DONE; } static ngx_int_t ngx_http_redis_create_request(ngx_http_request_t *r) { size_t len; uintptr_t escape; ngx_buf_t *b; ngx_chain_t *cl; ngx_http_redis_ctx_t *ctx; ngx_http_variable_value_t *vv[2]; ngx_http_redis_loc_conf_t *rlcf; rlcf = ngx_http_get_module_loc_conf(r, ngx_http_redis_module); vv[0] = ngx_http_get_indexed_variable(r, rlcf->db); if (vv[0] == NULL || vv[0]->not_found || vv[0]->len == 0) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "select 0 redis database" ); len = sizeof("select 0") - 1; } else { len = sizeof("select ") - 1 + vv[0]->len; } len += sizeof(CRLF) - 1; vv[1] = ngx_http_get_indexed_variable(r, rlcf->index); if (vv[1] == NULL || vv[1]->not_found || vv[1]->len == 0) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "the \"$redis_key\" variable is not set"); return NGX_ERROR; } escape = 2 * ngx_escape_uri(NULL, vv[1]->data, vv[1]->len, NGX_ESCAPE_REDIS); len += sizeof("get ") - 1 + vv[1]->len + escape + sizeof(CRLF) - 1; b = ngx_create_temp_buf(r->pool, len); if (b == NULL) { return NGX_ERROR; } cl = ngx_alloc_chain_link(r->pool); if (cl == NULL) { return NGX_ERROR; } cl->buf = b; cl->next = NULL; r->upstream->request_bufs = cl; *b->last++ = 's'; *b->last++ = 'e'; *b->last++ = 'l'; *b->last++ = 'e'; *b->last++ = 'c'; *b->last++ = 't'; *b->last++ = ' '; ctx = ngx_http_get_module_ctx(r, ngx_http_redis_module); ctx->key.data = b->last; if (vv[0] == NULL || vv[0]->not_found || vv[0]->len == 0) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "select 0 redis database" ); *b->last++ = '0'; } else { b->last = ngx_copy(b->last, vv[0]->data, vv[0]->len); ctx->key.len = b->last - ctx->key.data; } *b->last++ = CR; *b->last++ = LF; *b->last++ = 'g'; *b->last++ = 'e'; *b->last++ = 't'; *b->last++ = ' '; ctx = ngx_http_get_module_ctx(r, ngx_http_redis_module); ctx->key.data = b->last; if (escape == 0) { b->last = ngx_copy(b->last, vv[1]->data, vv[1]->len); } else { b->last = (u_char *) ngx_escape_uri(b->last, vv[1]->data, vv[1]->len, NGX_ESCAPE_REDIS); } ctx->key.len = b->last - ctx->key.data; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http redis request: \"%V\"", &ctx->key); *b->last++ = CR; *b->last++ = LF; return NGX_OK; }
static ngx_int_t ngx_http_mytest_upstream_handler(ngx_http_request_t *r) { //首先建立http上下文结构体ngx_http_mytest_ctx_t ngx_http_mytest_upstream_ctx_t* myctx = ngx_http_get_module_ctx(r, ngx_http_mytest_upstream_module); if (myctx == NULL) { myctx = ngx_palloc(r->pool, sizeof(ngx_http_mytest_upstream_ctx_t)); if (myctx == NULL) { return NGX_ERROR; } //将新建的上下文与请求关联起来 ngx_http_set_ctx(r, myctx, ngx_http_mytest_upstream_module); } //对每1个要使用upstream的请求,必须调用且只能调用1次 //ngx_http_upstream_create方法,它会初始化r->upstream成员 if (ngx_http_upstream_create(r) != NGX_OK) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "ngx_http_upstream_create() failed"); return NGX_ERROR; } //得到配置结构体ngx_http_mytest_conf_t ngx_http_mytest_upstream_conf_t *mycf = (ngx_http_mytest_upstream_conf_t *) ngx_http_get_module_loc_conf(r, ngx_http_mytest_upstream_module); ngx_http_upstream_t *u = r->upstream; //这里用配置文件中的结构体来赋给r->upstream->conf成员 u->conf = &mycf->upstream;//把我们设置好的upstream配置信息赋值给ngx_http_request_t->upstream->conf //决定转发包体时使用的缓冲区 u->buffering = mycf->upstream.buffering; //以下代码开始初始化resolved结构体,用来保存上游服务器的地址 u->resolved = (ngx_http_upstream_resolved_t*) ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_resolved_t)); if (u->resolved == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "ngx_pcalloc resolved error. %s.", strerror(errno)); return NGX_ERROR; } //这里的上游服务器就是www.google.com static struct sockaddr_in backendSockAddr; struct hostent *pHost = gethostbyname((char*) "www.sina.com"); if (pHost == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "gethostbyname fail. %s", strerror(errno)); ngx_log_debugall(r->connection->log, 0, "yang test ############################MYTEST upstream gethostbyname error\n"); return NGX_ERROR; } //访问上游服务器的80端口 backendSockAddr.sin_family = AF_INET; backendSockAddr.sin_port = htons((in_port_t) 80); char* pDmsIP = inet_ntoa(*(struct in_addr*) (pHost->h_addr_list[0])); //char* pDmsIP = inet_ntoa(*(struct in_addr*) ("10.10.0.2")); backendSockAddr.sin_addr.s_addr = inet_addr(pDmsIP); myctx->backendServer.data = (u_char*)pDmsIP; myctx->backendServer.len = strlen(pDmsIP); ngx_log_debugall(r->connection->log, 0, "yang test ############################MYTEST upstream gethostbyname OK, addr:%s\n", pDmsIP); //将地址设置到resolved成员中 u->resolved->sockaddr = (struct sockaddr *)&backendSockAddr; u->resolved->socklen = sizeof(struct sockaddr_in); u->resolved->naddrs = 1; //设置三个必须实现的回调方法,也就是5.3.3节至5.3.5节中实现的3个方法 u->create_request = mytest_upstream_create_request; //构造http请求行和头部行 u->process_header = mytest_process_status_line; u->finalize_request = mytest_upstream_finalize_request; //这里必须将count成员加1,理由见5.1.5节 /* 这里还需要执行r->main->count++,这是在告诉HTTP框架将当前请求的引用计数加1,即告诉ngx_http_mytest_handler方法暂时不要销 毁请求,因为HTTP框架只有在引用计数为0时才能真正地销毁请求。这样的话,upstream机制接下来才能接管请求的处理工作。 */ r->main->count++; //启动upstream ngx_http_upstream_init(r); //必须返回NGX_DONE return NGX_DONE; //这时要通过返回NGX DONE告诉HTTP框架暂停执行请求的下一个阶段 }