title: Error: upstream prematurely closed connection while reading response header from upstream
body: <p>Recently I tried to implemented an Nginx extension module to save the request body to redis list (via RPUSH command) directly .</p>
  <p>However, I got a <strong>502 Bad Gateway</strong> error!</p>
  <p>The error occurs after calling ngx_http_redis_create_request, before ngx_http_redis_process_header() called [ nginx/logs/error.log ]</p>
  <p>Anyone know what is the problem?</p>
  <p>Here are the log within <strong>nginx/logs/error.log</strong></p>
  <pre><code>2015/04/20 13:56:54 [debug] 5759#0: *1 http process request line
  2015/04/20 13:56:54 [debug] 5759#0: *1 http request line: &quot;GET /test HTTP/1.1&quot;
  2015/04/20 13:56:54 [debug] 5759#0: *1 http uri: &quot;/test&quot;
  2015/04/20 13:56:54 [debug] 5759#0: *1 http args: &quot;&quot;
  2015/04/20 13:56:54 [debug] 5759#0: *1 http exten: &quot;&quot;
  2015/04/20 13:56:54 [debug] 5759#0: *1 http process request header line
  2015/04/20 13:56:54 [debug] 5759#0: *1 http header: &quot;User-Agent: Wget/1.15 (linux-gnu)&quot;
  2015/04/20 13:56:54 [debug] 5759#0: *1 http header: &quot;Accept: */*&quot;
  2015/04/20 13:56:54 [debug] 5759#0: *1 http header: &quot;Host: localhost:8989&quot;
  2015/04/20 13:56:54 [debug] 5759#0: *1 http header: &quot;Connection: Keep-Alive&quot;
  2015/04/20 13:56:54 [debug] 5759#0: *1 http header done
  2015/04/20 13:56:54 [debug] 5759#0: *1 event timer del: 3: 1429509474481
  2015/04/20 13:56:54 [debug] 5759#0: *1 test location: &quot;/&quot;
  2015/04/20 13:56:54 [debug] 5759#0: *1 test location: &quot;general/test&quot;
  2015/04/20 13:56:54 [debug] 5759#0: *1 test location: &quot;test&quot;
  2015/04/20 13:56:54 [debug] 5759#0: *1 using configuration &quot;/test&quot;
  2015/04/20 13:56:54 [debug] 5759#0: *1 http cl:-1 max:1048576
  2015/04/20 13:56:54 [debug] 5759#0: *1 generic phase: 1
  2015/04/20 13:56:54 [debug] 5759#0: *1 generic phase: 2
  2015/04/20 13:56:54 [debug] 5759#0: *1 access phase: 3
  2015/04/20 13:56:54 [debug] 5759#0: *1 access phase: 4
  2015/04/20 13:56:54 [debug] 5759#0: *1 post access phase: 5
  2015/04/20 13:56:54 [debug] 5759#0: *1 posix_memalign: 00000000012627D0:4096 @16
  2015/04/20 13:56:54 [debug] 5759#0: *1 http init upstream, client timer: 0
  2015/04/20 13:56:54 [debug] 5759#0: *1 epoll add event: fd:3 op:3 ev:80002005
  2015/04/20 13:56:54 [debug] 5759#0: *1 http cleanup add: 0000000001262788
  2015/04/20 13:56:54 [debug] 5759#0: *1 get rr peer, try: 1
  2015/04/20 13:56:54 [debug] 5759#0: *1 socket 9
  2015/04/20 13:56:54 [debug] 5759#0: *1 epoll add connection: fd:9 ev:80002005
  2015/04/20 13:56:54 [debug] 5759#0: *1 connect to 127.0.0.1:6379, fd:9 #2
  2015/04/20 13:56:54 [debug] 5759#0: *1 http upstream connect: -2
  2015/04/20 13:56:54 [debug] 5759#0: *1 posix_memalign: 000000000125B640:128 @16
  2015/04/20 13:56:54 [debug] 5759#0: *1 event timer add: 9: 60000:1429509474482
  2015/04/20 13:56:54 [debug] 5759#0: *1 http finalize request: -4, &quot;/test?&quot; a:1, c:2
  2015/04/20 13:56:54 [debug] 5759#0: *1 http request count:2 blk:0
  2015/04/20 13:56:54 [debug] 5759#0: timer delta: 1
  2015/04/20 13:56:54 [debug] 5759#0: posted events 0000000000000000
  2015/04/20 13:56:54 [debug] 5759#0: worker cycle
  2015/04/20 13:56:54 [debug] 5759#0: epoll timer: 60000
  2015/04/20 13:56:54 [debug] 5759#0: epoll: fd:3 ev:0004 d:00007F39455B51B0
  2015/04/20 13:56:54 [debug] 5759#0: *1 http run request: &quot;/test?&quot;
  2015/04/20 13:56:54 [debug] 5759#0: *1 http upstream check client, write event:1, &quot;/test&quot;
  2015/04/20 13:56:54 [debug] 5759#0: *1 http upstream recv(): -1 (11: Resource temporarily unavailable)
  2015/04/20 13:56:54 [debug] 5759#0: epoll: fd:9 ev:0004 d:00007F39455B5280
  2015/04/20 13:56:54 [debug] 5759#0: *1 http upstream request: &quot;/test?&quot;
  2015/04/20 13:56:54 [debug] 5759#0: *1 http upstream send request handler
  2015/04/20 13:56:54 [debug] 5759#0: *1 http upstream send request
  2015/04/20 13:56:54 [debug] 5759#0: *1 chain writer buf fl:0 s:30
  2015/04/20 13:56:54 [debug] 5759#0: *1 chain writer in: 0000000001262B88
  2015/04/20 13:56:54 [debug] 5759#0: *1 writev: 30
  2015/04/20 13:56:54 [debug] 5759#0: *1 chain writer out: 0000000000000000
  2015/04/20 13:56:54 [debug] 5759#0: *1 event timer del: 9: 1429509474482
  2015/04/20 13:56:54 [debug] 5759#0: *1 event timer add: 9: 60000:1429509474482
  2015/04/20 13:56:54 [debug] 5759#0: timer delta: 0
  2015/04/20 13:56:54 [debug] 5759#0: posted events 0000000000000000
  2015/04/20 13:56:54 [debug] 5759#0: worker cycle
  2015/04/20 13:56:54 [debug] 5759#0: epoll timer: 60000
  2015/04/20 13:56:54 [debug] 5759#0: epoll: fd:9 ev:0005 d:00007F39455B5280
  2015/04/20 13:56:54 [debug] 5759#0: *1 http upstream request: &quot;/test?&quot;
  2015/04/20 13:56:54 [debug] 5759#0: *1 http upstream process header
  2015/04/20 13:56:54 [debug] 5759#0: *1 recv: fd:9 0 of 0
  2015/04/20 13:56:54 [error] 5759#0: *1 upstream prematurely closed connection while reading response header from upstream, client: 127.0.0.1, server: localhost,request: &quot;GET /test HTTP/1.1&quot;, upstream: &quot;redis://127.0.0.1:6379&quot;, host: &quot;localhost:8989&quot;
  </code></pre>
  <p>The configuration in Nginx as following shown</p>
  <blockquote>
  <p>redis_pass 127.0.0.1:6379;</p>
  <p>redis_db 3;</p>
  <p>redis_key  candice;</p>
  </blockquote>
  <p>I pasted some related source code here</p>
  <pre><code>static ngx_command_t ngx_http_redis_commands[] = {
      {
          ngx_string(&quot;redis_pass&quot;),
          NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
          ngx_http_redis_pass,
          NGX_HTTP_LOC_CONF_OFFSET,
          0,
          NULL
      },
      {
          ngx_string(&quot;redis_db&quot;),
          NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
          ngx_conf_set_num_slot,
          NGX_HTTP_LOC_CONF_OFFSET,
          offsetof(ngx_http_redis_loc_conf_t, db),
          NULL
      },
      {   
          ngx_string(&quot;redis_key&quot;),
          NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
          ngx_conf_set_str_slot,
          NGX_HTTP_LOC_CONF_OFFSET,
          offsetof(ngx_http_redis_loc_conf_t, key),
          NULL
      },
      {
          ngx_string(&quot;redis_connect_timeout&quot;),
          NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
          ngx_conf_set_msec_slot,
          NGX_HTTP_LOC_CONF_OFFSET,
          offsetof(ngx_http_redis_loc_conf_t, upstream.connect_timeout),
          NULL
      },
      {
          ngx_string(&quot;redis_send_timeout&quot;),
          NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
          ngx_conf_set_msec_slot,
          NGX_HTTP_LOC_CONF_OFFSET,
          offsetof(ngx_http_redis_loc_conf_t, upstream.send_timeout),
          NULL
      },
      {
          ngx_string(&quot;redis_read_timeout&quot;),
          NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
          ngx_conf_set_msec_slot,
          NGX_HTTP_LOC_CONF_OFFSET,
          offsetof(ngx_http_redis_loc_conf_t, upstream.read_timeout),
          NULL
      },
      ngx_null_command,
  };
  </code></pre>
  <p><strong>ngx_http_redis_handler</strong></p>
  <pre><code>static ngx_int_t
  ngx_http_redis_handler(ngx_http_request_t *r)
  {
      ngx_http_redis_loc_conf_t *rlcf;
      ngx_http_upstream_t *u;
      ngx_int_t rc;
  
      /* set up upstream structure */
      if (ngx_http_upstream_create(r) != NGX_OK)
      {
          ngx_log_error(NGX_LOG_ERR, r-&gt;connection-&gt;log, 0, &quot;ngx_http_upstream_create() failed&quot;);
          return NGX_HTTP_INTERNAL_SERVER_ERROR;
      }
  
      u = r-&gt;upstream;
      ngx_str_set(&amp;u-&gt;schema, &quot;redis://&quot;);
  
      rlcf = ngx_http_get_module_loc_conf(r, ngx_http_redis_module);
      u-&gt;conf = &amp;rlcf-&gt;upstream;
      
      /* attach the callback functions */
      u-&gt;create_request = ngx_http_redis_create_request;
      u-&gt;reinit_request = ngx_http_redis_reinit_request;
      u-&gt;process_header = ngx_http_redis_process_header;
      u-&gt;finalize_request = ngx_http_redis_finalize_request;
  
      rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init);
      if (rc &gt; NGX_HTTP_SPECIAL_RESPONSE)
          return rc;
      return NGX_DONE;
  }
  </code></pre>
  <p><strong>ngx_http_redis_create_request</strong>
  To send command <em>&quot;SELECT \r\nRPUSH  \r\n&quot; to redis</em></p>
  <pre><code>/* callbacks */
  static ngx_int_t ngx_http_redis_create_request(ngx_http_request_t *r)
  {
      ngx_http_redis_loc_conf_t * rlcf;
      ngx_chain_t *cl, *body;
      ngx_buf_t *buf, *b;
  
      /* Do not forget to change the following offset when modifying the query string */
      ngx_str_t query = ngx_string(&quot;SELECT %ui\r\nRPUSH %V &quot;);
      size_t len = query.len - 5;
  
      rlcf = ngx_http_get_module_loc_conf(r, ngx_http_redis_module);
      len += (rlcf-&gt;db &gt; 9 ? 2 : 1) + rlcf-&gt;key.len;
  
      /* Create temporary buffer for request with size len. */
      buf = ngx_create_temp_buf(r-&gt;pool, len);
      if (buf == NULL) {
          return NGX_ERROR;
      }
      ngx_snprintf(buf-&gt;pos, len, (char*)query.data, rlcf-&gt;db, &amp;rlcf-&gt;key);
      buf-&gt;last = buf-&gt;pos + len;
  
      cl = ngx_alloc_chain_link(r-&gt;pool);
      if (cl == NULL) {
          return NGX_ERROR;
      }
  
      cl-&gt;buf = buf;
      cl-&gt;next = NULL;
  
      body = r-&gt;upstream-&gt;request_bufs;
      r-&gt;upstream-&gt;request_bufs = cl;
      while (body)
      {
          b = ngx_alloc_buf(r-&gt;pool);
          if (b == NULL)
              return NGX_ERROR;
  
          ngx_memcpy(b, body-&gt;buf, sizeof(ngx_buf_t));
          cl-&gt;next = ngx_alloc_chain_link(r-&gt;pool);
          if (cl-&gt;next == NULL)
              return NGX_ERROR;
  
          cl = cl-&gt;next;
          cl-&gt;buf = b;
          body = body-&gt;next;
      }
      *cl-&gt;buf-&gt;last++ = CR; *cl-&gt;buf-&gt;last++ = LF;
      cl-&gt;next = NULL;
      return NGX_OK;
  }
  </code></pre>