mirror of
https://github.com/nginx/nginx.git
synced 2026-07-10 10:54:57 +00:00
Merge 254f56139c into 42f8df65b6
This commit is contained in:
commit
dec44ac81e
5 changed files with 99 additions and 21 deletions
|
|
@ -77,6 +77,7 @@ typedef struct {
|
|||
ngx_str_t value;
|
||||
|
||||
u_char *field_end;
|
||||
size_t header_limit;
|
||||
size_t field_length;
|
||||
size_t field_rest;
|
||||
u_char field_state;
|
||||
|
|
@ -978,6 +979,14 @@ ngx_http_proxy_v2_reinit_request(ngx_http_request_t *r)
|
|||
}
|
||||
|
||||
ctx->state = 0;
|
||||
ctx->frame_state = 0;
|
||||
ctx->fragment_state = 0;
|
||||
ctx->rest = 0;
|
||||
ctx->stream_id = 0;
|
||||
ctx->type = 0;
|
||||
ctx->flags = 0;
|
||||
ctx->padding = 0;
|
||||
ctx->error = 0;
|
||||
ctx->header_sent = 0;
|
||||
ctx->output_closed = 0;
|
||||
ctx->output_blocked = 0;
|
||||
|
|
@ -1480,6 +1489,10 @@ ngx_http_proxy_v2_process_header(ngx_http_request_t *r)
|
|||
return NGX_HTTP_UPSTREAM_INVALID_HEADER;
|
||||
}
|
||||
|
||||
if (rc == NGX_HTTP_UPSTREAM_RETRY) {
|
||||
return NGX_HTTP_UPSTREAM_RETRY;
|
||||
}
|
||||
|
||||
if (rc == NGX_OK) {
|
||||
continue;
|
||||
}
|
||||
|
|
@ -1961,7 +1974,9 @@ ngx_http_proxy_v2_process_control_frame(ngx_http_request_t *r,
|
|||
|
||||
if (ctx->stream_id < ctx->id) {
|
||||
|
||||
/* TODO: we can retry non-idempotent requests */
|
||||
if (ctx->error == 0) {
|
||||
return NGX_HTTP_UPSTREAM_RETRY;
|
||||
}
|
||||
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||
"upstream sent goaway with error %ui",
|
||||
|
|
@ -2250,6 +2265,10 @@ ngx_http_proxy_v2_process_frames(ngx_http_request_t *r,
|
|||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (rc == NGX_HTTP_UPSTREAM_RETRY) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (rc == NGX_OK) {
|
||||
continue;
|
||||
}
|
||||
|
|
@ -2535,6 +2554,7 @@ ngx_http_proxy_v2_parse_header(ngx_http_request_t *r,
|
|||
if (ctx->type == NGX_HTTP_V2_HEADERS_FRAME) {
|
||||
ctx->parsing_headers = 1;
|
||||
ctx->fragment_state = 0;
|
||||
ctx->header_limit = r->upstream->conf->buffer_size;
|
||||
|
||||
min = (ctx->flags & NGX_HTTP_V2_PADDED_FLAG ? 1 : 0)
|
||||
+ (ctx->flags & NGX_HTTP_V2_PRIORITY_FLAG ? 5 : 0);
|
||||
|
|
@ -2730,7 +2750,7 @@ ngx_http_proxy_v2_parse_fragment(ngx_http_request_t *r,
|
|||
ngx_http_proxy_v2_ctx_t *ctx, ngx_buf_t *b)
|
||||
{
|
||||
u_char ch, *p, *last;
|
||||
size_t size;
|
||||
size_t len, size;
|
||||
ngx_uint_t index, size_update;
|
||||
enum {
|
||||
sw_start = 0,
|
||||
|
|
@ -3067,6 +3087,14 @@ ngx_http_proxy_v2_parse_fragment(ngx_http_request_t *r,
|
|||
break;
|
||||
|
||||
case sw_name:
|
||||
if (ctx->field_length > r->upstream->conf->buffer_size) {
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||
"upstream sent too large http2 "
|
||||
"header name length: %uz",
|
||||
ctx->field_length);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ctx->name.len = ctx->field_huffman ?
|
||||
ctx->field_length * 8 / 5 : ctx->field_length;
|
||||
|
||||
|
|
@ -3176,6 +3204,14 @@ ngx_http_proxy_v2_parse_fragment(ngx_http_request_t *r,
|
|||
break;
|
||||
|
||||
case sw_value:
|
||||
if (ctx->field_length > r->upstream->conf->buffer_size) {
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||
"upstream sent too large http2 "
|
||||
"header value length: %uz",
|
||||
ctx->field_length);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ctx->value.len = ctx->field_huffman ?
|
||||
ctx->field_length * 8 / 5 : ctx->field_length;
|
||||
|
||||
|
|
@ -3272,6 +3308,16 @@ ngx_http_proxy_v2_parse_fragment(ngx_http_request_t *r,
|
|||
}
|
||||
}
|
||||
|
||||
len = ctx->name.len + ctx->value.len;
|
||||
|
||||
if (len > ctx->header_limit) {
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||
"upstream sent too large http2 header");
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ctx->header_limit -= len;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
|
@ -3695,7 +3741,7 @@ ngx_http_proxy_v2_parse_settings(ngx_http_request_t *r,
|
|||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (ctx->free == NULL && ctx->settings++ > 1000) {
|
||||
if (ctx->settings++ > 1000) {
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||
"upstream sent too many settings frames");
|
||||
return NGX_ERROR;
|
||||
|
|
@ -3853,7 +3899,7 @@ ngx_http_proxy_v2_parse_ping(ngx_http_request_t *r,
|
|||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (ctx->free == NULL && ctx->pings++ > 1000) {
|
||||
if (ctx->pings++ > 1000) {
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||
"upstream sent too many ping frames");
|
||||
return NGX_ERROR;
|
||||
|
|
|
|||
|
|
@ -2597,6 +2597,11 @@ done:
|
|||
return;
|
||||
}
|
||||
|
||||
if (rc == NGX_HTTP_UPSTREAM_RETRY) {
|
||||
ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_RETRY);
|
||||
return;
|
||||
}
|
||||
|
||||
if (rc == NGX_ERROR) {
|
||||
ngx_http_upstream_finalize_request(r, u,
|
||||
NGX_HTTP_INTERNAL_SERVER_ERROR);
|
||||
|
|
@ -4598,7 +4603,8 @@ ngx_http_upstream_next(ngx_http_request_t *r, ngx_http_upstream_t *u,
|
|||
}
|
||||
|
||||
if (ft_type == NGX_HTTP_UPSTREAM_FT_HTTP_403
|
||||
|| ft_type == NGX_HTTP_UPSTREAM_FT_HTTP_404)
|
||||
|| ft_type == NGX_HTTP_UPSTREAM_FT_HTTP_404
|
||||
|| ft_type == NGX_HTTP_UPSTREAM_FT_RETRY)
|
||||
{
|
||||
state = NGX_PEER_NEXT;
|
||||
|
||||
|
|
@ -4619,7 +4625,10 @@ ngx_http_upstream_next(ngx_http_request_t *r, ngx_http_upstream_t *u,
|
|||
"upstream timed out");
|
||||
}
|
||||
|
||||
if (u->peer.cached && ft_type == NGX_HTTP_UPSTREAM_FT_ERROR) {
|
||||
if (u->peer.cached
|
||||
&& (ft_type == NGX_HTTP_UPSTREAM_FT_ERROR
|
||||
|| ft_type == NGX_HTTP_UPSTREAM_FT_RETRY))
|
||||
{
|
||||
/* TODO: inform balancer instead */
|
||||
u->peer.tries++;
|
||||
}
|
||||
|
|
@ -4670,14 +4679,16 @@ ngx_http_upstream_next(ngx_http_request_t *r, ngx_http_upstream_t *u,
|
|||
|
||||
timeout = u->conf->next_upstream_timeout;
|
||||
|
||||
if (u->request_sent
|
||||
if (ft_type != NGX_HTTP_UPSTREAM_FT_RETRY
|
||||
&& u->request_sent
|
||||
&& (r->method & (NGX_HTTP_POST|NGX_HTTP_LOCK|NGX_HTTP_PATCH)))
|
||||
{
|
||||
ft_type |= NGX_HTTP_UPSTREAM_FT_NON_IDEMPOTENT;
|
||||
}
|
||||
|
||||
if (u->peer.tries == 0
|
||||
|| ((u->conf->next_upstream & ft_type) != ft_type)
|
||||
|| (ft_type != NGX_HTTP_UPSTREAM_FT_RETRY
|
||||
&& ((u->conf->next_upstream & ft_type) != ft_type))
|
||||
|| (u->request_sent && r->request_body_no_buffering)
|
||||
|| (timeout && ngx_current_msec - u->peer.start_time >= timeout))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#define NGX_HTTP_UPSTREAM_FT_BUSY_LOCK 0x00001000
|
||||
#define NGX_HTTP_UPSTREAM_FT_MAX_WAITING 0x00002000
|
||||
#define NGX_HTTP_UPSTREAM_FT_NON_IDEMPOTENT 0x00004000
|
||||
#define NGX_HTTP_UPSTREAM_FT_RETRY 0x00008000
|
||||
#define NGX_HTTP_UPSTREAM_FT_NOLIVE 0x40000000
|
||||
#define NGX_HTTP_UPSTREAM_FT_OFF 0x80000000
|
||||
|
||||
|
|
@ -44,6 +45,7 @@
|
|||
|
||||
#define NGX_HTTP_UPSTREAM_INVALID_HEADER 40
|
||||
#define NGX_HTTP_UPSTREAM_EARLY_HINTS 41
|
||||
#define NGX_HTTP_UPSTREAM_RETRY 42
|
||||
|
||||
|
||||
#define NGX_HTTP_UPSTREAM_IGN_XA_REDIRECT 0x00000002
|
||||
|
|
|
|||
|
|
@ -2181,6 +2181,9 @@ ngx_http_v2_state_settings(ngx_http_v2_connection_t *h2c, u_char *pos,
|
|||
return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR);
|
||||
}
|
||||
|
||||
h2c->state.init_window_set = 0;
|
||||
h2c->state.max_frame_set = 0;
|
||||
|
||||
return ngx_http_v2_state_settings_params(h2c, pos, end);
|
||||
}
|
||||
|
||||
|
|
@ -2193,8 +2196,6 @@ ngx_http_v2_state_settings_params(ngx_http_v2_connection_t *h2c, u_char *pos,
|
|||
ngx_uint_t id, value;
|
||||
ngx_http_v2_out_frame_t *frame;
|
||||
|
||||
window_delta = 0;
|
||||
|
||||
while (h2c->state.length) {
|
||||
if (end - pos < NGX_HTTP_V2_SETTINGS_PARAM_SIZE) {
|
||||
return ngx_http_v2_state_save(h2c, pos, end,
|
||||
|
|
@ -2222,7 +2223,8 @@ ngx_http_v2_state_settings_params(ngx_http_v2_connection_t *h2c, u_char *pos,
|
|||
NGX_HTTP_V2_FLOW_CTRL_ERROR);
|
||||
}
|
||||
|
||||
window_delta = value - h2c->init_window;
|
||||
h2c->state.init_window_size = value;
|
||||
h2c->state.init_window_set = 1;
|
||||
break;
|
||||
|
||||
case NGX_HTTP_V2_MAX_FRAME_SIZE_SETTING:
|
||||
|
|
@ -2238,7 +2240,8 @@ ngx_http_v2_state_settings_params(ngx_http_v2_connection_t *h2c, u_char *pos,
|
|||
NGX_HTTP_V2_PROTOCOL_ERROR);
|
||||
}
|
||||
|
||||
h2c->frame_size = value;
|
||||
h2c->state.max_frame_size = value;
|
||||
h2c->state.max_frame_set = 1;
|
||||
break;
|
||||
|
||||
case NGX_HTTP_V2_ENABLE_PUSH_SETTING:
|
||||
|
|
@ -2266,6 +2269,27 @@ ngx_http_v2_state_settings_params(ngx_http_v2_connection_t *h2c, u_char *pos,
|
|||
pos += NGX_HTTP_V2_SETTINGS_PARAM_SIZE;
|
||||
}
|
||||
|
||||
if (h2c->state.max_frame_set) {
|
||||
h2c->frame_size = h2c->state.max_frame_size;
|
||||
h2c->state.max_frame_set = 0;
|
||||
}
|
||||
|
||||
if (h2c->state.init_window_set) {
|
||||
window_delta = (ssize_t) h2c->state.init_window_size
|
||||
- (ssize_t) h2c->init_window;
|
||||
|
||||
h2c->init_window = h2c->state.init_window_size;
|
||||
|
||||
if (window_delta
|
||||
&& ngx_http_v2_adjust_windows(h2c, window_delta) != NGX_OK)
|
||||
{
|
||||
return ngx_http_v2_connection_error(h2c,
|
||||
NGX_HTTP_V2_INTERNAL_ERROR);
|
||||
}
|
||||
|
||||
h2c->state.init_window_set = 0;
|
||||
}
|
||||
|
||||
frame = ngx_http_v2_get_frame(h2c, NGX_HTTP_V2_SETTINGS_ACK_SIZE,
|
||||
NGX_HTTP_V2_SETTINGS_FRAME,
|
||||
NGX_HTTP_V2_ACK_FLAG, 0);
|
||||
|
|
@ -2275,15 +2299,6 @@ ngx_http_v2_state_settings_params(ngx_http_v2_connection_t *h2c, u_char *pos,
|
|||
|
||||
ngx_http_v2_queue_ordered_frame(h2c, frame);
|
||||
|
||||
if (window_delta) {
|
||||
h2c->init_window += window_delta;
|
||||
|
||||
if (ngx_http_v2_adjust_windows(h2c, window_delta) != NGX_OK) {
|
||||
return ngx_http_v2_connection_error(h2c,
|
||||
NGX_HTTP_V2_INTERNAL_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
return ngx_http_v2_state_complete(h2c, pos, end);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -80,10 +80,14 @@ typedef struct {
|
|||
ngx_uint_t sid;
|
||||
size_t length;
|
||||
size_t padding;
|
||||
size_t init_window_size;
|
||||
size_t max_frame_size;
|
||||
unsigned flags:8;
|
||||
|
||||
unsigned incomplete:1;
|
||||
unsigned keep_pool:1;
|
||||
unsigned init_window_set:1;
|
||||
unsigned max_frame_set:1;
|
||||
|
||||
/* HPACK */
|
||||
unsigned parse_name:1;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue