static ngx_int_t mytest_process_status_line(ngx_http_request_t *r) { size_t len; ngx_int_t rc; ngx_http_upstream_t *u; ngx_http_mytest_ctx_t* ctx = ngx_http_get_module_ctx(r, ngx_http_mytest_module); if (ctx == NULL) return NGX_ERROR; u = r->upstream; rc = ngx_http_parse_status_line(r, &u->buffer, &ctx->status);//解析HTTP响应行 if (rc == NGX_AGAIN) return rc; if (rc == NGX_ERROR) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "[jseanj] upstream sent no valid HTTP/1.0 header"); r->http_version = NGX_HTTP_VERSION_9; u->state->status = NGX_HTTP_OK; return NGX_OK; } if (u->state) u->state->status = ctx->status.code; u->headers_in.status_n = ctx->status.code; len = ctx->status.end - ctx->status.start; u->headers_in.status_line.len = len; u->headers_in.status_line.data = ngx_pnalloc(r->pool, len); if (u->headers_in.status_line.data == NULL) return NGX_ERROR; ngx_memcpy(u->headers_in.status_line.data, ctx->status.start, len); u->process_header = mytest_upstream_process_header; return mytest_upstream_process_header(r); }
static ngx_int_t ngx_http_scgi_process_status_line(ngx_http_request_t *r) { size_t len; ngx_int_t rc; ngx_http_status_t *status; ngx_http_upstream_t *u; status = ngx_http_get_module_ctx(r, ngx_http_scgi_module); if (status == NULL) { return NGX_ERROR; } u = r->upstream; rc = ngx_http_parse_status_line(r, &u->buffer, status); if (rc == NGX_AGAIN) { return rc; } if (rc == NGX_ERROR) { r->http_version = NGX_HTTP_VERSION_9; u->process_header = ngx_http_scgi_process_header; return ngx_http_scgi_process_header(r); } if (u->state) { u->state->status = status->code; } u->headers_in.status_n = status->code; len = status->end - status->start; u->headers_in.status_line.len = len; u->headers_in.status_line.data = ngx_pnalloc(r->pool, len); if (u->headers_in.status_line.data == NULL) { return NGX_ERROR; } ngx_memcpy(u->headers_in.status_line.data, status->start, len); ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http scgi status %ui \"%V\"", u->headers_in.status_n, &u->headers_in.status_line); u->process_header = ngx_http_scgi_process_header; return ngx_http_scgi_process_header(r); }
// reference: ngx_http_proxy_process_status_line ngx_int_t ngx_http_fetch_decode(ngx_http_request_t *r) { ngx_http_fetch_ctx_t * ctx = ngx_http_fetch_get_module_ctx(r); if (!ctx) { return NGX_ERROR; } ngx_http_upstream_t * u = r->upstream; ngx_int_t rc = ngx_http_parse_status_line(r, &u->buffer, &ctx->status); if (rc == NGX_AGAIN) { return rc; } if (rc == NGX_ERROR) { r->http_version = NGX_HTTP_VERSION_9; u->state->status = NGX_HTTP_OK; u->headers_in.connection_close = 1; return NGX_OK; } if (u->state && u->state->status == 0) { u->state->status = ctx->status.code; } u->headers_in.status_n = ctx->status.code; size_t len = ctx->status.end - ctx->status.start; u->headers_in.status_line.len = len; u->headers_in.status_line.data = ngx_pnalloc(r->pool, len); if (!u->headers_in.status_line.data) { return NGX_ERROR; } ngx_memcpy(u->headers_in.status_line.data, ctx->status.start, len); if (ctx->status.http_version < NGX_HTTP_VERSION_11) { u->headers_in.connection_close = 1; } u->process_header = __decode_header; return __decode_header(r); }
ngx_int_t ngx_http_srcache_process_status_line(ngx_http_request_t *r, ngx_buf_t *b) { ngx_int_t rc; ngx_http_srcache_ctx_t *ctx; ngx_http_request_t *pr; ngx_http_srcache_loc_conf_t *conf; ctx = ngx_http_get_module_ctx(r, ngx_http_srcache_filter_module); rc = ngx_http_parse_status_line(r, b, &ctx->status); if (rc == NGX_AGAIN) { return NGX_AGAIN; } if (rc == NGX_ERROR) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "srcache_fetch: cache sent invalid status line"); return NGX_ERROR; } /* rc == NGX_OK */ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "srcache_fetch status line done"); pr = r->parent; pr->headers_out.status = ctx->status.code; ctx->process_header = ngx_http_srcache_process_header; conf = ngx_http_get_module_loc_conf(pr, ngx_http_srcache_filter_module); dd("header buffer size: %d", (int) conf->header_buf_size); ctx->header_buf = ngx_create_temp_buf(r->pool, conf->header_buf_size); if (ctx->header_buf == NULL) { return NGX_ERROR; } if (b->pos == b->last) { return NGX_AGAIN; } return ngx_http_srcache_process_header(r, b); }
static ngx_int_t ngx_http_poller_process_status_line(ngx_http_request_t *r) { ngx_int_t rc; ngx_http_upstream_t *u; ngx_http_poller_t *poller; poller = ngx_http_get_module_ctx(r, ngx_http_poller_module); if (poller == NULL) { return NGX_ERROR; } u = r->upstream; rc = ngx_http_parse_status_line(r, &u->buffer, &poller->status); if (rc == NGX_AGAIN) { return rc; } if (rc == NGX_ERROR) { if (u->state) { u->state->status = NGX_HTTP_OK; } u->headers_in.connection_close = 1; return NGX_OK; } if (u->state) { u->state->status = poller->status.code; } u->headers_in.connection_close = 1; if (poller->handler.status != NULL) { poller->handler.status(r, &poller->status); } ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "[poller] %V: status = %uD", &poller->name, (uint32_t)poller->status.code); r->upstream->process_header = ngx_http_poller_process_header; return ngx_http_poller_process_header(r); }
static ngx_int_t mytest_process_status_line(ngx_http_request_t *r) { size_t len; ngx_int_t rc; ngx_http_upstream_t *u; //上下文中才会保存多次解析http响应行的状态,下面首先取出请求的上下文 ngx_http_mytest_ctx_t* ctx = ngx_http_get_module_ctx(r,ngx_http_mytest_module); if(ctx == NULL){ return NGX_ERROR; } u = r->upstream; /* http框架提供的ngx_http_parse_status_line方法可以解析http响应行,它的输入就是收到的 * 字符流和上下文中的ngx_http_status_t结构 */ rc = ngx_http_parse_status_line(r,&u->buffer,&ctx->status); if(rc == NGX_AGAIN){ return rc; } if(rc == NGX_ERROR){ ngx_log_error(NGX_LOG_ERR,r->connection->log,0,"upstream sent no valid HTTP/1.0 header"); r->http_version = NGX_HTTP_VERSION_9; u->state->status = NGX_HTTP_OK; return NGX_OK; } //将解析到完整的http响应行时,会做一些简单的赋值操作,将解析出的信息设置到r->upstream->headers_in结构体中 if(u->state){ u->state->status = ctx->status.code; } u->headers_in.status_n = ctx->status.code; len = ctx->status.end - ctx->status.start; u->headers_in.status_line.len = len; u->headers_in.status_line.data = ngx_pnalloc(r->pool,len); if(u->headers_in.status_line.data == NULL){ return NGX_ERROR; } ngx_memcpy(u->headers_in.status_line.data,ctx->status.start,len); u->process_header = mytest_upstream_process_header; return mytest_upstream_process_header(r); }
//解析HTTP响应行 static ngx_int_t mytest_process_status_line(ngx_http_request_t *r) { size_t len; ngx_int_t rc; ngx_http_upstream_t *u; //上下文中才会保存多次解析HTTP响应行的状态,下面首先取出请求的上下文 ngx_http_mytest_ctx_t * ctx = ngx_http_get_module_ctx(r, ngx_http_mytest_module); if(ctx == NULL){ return NGX_ERROR; } u = r->upstream; //HTTP框架提供的ngx_http_parse_status_line方法可以解析HTTP响应行,它的输入就是收到 //的字符流和上下文中的ngx_http_status_t结构 rc = ngx_http_parse_status_line(r, &u->buffer, &ctx->status); //返回NGX_AGAIN时,表示还没有解析出完整的HTTP响应行,需要接收更多的字符流在进行解析 if(rc == NGX_AGAIN){ return rc; } //返回NGX_ERROR时,表示没有接收到合法的HTTP响应行 if(rc == NGX_ERROR){ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "upstream sent no valid HTTP/1.0 header"); r->http_version = NGX_HTTP_VERSION_9; u->state->status = NGX_HTTP_OK; return NGX_OK; } //以下表示在解析到完整的HTTP响应行时,会做一些简单的赋值操作,将解析出的信息设置到 //r->upstream->headers_in结构体中。当upstream解析完所有的包头时,会把headers_in中的 //成员设置到将要向下游发送的r->headers_out结构体中,也就是说,现在用户向headers_in中 //设置的信息,最终都会发往下游客户端。为什么不直接设置r->headers_out而要多次一举呢? //因为upstream希望能够按照ngx_http_upstream_conf_t配置结构体中的hide_headers等成员对 //发往下游的响应头部做统一处理 if(u->state){ u->state->status = ctx->status.code; } u->headers_in.status_n = ctx->status.code; len = ctx->status.end - ctx->status.start; u->headers_in.status_line.len = len; u->headers_in.status_line.data = ngx_pnalloc(r->pool, len); if(u->headers_in.status_line.data == NULL){ return NGX_ERROR; } ngx_memcpy(u->headers_in.status_line.data, ctx->status.start, len); //下一步将开始解析HTTP头部。设置process_header回调方法为mytest_upstream_process_header, //之后在再收到的新字符流将由mytest_upstream_process_header操作 u->process_header = mytest_upstream_process_header; return mytest_upstream_process_header(r); }
static ngx_int_t mytest_process_status_line(ngx_http_request_t *r) { size_t len; ngx_int_t rc; ngx_http_upstream_t *u; //上下文中才会保存多次解析http响应行的状态,首先取出请求的上下文 ngx_http_mytest_ctx_t* ctx = ngx_http_get_module_ctx(r, ngx_http_mytest_module); if (ctx == NULL) { return NGX_ERROR; } u = r->upstream; //http框架提供的ngx_http_parse_status_line方法可以解析http //响应行,它的输入就是收到的字符流和上下文中的ngx_http_status_t结构 rc = ngx_http_parse_status_line(r, &u->buffer, &ctx->status); //返回NGX_AGAIN表示还没有解析出完整的http响应行,需要接收更多的 //字符流再来解析 if (rc == NGX_AGAIN) { return rc; } //返回NGX_ERROR则没有接收到合法的http响应行 if (rc == NGX_ERROR) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "upstream sent no valid HTTP/1.0 header"); r->http_version = NGX_HTTP_VERSION_9; u->state->status = NGX_HTTP_OK; return NGX_OK; } //以下表示解析到完整的http响应行,这时会做一些简单的赋值操作,将解析出 //的信息设置到r->upstream->headers_in结构体中,upstream解析完所 //有的包头时,就会把headers_in中的成员设置到将要向下游发送的 //r->headers_out结构体中,也就是说,现在我们向headers_in中设置的 //信息,最终都会发往下游客户端。为什么不是直接设置r->headers_out而要 //这样多此一举呢?这是因为upstream希望能够按照 //ngx_http_upstream_conf_t配置结构体中的hide_headers等成员对 //发往下游的响应头部做统一处理 if (u->state) { u->state->status = ctx->status.code; } u->headers_in.status_n = ctx->status.code; len = ctx->status.end - ctx->status.start; u->headers_in.status_line.len = len; u->headers_in.status_line.data = ngx_pnalloc(r->pool, len); if (u->headers_in.status_line.data == NULL) { return NGX_ERROR; } ngx_memcpy(u->headers_in.status_line.data, ctx->status.start, len); //下一步将开始解析http头部,设置process_header回调方法为 //mytest_upstream_process_header, //之后再收到的新字符流将由mytest_upstream_process_header解析 u->process_header = mytest_upstream_process_header; //如果本次收到的字符流除了http响应行外,还有多余的字符, //将由mytest_upstream_process_header方法解析 return mytest_upstream_process_header(r); }