/* Handler function that processes incoming requests destined for the Mobwrite daemon */
static ngx_int_t
ngx_http_mobwrite_handler(ngx_http_request_t *r)
{
  ngx_int_t rc;
  ngx_http_upstream_t *upstream;
  ngx_http_mobwrite_loc_conf_t *mobwrite_conf;

  /* Create an "upstream" object that tells nginx how to call the Mobwrite daemon */
  if ((rc = ngx_http_upstream_create(r)) != NGX_OK) {
    return rc;
  }
  upstream = r->upstream;
  upstream->schema.len = sizeof("mobwrite://") - 1;
  upstream->schema.data = (u_char *)"mobwrite://";
  upstream->output.tag = (ngx_buf_tag_t)&ngx_http_mobwrite_module;
  mobwrite_conf = (ngx_http_mobwrite_loc_conf_t *)ngx_http_get_module_loc_conf(r, ngx_http_mobwrite_module);
  upstream->conf = &(mobwrite_conf->upstream);

  /* These callbacks will do the actual work of sending a request to the
     Mobwrite daemon and processing the reponse */
  upstream->create_request = ngx_http_mobwrite_create_request;
  upstream->reinit_request = ngx_http_mobwrite_reinit_request;
  upstream->process_header = ngx_http_mobwrite_process_response_header;
  upstream->abort_request = ngx_http_mobwrite_abort_request;
  upstream->finalize_request = ngx_http_mobwrite_finalize_request;

  /* Ask the nginx core to call our callbacks after the full POST body arrives. */
  rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init);
  if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
    return rc;
  }
  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;

    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_lcb_handler(ngx_http_request_t *r)
{
    ngx_int_t rc;
    ngx_http_upstream_t *u;
    ngx_lcb_loc_conf_t *llcf;

    llcf = ngx_http_get_module_loc_conf(r, ngx_http_couchbase_module);
    if (ngx_http_upstream_create(r) != NGX_OK) {
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

    u = r->upstream;
    u->conf = &llcf->upstream;
    u->schema.len = sizeof("couchbase://") - 1;
    u->schema.data = (u_char *) "couchbase://";
    u->output.tag = (ngx_buf_tag_t) &ngx_http_couchbase_module;
    u->create_request = ngx_lcb_create_request;
    u->reinit_request = ngx_lcb_reinit_request;
    u->process_header = ngx_lcb_process_header;
    u->abort_request = ngx_lcb_abort_request;
    u->finalize_request = ngx_lcb_finalize_request;
    u->input_filter_init = ngx_lcb_input_filter_init;
    u->input_filter = ngx_lcb_input_filter;
    u->input_filter_ctx = NULL;

    rc = ngx_http_read_client_request_body(r, ngx_lcb_upstream_init);
    if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
        ngx_http_finalize_request(r, rc);
    }

    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_tnt_handler(ngx_http_request_t *r)
{
    ngx_int_t               rc;
    ngx_http_upstream_t     *u;
    ngx_http_tnt_loc_conf_t *tlcf;

    tlcf = ngx_http_get_module_loc_conf(r, ngx_http_tnt_module);

    if (!(r->method & ngx_http_tnt_allowed_methods)
        || (r->method & tlcf->http_rest_methods
              && !tlcf->method.len && r->uri.len <= 1 /* i.e '/' */))
    {
        return NGX_HTTP_NOT_ALLOWED;
    }

    if (ngx_http_set_content_type(r) != NGX_OK
        || ngx_http_upstream_create(r) != NGX_OK)
    {
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

    u = r->upstream;

    ngx_str_set(&u->schema, "tnt://");
    u->output.tag = (ngx_buf_tag_t) &ngx_http_tnt_module;

    u->conf = &tlcf->upstream;

    rc = ngx_http_tnt_init_handlers(r, u, tlcf);
    if (rc != NGX_OK){
        return rc;
    }

    u->input_filter_init = ngx_http_tnt_filter_init;
    u->input_filter = ngx_http_tnt_filter;
    u->input_filter_ctx = r;

    u->length = 0;
    u->state = 0;

    rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init);
    if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
        return rc;
    }

    return NGX_DONE;
}
static ngx_int_t
ngx_zmx_handler(ngx_http_request_t *r)
{
    ngx_int_t                   rc;
    ngx_http_upstream_t        *u;
    ngx_zmx_ctx_t       *ctx;
    ngx_http_proxy_loc_conf_t  *plcf;

    if (ngx_http_upstream_create(r) != NGX_OK) {
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

    ctx = ngx_pcalloc(r->pool, sizeof(ngx_zmx_ctx_t));
    if (ctx == NULL) {
        return NGX_ERROR;
    }

    ngx_http_set_ctx(r, ctx, ngx_zmx_module);

    /* plcf = ngx_http_get_module_loc_conf(r, ngx_zmx_module); */

    u = r->upstream;

    u->output.tag = (ngx_buf_tag_t) &ngx_zmx_module;

    u->conf = &plcf->upstream;

    u->create_request = ngx_http_proxy_create_request;
    u->reinit_request = ngx_http_proxy_reinit_request;
    u->process_header = ngx_http_proxy_process_status_line;
    u->abort_request = ngx_http_proxy_abort_request;
    u->finalize_request = ngx_http_proxy_finalize_request;
    r->state = 0;

    u->buffering = plcf->upstream.buffering;

    /* u->pipe = ngx_pcalloc(r->pool, sizeof(ngx_event_pipe_t)); */
    /* if (u->pipe == NULL) { */
    /*     return NGX_HTTP_INTERNAL_SERVER_ERROR; */
    /* } */

    /* u->accel = 1; */

    rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init);

    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 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;
}
Beispiel #10
0
ngx_int_t
passenger_content_handler(ngx_http_request_t *r)
{
    ngx_int_t              rc;
    ngx_http_upstream_t   *u;
    passenger_loc_conf_t  *slcf;
    ngx_str_t              path, base_uri;
    u_char                *path_last, *end;
    u_char                 root_path_str[NGX_MAX_PATH + 1];
    ngx_str_t              root_path;
    size_t                 root_len, len;
    u_char                 page_cache_file_str[NGX_MAX_PATH + 1];
    ngx_str_t              page_cache_file;
    passenger_context_t   *context;
    PP_Error               error;

    if (passenger_main_conf.root_dir.len == 0) {
        return NGX_DECLINED;
    }

    slcf = ngx_http_get_module_loc_conf(r, ngx_http_passenger_module);

    /* Let the next content handler take care of this request if Phusion
     * Passenger is disabled for this URL.
     */
    if (!slcf->enabled) {
        return NGX_DECLINED;
    }

    /* Let the next content handler take care of this request if this URL
     * maps to an existing file.
     */
    path_last = ngx_http_map_uri_to_path(r, &path, &root_len, 0);
    if (path_last != NULL && file_exists(path.data, 0)) {
        return NGX_DECLINED;
    }

    /* Create a string containing the root path. This path already
     * contains a trailing slash.
     */
    end = ngx_copy(root_path_str, path.data, root_len);
    *end = '\0';
    root_path.data = root_path_str;
    root_path.len  = root_len;


    context = ngx_pcalloc(r->pool, sizeof(passenger_context_t));
    if (context == NULL) {
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }
    ngx_http_set_ctx(r, context, ngx_http_passenger_module);


    /* Find the base URI for this web application, if any. */
    if (find_base_uri(r, slcf, &base_uri)) {
        /* Store the found base URI into context->public_dir. We infer that
         * the 'public' directory of the web app equals document root + base URI.
         */
        if (slcf->document_root.data != NULL) {
            len = slcf->document_root.len + 1;
            context->public_dir.data = ngx_palloc(r->pool, sizeof(u_char) * len);
            end = ngx_copy(context->public_dir.data, slcf->document_root.data,
                           slcf->document_root.len);
        } else {
            len = root_path.len + base_uri.len + 1;
            context->public_dir.data = ngx_palloc(r->pool, sizeof(u_char) * len);
            end = ngx_copy(context->public_dir.data, root_path.data, root_path.len);
            end = ngx_copy(end, base_uri.data, base_uri.len);
        }
        *end = '\0';
        context->public_dir.len = len - 1;
        context->base_uri = base_uri;
    } else {
        /* No base URI directives are applicable for this request. So assume that
         * the web application's public directory is the document root.
         * context->base_uri is now a NULL string.
         */
        len = sizeof(u_char *) * (root_path.len + 1);
        context->public_dir.data = ngx_palloc(r->pool, len);
        end = ngx_copy(context->public_dir.data, root_path.data,
                       root_path.len);
        *end = '\0';
        context->public_dir.len  = root_path.len;
    }

    /* If there's a corresponding page cache file for this URL, then serve that
     * file instead.
     */
    page_cache_file.data = page_cache_file_str;
    page_cache_file.len  = sizeof(page_cache_file_str);
    if (map_uri_to_page_cache_file(r, &context->public_dir, path.data,
                                   path_last - path.data, &page_cache_file)) {
        return passenger_static_content_handler(r, &page_cache_file);
    }

    if (slcf->app_type.data == NULL) {
        pp_error_init(&error);
        if (slcf->app_root.data == NULL) {
            context->app_type = pp_app_type_detector_check_document_root(
                pp_app_type_detector,
                (const char *) context->public_dir.data, context->public_dir.len,
                context->base_uri.len != 0,
                &error);
        } else {
            context->app_type = pp_app_type_detector_check_app_root(
                pp_app_type_detector,
                (const char *) slcf->app_root.data, slcf->app_root.len,
                &error);
        }
        if (context->app_type == PAT_NONE) {
            return NGX_DECLINED;
        } else if (context->app_type == PAT_ERROR) {
            if (error.errnoCode == EACCES) {
                ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
                              "%s; This error means that the Nginx worker process (PID %d, "
                              "running as UID %d) does not have permission to access this file. "
                              "Please read the manual to learn how to fix this problem: "
                              "section 'Troubleshooting' -> 'Upon accessing the web app, Nginx "
                              "reports a \"Permission denied\" error'; Extra info",
                              error.message,
                              (int) getpid(),
                              (int) getuid());
            } else {
                ngx_log_error(NGX_LOG_ALERT, r->connection->log,
                              (error.errnoCode == PP_NO_ERRNO) ? 0 : error.errnoCode,
                              "%s",
                              error.message);
            }
            pp_error_destroy(&error);
            return NGX_HTTP_INTERNAL_SERVER_ERROR;
        }
    } else {
        context->app_type = pp_get_app_type2((const char *) slcf->app_type.data,
            slcf->app_type.len);
        if (context->app_type == PAT_NONE) {
            return NGX_DECLINED;
        }
    }


    /* Setup upstream stuff and prepare sending the request to the Passenger core. */

    if (ngx_http_upstream_create(r) != NGX_OK) {
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }
    u = r->upstream;

    u->schema = pp_schema_string;
    u->output.tag = (ngx_buf_tag_t) &ngx_http_passenger_module;
    set_upstream_server_address(u, &slcf->upstream_config);
    u->conf = &slcf->upstream_config;

#if (NGX_HTTP_CACHE)
    u->create_key       = create_key;
#endif
    u->create_request   = create_request;
    u->reinit_request   = reinit_request;
    u->process_header   = process_status_line;
    u->abort_request    = abort_request;
    u->finalize_request = finalize_request;
    r->state = 0;

    u->buffering = slcf->upstream_config.buffering;

    u->pipe = ngx_pcalloc(r->pool, sizeof(ngx_event_pipe_t));
    if (u->pipe == NULL) {
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

    u->pipe->input_filter = ngx_event_pipe_copy_input_filter;
    u->pipe->input_ctx = r;

    rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init);

    fix_peer_address(r);

    if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
        return rc;
    }

    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;
}
//在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;

}
static ngx_int_t
ngx_http_scgi_handler(ngx_http_request_t *r)
{
    ngx_int_t                  rc;
    ngx_http_status_t         *status;
    ngx_http_upstream_t       *u;
    ngx_http_scgi_loc_conf_t  *scf;

    if (r->subrequest_in_memory) {
        ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
                      "ngx_http_scgi_module does not support "
                      "subrequests in memory");
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

    if (ngx_http_upstream_create(r) != NGX_OK) {
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

    status = ngx_pcalloc(r->pool, sizeof(ngx_http_status_t));
    if (status == NULL) {
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

    ngx_http_set_ctx(r, status, ngx_http_scgi_module);

    scf = ngx_http_get_module_loc_conf(r, ngx_http_scgi_module);

    if (scf->scgi_lengths) {
        if (ngx_http_scgi_eval(r, scf) != NGX_OK) {
            return NGX_HTTP_INTERNAL_SERVER_ERROR;
        }
    }

    u = r->upstream;

    ngx_str_set(&u->schema, "scgi://");
    u->output.tag = (ngx_buf_tag_t) &ngx_http_scgi_module;

    u->conf = &scf->upstream;

#if (NGX_HTTP_CACHE)
    u->create_key = ngx_http_scgi_create_key;
#endif
    u->create_request = ngx_http_scgi_create_request;
    u->reinit_request = ngx_http_scgi_reinit_request;
    u->process_header = ngx_http_scgi_process_status_line;
    u->abort_request = ngx_http_scgi_abort_request;
    u->finalize_request = ngx_http_scgi_finalize_request;

    u->buffering = 1;

    u->pipe = ngx_pcalloc(r->pool, sizeof(ngx_event_pipe_t));
    if (u->pipe == NULL) {
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

    u->pipe->input_filter = ngx_event_pipe_copy_input_filter;
    u->pipe->input_ctx = r;

    rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init);

    if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
        return rc;
    }

    return NGX_DONE;
}
ngx_int_t
ngx_http_drizzle_handler(ngx_http_request_t *r)
{
    ngx_http_upstream_t            *u;
    ngx_http_drizzle_loc_conf_t    *dlcf;
#if defined(nginx_version) && nginx_version < 8017
    ngx_http_drizzle_ctx_t         *dctx;
#endif
    ngx_http_core_loc_conf_t       *clcf;
    ngx_str_t                       target;
    ngx_url_t                       url;
    ngx_connection_t               *c;

    dd("request: %p", r);
    dd("subrequest in memory: %d", (int) r->subrequest_in_memory);
    dd("connection: %p", r->connection);
    dd("connection log: %p", r->connection->log);

    if (r->subrequest_in_memory) {
        /* TODO: add support for subrequest in memory by
         * emitting output into u->buffer instead */

        ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
                      "ngx_http_drizzle_module does not support "
                      "subrequest in memory");

        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

    dlcf = ngx_http_get_module_loc_conf(r, ngx_http_drizzle_module);

    if ((dlcf->default_query == NULL) && !(dlcf->methods_set & r->method)) {
        if (dlcf->methods_set != 0) {
            return NGX_HTTP_NOT_ALLOWED;
        }

        clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                      "drizzle: missing \"drizzle_query\" in location \"%V\"",
                      &clcf->name);

        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

    dd("XXX upstream already exists? %p", r->upstream);

#if defined(nginx_version) &&                                                \
    ((nginx_version >= 7063 && nginx_version < 8000)                         \
     || nginx_version >= 8007)

    dd("creating upstream.......");
    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 */

    dd("XXX create upstream");
    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

    if (dlcf->complex_target) {
        /* variables used in the drizzle_pass directive */
        if (ngx_http_complex_value(r, dlcf->complex_target, &target)
            != NGX_OK)
        {
            dd("failed to compile");
            return NGX_ERROR;
        }

        if (target.len == 0) {
            ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                          "drizzle: handler: empty \"drizzle_pass\" target");
            return NGX_HTTP_INTERNAL_SERVER_ERROR;
        }

        url.host = target;
        url.port = 0;
        url.no_resolve = 1;

        dlcf->upstream.upstream = ngx_http_upstream_drizzle_add(r, &url);

        if (dlcf->upstream.upstream == NULL) {
            ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                          "drizzle: upstream \"%V\" not found", &target);

            return NGX_HTTP_INTERNAL_SERVER_ERROR;
        }
    }

#if defined(nginx_version) && nginx_version < 8017
    dctx = ngx_pcalloc(r->pool, sizeof(ngx_http_drizzle_ctx_t));
    if (dctx == NULL) {
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

    ngx_http_set_ctx(r, dctx, ngx_http_drizzle_module);
#endif

    u->schema.len = sizeof("drizzle://") - 1;
    u->schema.data = (u_char *) "drizzle://";

    u->output.tag = (ngx_buf_tag_t) &ngx_http_drizzle_module;

    dd("drizzle tag: %p", (void *) u->output.tag);

    u->conf = &dlcf->upstream;

    u->create_request = ngx_http_drizzle_create_request;
    u->reinit_request = ngx_http_drizzle_reinit_request;
    u->process_header = ngx_http_drizzle_process_header;
    u->abort_request = ngx_http_drizzle_abort_request;
    u->finalize_request = ngx_http_drizzle_finalize_request;

    /* we bypass the upstream input filter mechanism in
     * ngx_http_upstream_process_headers */

    u->input_filter_init = ngx_http_drizzle_input_filter_init;
    u->input_filter = ngx_http_drizzle_input_filter;
    u->input_filter_ctx = NULL;

#if defined(nginx_version) && nginx_version >= 8011
    r->main->count++;
#endif

    dd("XXX connect timeout: %d", (int) dlcf->upstream.connect_timeout);

    ngx_http_upstream_dbd_init(r);

    /* override the read/write event handler to our own */
    u->write_event_handler = ngx_http_drizzle_wev_handler;
    u->read_event_handler  = ngx_http_drizzle_rev_handler;

    /* a bit hack-ish way to return error response (clean-up part) */
    if ((u->peer.connection) && (u->peer.connection->fd == 0)) {
        c = u->peer.connection;
        u->peer.connection = NULL;

        if (c->write->timer_set) {
            ngx_del_timer(c->write);
        }

        ngx_free_connection(c);

        ngx_http_upstream_drizzle_finalize_request(r, u,
#if defined(nginx_version) && (nginx_version >= 8017)
            NGX_HTTP_SERVICE_UNAVAILABLE);
#else
            dctx->status ? dctx->status : NGX_HTTP_INTERNAL_SERVER_ERROR);
#endif
    }
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;
}
Beispiel #16
0
ngx_int_t
passenger_content_handler(ngx_http_request_t *r)
{
    ngx_int_t              rc;
    ngx_http_upstream_t   *u;
    passenger_loc_conf_t  *slcf;
    ngx_str_t              path, base_uri;
    u_char                *path_last, *end;
    u_char                 root_path_str[NGX_MAX_PATH + 1];
    ngx_str_t              root_path;
    size_t                 root, len;
    u_char                 page_cache_file_str[NGX_MAX_PATH + 1];
    ngx_str_t              page_cache_file;
    passenger_context_t   *context;

    if (passenger_main_conf.root_dir.len == 0) {
        return NGX_DECLINED;
    } else if (r->subrequest_in_memory) {
        ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
                      "ngx_http_passenger_module does not support "
                      "subrequest in memory");
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

    slcf = ngx_http_get_module_loc_conf(r, ngx_http_passenger_module);

    /* Let the next content handler take care of this request if Phusion
     * Passenger is disabled for this URL.
     */
    if (!slcf->enabled) {
        return NGX_DECLINED;
    }
    
    /* Let the next content handler take care of this request if this URL
     * maps to an existing file.
     */
    path_last = ngx_http_map_uri_to_path(r, &path, &root, 0);
    if (path_last != NULL && file_exists(path.data, 0)) {
        return NGX_DECLINED;
    }
    
    /* Create a string containing the root path. This path already
     * contains a trailing slash.
     */
    end = ngx_copy(root_path_str, path.data, root);
    *end = '\0';
    root_path.data = root_path_str;
    root_path.len  = root;
    
    
    context = ngx_pcalloc(r->pool, sizeof(passenger_context_t));
    if (context == NULL) {
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }
    ngx_http_set_ctx(r, context, ngx_http_passenger_module);
    
    
    /* Find the base URI for this web application, if any. */
    if (find_base_uri(r, slcf, &base_uri)) {
        /* Store the found base URI in context->public_dir. We infer that the 'public'
         * directory of the web application is document root + base URI.
         */
        len = root_path.len + base_uri.len + 1;
        context->public_dir.data = ngx_palloc(r->pool, sizeof(u_char) * len);
        end = ngx_copy(context->public_dir.data, root_path.data, root_path.len);
        end = ngx_copy(end, base_uri.data, base_uri.len);
        *end = '\0';
        context->public_dir.len = len - 1;
        context->base_uri = base_uri;
    } else {
        /* No base URI directives are applicable for this request. So assume that
         * the web application's public directory is the document root.
         * context->base_uri is now a NULL string.
         */
        len = sizeof(u_char *) * (root_path.len + 1);
        context->public_dir.data = ngx_palloc(r->pool, len);
        end = ngx_copy(context->public_dir.data, root_path.data,
                       root_path.len);
        *end = '\0';
        context->public_dir.len  = root_path.len;
    }
    
    /* If there's a corresponding page cache file for this URL, then serve that
     * file instead.
     */
    page_cache_file.data = page_cache_file_str;
    page_cache_file.len  = sizeof(page_cache_file_str);
    if (map_uri_to_page_cache_file(r, &context->public_dir, path.data,
                                   path_last - path.data, &page_cache_file)) {
        return passenger_static_content_handler(r, &page_cache_file);
    }
    
    context->app_type = detect_application_type(&context->public_dir);
    if (context->app_type == AP_NONE) {
        return NGX_DECLINED;
    }
    
    
    /* Setup upstream stuff and prepare sending the request to the backend. */
    
    if (ngx_http_upstream_create(r) != NGX_OK) {
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }
    u = r->upstream;
    
    u->schema = passenger_schema_string;
    u->output.tag = (ngx_buf_tag_t) &ngx_http_passenger_module;
    set_upstream_server_address(u, &slcf->upstream_config);
    u->conf = &slcf->upstream_config;

#if (NGX_HTTP_CACHE)
    u->create_key       = create_key;
#endif
    u->create_request   = create_request;
    u->reinit_request   = reinit_request;
    u->process_header   = process_status_line;
    u->abort_request    = abort_request;
    u->finalize_request = finalize_request;

    u->buffering = slcf->upstream_config.buffering;
    
    u->pipe = ngx_pcalloc(r->pool, sizeof(ngx_event_pipe_t));
    if (u->pipe == NULL) {
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

    u->pipe->input_filter = ngx_event_pipe_copy_input_filter;
    u->pipe->input_ctx = r;

    rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init);

    if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
        return rc;
    }

    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;
}
/* XXX extermely evil and not working yet */
ngx_int_t
ngx_http_echo_exec_abort_parent(ngx_http_request_t *r,
        ngx_http_echo_ctx_t *ctx)
{
#if 0
    ngx_http_postponed_request_t    *pr, *ppr;
    ngx_http_request_t              *saved_data = NULL;
    ngx_chain_t                     *out = NULL;
    /* ngx_int_t                       rc; */

    dd("aborting parent...");

    if (r == r->main || r->parent == NULL) {
        return NGX_OK;
    }

    if (r->parent->postponed) {
        dd("Found parent->postponed...");

        saved_data = r->connection->data;
        ppr = NULL;
        for (pr = r->parent->postponed; pr->next; pr = pr->next) {
            if (pr->request == NULL) {
                continue;
            }

            if (pr->request == r) {
                /* r->parent->postponed->next = pr; */
                dd("found the current subrequest");
                out = pr->out;
                continue;
            }

            /* r->connection->data = pr->request; */
            dd("finalizing the subrequest...");
            ngx_http_upstream_create(pr->request);
            pr->request->upstream = NULL;

            if (ppr == NULL) {
                r->parent->postponed = pr->next;
                ppr = pr->next;
            } else {
                ppr->next = pr->next;
                ppr = pr->next;
            }
        }
    }

    r->parent->postponed->next = NULL;

    /*
    r->connection->data = r->parent;
    r->connection->buffered = 0;

    if (out != NULL) {
        dd("trying to send more stuffs for the parent");
        ngx_http_output_filter(r->parent, out);
    }
    */

    /* ngx_http_send_special(r->parent, NGX_HTTP_LAST); */

    if (saved_data) {
        r->connection->data = saved_data;
    }

    dd("terminating the parent request");

    return ngx_http_echo_send_chain_link(r, ctx, NULL /* indicate LAST */);

    /* ngx_http_upstream_create(r); */

    /* ngx_http_finalize_request(r->parent, NGX_ERROR); */
#endif

    return NGX_OK;
}
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_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_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_tcp_proxy_handler(ngx_http_request_t *r)
{
    ngx_http_upstream_t            *u = NULL;
    ngx_http_downstream_t          *d = NULL;
    ngx_http_tcp_proxy_loc_conf_t  *tlcf = NULL;

    if (!(r->method & (NGX_HTTP_CONNECT))) {
        return NGX_HTTP_NOT_ALLOWED;
    }

    tlcf = ngx_http_get_module_loc_conf(r, ngx_http_tcp_proxy_module);

    if (ngx_http_upstream_create(r) != NGX_OK) {
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

    u = r->upstream;

	if (ngx_http_dyconfig_enabled(r)){

		if(ngx_http_proxy_switch_set_upstream_srv_conf(r, u) != NGX_OK){

			return NGX_HTTP_INTERNAL_SERVER_ERROR;
		}

		if (u->uscf->domain == 1){
			if (ngx_http_proxy_switch_eval(r, 
						tlcf->proxy_lengths, tlcf->proxy_values) != NGX_OK){

				return NGX_HTTP_INTERNAL_SERVER_ERROR;
			}
		}

	}else{

		if (ngx_http_proxy_switch_eval(r, 
					tlcf->proxy_lengths, tlcf->proxy_values) != NGX_OK){

			return NGX_HTTP_INTERNAL_SERVER_ERROR;
		}
	}

    u->output.tag = (ngx_buf_tag_t) &ngx_http_tcp_proxy_module;

	u->conf = &tlcf->upstream;

	u->create_established_response = ngx_http_tcp_proxy_create_established_response;
	u->create_request = ngx_http_tcp_proxy_create_request;
	u->reinit_request = ngx_http_tcp_proxy_reinit_request;
	u->process_header = ngx_http_tcp_proxy_process_header;
	u->abort_request = ngx_http_tcp_proxy_abort_request;
	u->finalize_request = ngx_http_tcp_proxy_finalize_request;
	r->state = 0;

	if( ngx_http_downstream_create(r,u) != NGX_OK){
		return NGX_HTTP_INTERNAL_SERVER_ERROR;
	}

	d = u->downstream;
    d->output.tag = (ngx_buf_tag_t) &ngx_http_tcp_proxy_module;
	d->process_header = ngx_http_tcp_proxy_downstream_process_header;
	d->input_filter = NULL;

	return ngx_http_proxy_switch_start(r);
}
ngx_int_t
ngx_http_ajp_handler(ngx_http_request_t *r)
{
    ngx_int_t                 rc;
    ngx_http_upstream_t      *u;
    ngx_http_ajp_ctx_t       *a;
    ngx_http_ajp_loc_conf_t  *alcf;

    if (r->subrequest_in_memory) {
        ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
                      "ngx_ajp_module does not support "
                      "subrequest in memory");
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

    if (ngx_http_upstream_create(r) != NGX_OK) {
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

    a = ngx_pcalloc(r->pool, sizeof(ngx_http_ajp_ctx_t));
    if (a == NULL) {
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

    a->state = ngx_http_ajp_st_init_state;
    a->pstate = ngx_http_ajp_pst_init_state;

    ngx_http_set_ctx(r, a, ngx_http_ajp_module);

    alcf = ngx_http_get_module_loc_conf(r, ngx_http_ajp_module);

    if (alcf->ajp_lengths) {
        if (ngx_http_ajp_eval(r, alcf) != NGX_OK) {
            return NGX_HTTP_INTERNAL_SERVER_ERROR;
        }
    }

    u = r->upstream;

    u->schema.len = sizeof("ajp://") - 1;
    u->schema.data = (u_char *) "ajp://";

    u->output.tag = (ngx_buf_tag_t) &ngx_http_ajp_module;

    u->conf = &alcf->upstream;

#if (NGX_HTTP_CACHE)
    u->create_key = ngx_http_ajp_create_key;
#endif
    u->create_request = ngx_http_ajp_create_request;
    u->reinit_request = ngx_http_ajp_reinit_request;
    u->process_header = ngx_http_ajp_process_header;
    u->abort_request = ngx_http_ajp_abort_request;
    u->finalize_request = ngx_http_ajp_finalize_request;

    u->buffering = 1;

    u->pipe = ngx_pcalloc(r->pool, sizeof(ngx_event_pipe_t));
    if (u->pipe == NULL) {
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

    u->pipe->input_filter = ngx_http_ajp_input_filter;
    u->pipe->input_ctx = r;
    u->input_filter_init = ngx_http_ajp_input_filter_init;

    rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init);

    if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
        return rc;
    }

    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  *mlcf;

    if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD|NGX_HTTP_POST))) {
        return NGX_HTTP_NOT_ALLOWED;
    }

    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, "redis://");
    u->output.tag = (ngx_buf_tag_t) &ngx_http_redis_module;

    mlcf = ngx_http_get_module_loc_conf(r, ngx_http_redis_module);

    u->conf = &mlcf->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;

    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;
    ctx->command_hash = mlcf->command_hash;

    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;

    r->main->count++;

    //ngx_http_upstream_init(r);
    rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init);

    if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
        return rc;
    }

    return NGX_DONE;
}
Beispiel #25
0
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_http_request_t *
ngx_http_poller_request(ngx_http_poller_t *poller)
{
  ngx_connection_t           *c;
  ngx_http_request_t         *r;
  ngx_http_upstream_t        *u;
  ngx_log_t                  *log;
  ngx_http_log_ctx_t         *ctx;
  ngx_http_core_main_conf_t  *cmcf;
  ngx_http_conf_ctx_t        *cctx;
  ngx_pool_t                 *cpool = NULL;
  ngx_pool_t                 *rpool = NULL;
  ngx_time_t                 *tp;
  struct sockaddr_in         *sin;

  log = &poller->log;
  log->log_level = NGX_LOG_DEBUG_CONNECTION | NGX_LOG_DEBUG_ALL;

  /* using connection_pool_size default */
  cpool = ngx_create_pool(256, log);
  if (cpool == NULL) {
    return ngx_http_poller_destroy_pools(cpool, rpool);
  }

  c = ngx_pcalloc(poller->pool, sizeof(ngx_connection_t));
  if (c == NULL) {
    return ngx_http_poller_destroy_pools(cpool, rpool);
  }

  c->read = ngx_pcalloc(cpool, sizeof(ngx_event_t));
  if (c->read == NULL) {
    return ngx_http_poller_destroy_pools(cpool, rpool);
  }

  c->write = ngx_pcalloc(cpool, sizeof(ngx_event_t));
  if (c->write == NULL) {
    return ngx_http_poller_destroy_pools(cpool, rpool);
  }

  c->local_sockaddr = ngx_pcalloc(cpool, sizeof(struct sockaddr_in));
  if (c->local_sockaddr == NULL) {
    return ngx_http_poller_destroy_pools(cpool, rpool);
  }

  c->pool = cpool;
  c->log = log;

  c->local_sockaddr->sa_family = AF_INET;
  sin = (struct sockaddr_in *)c->local_sockaddr;
  sin->sin_addr.s_addr = 0x0100007f;

  c->read->log = log;
  c->write->log = log;

  c->log->log_level = NGX_LOG_DEBUG_CONNECTION | NGX_LOG_DEBUG_ALL;
  c->requests++;

  /* using request_pool_size default */
  rpool = ngx_create_pool(4096, log);
  if (rpool == NULL) {
    return ngx_http_poller_destroy_pools(cpool, rpool);
  }

  r = ngx_pcalloc(rpool, sizeof(ngx_http_request_t));
  if (r == NULL) {
    return ngx_http_poller_destroy_pools(cpool, rpool);
  }

  r->pool = rpool;
  r->connection = c;

  cctx = (ngx_http_conf_ctx_t *)ngx_cycle->conf_ctx[ngx_http_module.index];

  r->main_conf = cctx->main_conf;
  r->srv_conf = cctx->srv_conf;
  r->loc_conf = cctx->loc_conf;

  if (ngx_list_init(&r->headers_out.headers, r->pool, 20,
                    sizeof(ngx_table_elt_t)) != NGX_OK) {
    return ngx_http_poller_destroy_pools(cpool, rpool);
  }

  r->ctx = ngx_pcalloc(r->pool, sizeof(void *) * ngx_http_max_module);
  if (r->ctx == NULL) {
    return ngx_http_poller_destroy_pools(cpool, rpool);
  }

  cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);

  r->variables = ngx_pcalloc(r->pool, cmcf->variables.nelts
                             * sizeof(ngx_http_variable_value_t));
  if (r->variables == NULL) {
    return ngx_http_poller_destroy_pools(cpool, rpool);
  }

  r->main = r;
  r->count = 1;

  tp = ngx_timeofday();
  r->start_sec = tp->sec;
  r->start_msec = tp->msec;

  ctx = ngx_palloc(c->pool, sizeof(ngx_http_log_ctx_t));
  if (ctx == NULL) {
    return ngx_http_poller_destroy_pools(cpool, rpool);
  }

  ctx->connection = c;
  ctx->request = r;
  ctx->current_request = r;

  c->log->data = ctx;
  c->log->action = "polling";
  c->log_error = NGX_ERROR_INFO;
  c->write->active = 1;
  c->fd = -1;
  c->data = r;

  if (ngx_http_upstream_create(r) != NGX_OK) {
    return ngx_http_poller_destroy_pools(cpool, rpool);
  }

  ngx_http_set_ctx(r, poller, ngx_http_poller_module);

  u = r->upstream;

#if (NGX_HTTP_SSL)
  if (conf->upstream.ssl != NULL) {
    u->ssl = 1;
  }
#endif

  u->output.tag = (ngx_buf_tag_t)&ngx_http_poller_module;
  u->headers_in.content_length_n = -1;
  u->conf = &poller->upstream;

  ngx_memzero(&poller->status, sizeof(ngx_http_status_t));

  u->create_request = ngx_http_poller_create_request;
  u->reinit_request = ngx_http_poller_reinit_request;
  u->process_header = ngx_http_poller_process_status_line;
  u->abort_request = ngx_http_poller_abort_request;
  u->finalize_request = ngx_http_poller_finalize_request;

  u->buffering = 1;
  u->input_filter_init = ngx_http_poller_filter_init;
  u->input_filter = ngx_http_poller_filter;
  u->input_filter_ctx = r;

  return r;
}
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框架暂停执行请求的下一个阶段
}