mirror of https://github.com/nginx/nginx
Proxy: extracted control frame and skip functions for HTTP/2.
This commit is contained in:
parent
2a0342a17d
commit
fdd8e97558
|
|
@ -117,6 +117,10 @@ static ngx_int_t ngx_http_proxy_v2_process_header(ngx_http_request_t *r);
|
|||
static ngx_int_t ngx_http_proxy_v2_filter_init(void *data);
|
||||
static ngx_int_t ngx_http_proxy_v2_non_buffered_filter(void *data,
|
||||
ssize_t bytes);
|
||||
static ngx_int_t ngx_http_proxy_v2_process_control_frame(ngx_http_request_t *r,
|
||||
ngx_http_proxy_v2_ctx_t *ctx, ngx_buf_t *b);
|
||||
static ngx_int_t ngx_http_proxy_v2_skip_frame(ngx_http_proxy_v2_ctx_t *ctx,
|
||||
ngx_buf_t *b);
|
||||
static ngx_int_t ngx_http_proxy_v2_process_frames(ngx_http_request_t *r,
|
||||
ngx_http_proxy_v2_ctx_t *ctx, ngx_buf_t *b);
|
||||
|
||||
|
|
@ -1391,9 +1395,7 @@ ngx_http_proxy_v2_process_header(ngx_http_request_t *r)
|
|||
return NGX_HTTP_UPSTREAM_INVALID_HEADER;
|
||||
}
|
||||
|
||||
if (ctx->type == NGX_HTTP_V2_GOAWAY_FRAME) {
|
||||
|
||||
rc = ngx_http_proxy_v2_parse_goaway(r, ctx, b);
|
||||
rc = ngx_http_proxy_v2_process_control_frame(r, ctx, b);
|
||||
|
||||
if (rc == NGX_AGAIN) {
|
||||
return NGX_AGAIN;
|
||||
|
|
@ -1403,106 +1405,21 @@ ngx_http_proxy_v2_process_header(ngx_http_request_t *r)
|
|||
return NGX_HTTP_UPSTREAM_INVALID_HEADER;
|
||||
}
|
||||
|
||||
/*
|
||||
* If stream_id is lower than one we use, our
|
||||
* request won't be processed and needs to be retried.
|
||||
* If stream_id is greater or equal to the one we use,
|
||||
* we can continue normally (except we can't use this
|
||||
* connection for additional requests). If there is
|
||||
* a real error, the connection will be closed.
|
||||
*/
|
||||
|
||||
if (ctx->stream_id < ctx->id) {
|
||||
|
||||
/* TODO: we can retry non-idempotent requests */
|
||||
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||
"upstream sent goaway with error %ui",
|
||||
ctx->error);
|
||||
|
||||
return NGX_HTTP_UPSTREAM_INVALID_HEADER;
|
||||
}
|
||||
|
||||
ctx->goaway = 1;
|
||||
|
||||
if (rc == NGX_OK) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ctx->type == NGX_HTTP_V2_WINDOW_UPDATE_FRAME) {
|
||||
|
||||
rc = ngx_http_proxy_v2_parse_window_update(r, ctx, b);
|
||||
|
||||
if (rc == NGX_AGAIN) {
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
if (rc == NGX_ERROR) {
|
||||
return NGX_HTTP_UPSTREAM_INVALID_HEADER;
|
||||
}
|
||||
|
||||
if (ctx->in) {
|
||||
ngx_post_event(u->peer.connection->write, &ngx_posted_events);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ctx->type == NGX_HTTP_V2_SETTINGS_FRAME) {
|
||||
|
||||
rc = ngx_http_proxy_v2_parse_settings(r, ctx, b);
|
||||
|
||||
if (rc == NGX_AGAIN) {
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
if (rc == NGX_ERROR) {
|
||||
return NGX_HTTP_UPSTREAM_INVALID_HEADER;
|
||||
}
|
||||
|
||||
if (ctx->in) {
|
||||
ngx_post_event(u->peer.connection->write, &ngx_posted_events);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ctx->type == NGX_HTTP_V2_PING_FRAME) {
|
||||
|
||||
rc = ngx_http_proxy_v2_parse_ping(r, ctx, b);
|
||||
|
||||
if (rc == NGX_AGAIN) {
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
if (rc == NGX_ERROR) {
|
||||
return NGX_HTTP_UPSTREAM_INVALID_HEADER;
|
||||
}
|
||||
|
||||
ngx_post_event(u->peer.connection->write, &ngx_posted_events);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ctx->type == NGX_HTTP_V2_PUSH_PROMISE_FRAME) {
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||
"upstream sent unexpected push promise frame");
|
||||
return NGX_HTTP_UPSTREAM_INVALID_HEADER;
|
||||
}
|
||||
|
||||
if (ctx->type != NGX_HTTP_V2_HEADERS_FRAME
|
||||
&& ctx->type != NGX_HTTP_V2_CONTINUATION_FRAME)
|
||||
{
|
||||
/* priority, unknown frames */
|
||||
|
||||
if (b->last - b->pos < (ssize_t) ctx->rest) {
|
||||
ctx->rest -= b->last - b->pos;
|
||||
b->pos = b->last;
|
||||
rc = ngx_http_proxy_v2_skip_frame(ctx, b);
|
||||
|
||||
if (rc == NGX_AGAIN) {
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
b->pos += ctx->rest;
|
||||
ctx->rest = 0;
|
||||
ctx->state = ngx_http_proxy_v2_st_start;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -1807,6 +1724,134 @@ ngx_http_proxy_v2_non_buffered_filter(void *data, ssize_t bytes)
|
|||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_proxy_v2_process_control_frame(ngx_http_request_t *r,
|
||||
ngx_http_proxy_v2_ctx_t *ctx, ngx_buf_t *b)
|
||||
{
|
||||
ngx_int_t rc;
|
||||
ngx_http_upstream_t *u;
|
||||
|
||||
u = r->upstream;
|
||||
|
||||
if (ctx->type == NGX_HTTP_V2_GOAWAY_FRAME) {
|
||||
|
||||
rc = ngx_http_proxy_v2_parse_goaway(r, ctx, b);
|
||||
|
||||
if (rc == NGX_AGAIN) {
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
if (rc == NGX_ERROR) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* If stream_id is lower than one we use, our
|
||||
* request won't be processed and needs to be retried.
|
||||
* If stream_id is greater or equal to the one we use,
|
||||
* we can continue normally (except we can't use this
|
||||
* connection for additional requests). If there is
|
||||
* a real error, the connection will be closed.
|
||||
*/
|
||||
|
||||
if (ctx->stream_id < ctx->id) {
|
||||
|
||||
/* TODO: we can retry non-idempotent requests */
|
||||
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||
"upstream sent goaway with error %ui",
|
||||
ctx->error);
|
||||
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ctx->goaway = 1;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
if (ctx->type == NGX_HTTP_V2_WINDOW_UPDATE_FRAME) {
|
||||
|
||||
rc = ngx_http_proxy_v2_parse_window_update(r, ctx, b);
|
||||
|
||||
if (rc == NGX_AGAIN) {
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
if (rc == NGX_ERROR) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (ctx->in) {
|
||||
ngx_post_event(u->peer.connection->write, &ngx_posted_events);
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
if (ctx->type == NGX_HTTP_V2_SETTINGS_FRAME) {
|
||||
|
||||
rc = ngx_http_proxy_v2_parse_settings(r, ctx, b);
|
||||
|
||||
if (rc == NGX_AGAIN) {
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
if (rc == NGX_ERROR) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (ctx->in) {
|
||||
ngx_post_event(u->peer.connection->write, &ngx_posted_events);
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
if (ctx->type == NGX_HTTP_V2_PING_FRAME) {
|
||||
|
||||
rc = ngx_http_proxy_v2_parse_ping(r, ctx, b);
|
||||
|
||||
if (rc == NGX_AGAIN) {
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
if (rc == NGX_ERROR) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ngx_post_event(u->peer.connection->write, &ngx_posted_events);
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
if (ctx->type == NGX_HTTP_V2_PUSH_PROMISE_FRAME) {
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||
"upstream sent unexpected push promise frame");
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
return NGX_DECLINED;
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_proxy_v2_skip_frame(ngx_http_proxy_v2_ctx_t *ctx, ngx_buf_t *b)
|
||||
{
|
||||
if (b->last - b->pos < (ssize_t) ctx->rest) {
|
||||
ctx->rest -= b->last - b->pos;
|
||||
b->pos = b->last;
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
b->pos += ctx->rest;
|
||||
ctx->rest = 0;
|
||||
ctx->state = ngx_http_proxy_v2_st_start;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_proxy_v2_process_frames(ngx_http_request_t *r,
|
||||
ngx_http_proxy_v2_ctx_t *ctx, ngx_buf_t *b)
|
||||
|
|
@ -1990,9 +2035,7 @@ ngx_http_proxy_v2_process_frames(ngx_http_request_t *r,
|
|||
continue;
|
||||
}
|
||||
|
||||
if (ctx->type == NGX_HTTP_V2_GOAWAY_FRAME) {
|
||||
|
||||
rc = ngx_http_proxy_v2_parse_goaway(r, ctx, b);
|
||||
rc = ngx_http_proxy_v2_process_control_frame(r, ctx, b);
|
||||
|
||||
if (rc == NGX_AGAIN) {
|
||||
return NGX_AGAIN;
|
||||
|
|
@ -2002,91 +2045,10 @@ ngx_http_proxy_v2_process_frames(ngx_http_request_t *r,
|
|||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* If stream_id is lower than one we use, our
|
||||
* request won't be processed and needs to be retried.
|
||||
* If stream_id is greater or equal to the one we use,
|
||||
* we can continue normally (except we can't use this
|
||||
* connection for additional requests). If there is
|
||||
* a real error, the connection will be closed.
|
||||
*/
|
||||
|
||||
if (ctx->stream_id < ctx->id) {
|
||||
|
||||
/* TODO: we can retry non-idempotent requests */
|
||||
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||
"upstream sent goaway with error %ui",
|
||||
ctx->error);
|
||||
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ctx->goaway = 1;
|
||||
|
||||
if (rc == NGX_OK) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ctx->type == NGX_HTTP_V2_WINDOW_UPDATE_FRAME) {
|
||||
|
||||
rc = ngx_http_proxy_v2_parse_window_update(r, ctx, b);
|
||||
|
||||
if (rc == NGX_AGAIN) {
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
if (rc == NGX_ERROR) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (ctx->in) {
|
||||
ngx_post_event(u->peer.connection->write, &ngx_posted_events);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ctx->type == NGX_HTTP_V2_SETTINGS_FRAME) {
|
||||
|
||||
rc = ngx_http_proxy_v2_parse_settings(r, ctx, b);
|
||||
|
||||
if (rc == NGX_AGAIN) {
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
if (rc == NGX_ERROR) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (ctx->in) {
|
||||
ngx_post_event(u->peer.connection->write, &ngx_posted_events);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ctx->type == NGX_HTTP_V2_PING_FRAME) {
|
||||
|
||||
rc = ngx_http_proxy_v2_parse_ping(r, ctx, b);
|
||||
|
||||
if (rc == NGX_AGAIN) {
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
if (rc == NGX_ERROR) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ngx_post_event(u->peer.connection->write, &ngx_posted_events);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ctx->type == NGX_HTTP_V2_PUSH_PROMISE_FRAME) {
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||
"upstream sent unexpected push promise frame");
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (ctx->type == NGX_HTTP_V2_HEADERS_FRAME
|
||||
|| ctx->type == NGX_HTTP_V2_CONTINUATION_FRAME)
|
||||
{
|
||||
|
|
@ -2171,16 +2133,12 @@ ngx_http_proxy_v2_process_frames(ngx_http_request_t *r,
|
|||
|
||||
/* priority, unknown frames */
|
||||
|
||||
if (b->last - b->pos < (ssize_t) ctx->rest) {
|
||||
ctx->rest -= b->last - b->pos;
|
||||
b->pos = b->last;
|
||||
rc = ngx_http_proxy_v2_skip_frame(ctx, b);
|
||||
|
||||
if (rc == NGX_AGAIN) {
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
b->pos += ctx->rest;
|
||||
ctx->rest = 0;
|
||||
ctx->state = ngx_http_proxy_v2_st_start;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue