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_filter_init(void *data);
|
||||||
static ngx_int_t ngx_http_proxy_v2_non_buffered_filter(void *data,
|
static ngx_int_t ngx_http_proxy_v2_non_buffered_filter(void *data,
|
||||||
ssize_t bytes);
|
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,
|
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);
|
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;
|
return NGX_HTTP_UPSTREAM_INVALID_HEADER;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx->type == NGX_HTTP_V2_GOAWAY_FRAME) {
|
rc = ngx_http_proxy_v2_process_control_frame(r, ctx, b);
|
||||||
|
|
||||||
rc = ngx_http_proxy_v2_parse_goaway(r, ctx, b);
|
|
||||||
|
|
||||||
if (rc == NGX_AGAIN) {
|
if (rc == NGX_AGAIN) {
|
||||||
return 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;
|
return NGX_HTTP_UPSTREAM_INVALID_HEADER;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
if (rc == NGX_OK) {
|
||||||
* 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;
|
|
||||||
|
|
||||||
continue;
|
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
|
if (ctx->type != NGX_HTTP_V2_HEADERS_FRAME
|
||||||
&& ctx->type != NGX_HTTP_V2_CONTINUATION_FRAME)
|
&& ctx->type != NGX_HTTP_V2_CONTINUATION_FRAME)
|
||||||
{
|
{
|
||||||
/* priority, unknown frames */
|
/* priority, unknown frames */
|
||||||
|
|
||||||
if (b->last - b->pos < (ssize_t) ctx->rest) {
|
rc = ngx_http_proxy_v2_skip_frame(ctx, b);
|
||||||
ctx->rest -= b->last - b->pos;
|
|
||||||
b->pos = b->last;
|
if (rc == NGX_AGAIN) {
|
||||||
return NGX_AGAIN;
|
return NGX_AGAIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
b->pos += ctx->rest;
|
|
||||||
ctx->rest = 0;
|
|
||||||
ctx->state = ngx_http_proxy_v2_st_start;
|
|
||||||
|
|
||||||
continue;
|
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
|
static ngx_int_t
|
||||||
ngx_http_proxy_v2_process_frames(ngx_http_request_t *r,
|
ngx_http_proxy_v2_process_frames(ngx_http_request_t *r,
|
||||||
ngx_http_proxy_v2_ctx_t *ctx, ngx_buf_t *b)
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx->type == NGX_HTTP_V2_GOAWAY_FRAME) {
|
rc = ngx_http_proxy_v2_process_control_frame(r, ctx, b);
|
||||||
|
|
||||||
rc = ngx_http_proxy_v2_parse_goaway(r, ctx, b);
|
|
||||||
|
|
||||||
if (rc == NGX_AGAIN) {
|
if (rc == NGX_AGAIN) {
|
||||||
return NGX_AGAIN;
|
return NGX_AGAIN;
|
||||||
|
|
@ -2002,91 +2045,10 @@ ngx_http_proxy_v2_process_frames(ngx_http_request_t *r,
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
if (rc == NGX_OK) {
|
||||||
* 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;
|
|
||||||
|
|
||||||
continue;
|
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
|
if (ctx->type == NGX_HTTP_V2_HEADERS_FRAME
|
||||||
|| ctx->type == NGX_HTTP_V2_CONTINUATION_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 */
|
/* priority, unknown frames */
|
||||||
|
|
||||||
if (b->last - b->pos < (ssize_t) ctx->rest) {
|
rc = ngx_http_proxy_v2_skip_frame(ctx, b);
|
||||||
ctx->rest -= b->last - b->pos;
|
|
||||||
b->pos = b->last;
|
if (rc == NGX_AGAIN) {
|
||||||
return NGX_AGAIN;
|
return NGX_AGAIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
b->pos += ctx->rest;
|
|
||||||
ctx->rest = 0;
|
|
||||||
ctx->state = ngx_http_proxy_v2_st_start;
|
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue