From pluknet at nginx.com Thu Jun 1 01:58:38 2023 From: pluknet at nginx.com (=?iso-8859-1?q?Sergey_Kandaurov?=) Date: Thu, 01 Jun 2023 05:58:38 +0400 Subject: [PATCH] HTTP/2: removed server push Message-ID: # HG changeset patch # User Sergey Kandaurov # Date 1685584419 -14400 # Thu Jun 01 05:53:39 2023 +0400 # Node ID cd90a7bed6ebb098efe1e82b7ffa067e5f0e56c1 # Parent 79ed88b1bf961a19b1efccd058fae440c3acbbdc HTTP/2: removed server push. Although it has better implementation status than HTTP/3 server push, it remains of limited use, with adoption numbers seen as negligible. Per IETF 102 materials, server push was used only in 0.04% of sessions. It was considered to be "difficult to use effectively" in RFC 9113. Its use is further limited by badly matching to fetch/cache/connection models in browsers, see related discussions linked from [1]. Server push was disabled in Chrome 106 [2]. The http2_push, http2_push_preload, and http2_max_concurrent_pushes directives are made obsolete. [1] https://jakearchibald.com/2017/h2-push-tougher-than-i-thought/ [2] https://chromestatus.com/feature/6302414934114304 diff --git a/src/http/v2/ngx_http_v2.c b/src/http/v2/ngx_http_v2.c --- a/src/http/v2/ngx_http_v2.c +++ b/src/http/v2/ngx_http_v2.c @@ -11,14 +11,6 @@ #include -typedef struct { - ngx_str_t name; - ngx_uint_t offset; - ngx_uint_t hash; - ngx_http_header_t *hh; -} ngx_http_v2_parse_header_t; - - /* errors */ #define NGX_HTTP_V2_NO_ERROR 0x0 #define NGX_HTTP_V2_PROTOCOL_ERROR 0x1 @@ -126,7 +118,7 @@ static ngx_int_t ngx_http_v2_parse_int(n u_char **pos, u_char *end, ngx_uint_t prefix); static ngx_http_v2_stream_t *ngx_http_v2_create_stream( - ngx_http_v2_connection_t *h2c, ngx_uint_t push); + ngx_http_v2_connection_t *h2c); static ngx_http_v2_node_t *ngx_http_v2_get_node_by_id( ngx_http_v2_connection_t *h2c, ngx_uint_t sid, ngx_uint_t alloc); static ngx_http_v2_node_t *ngx_http_v2_get_closed_node( @@ -162,14 +154,11 @@ static ngx_int_t ngx_http_v2_parse_schem ngx_str_t *value); static ngx_int_t ngx_http_v2_parse_authority(ngx_http_request_t *r, ngx_str_t *value); -static ngx_int_t ngx_http_v2_parse_header(ngx_http_request_t *r, - ngx_http_v2_parse_header_t *header, ngx_str_t *value); static ngx_int_t ngx_http_v2_construct_request_line(ngx_http_request_t *r); static ngx_int_t ngx_http_v2_cookie(ngx_http_request_t *r, ngx_http_v2_header_t *header); static ngx_int_t ngx_http_v2_construct_cookie_header(ngx_http_request_t *r); static void ngx_http_v2_run_request(ngx_http_request_t *r); -static void ngx_http_v2_run_request_handler(ngx_event_t *ev); static ngx_int_t ngx_http_v2_process_request_body(ngx_http_request_t *r, u_char *pos, size_t size, ngx_uint_t last, ngx_uint_t flush); static ngx_int_t ngx_http_v2_filter_request_body(ngx_http_request_t *r); @@ -210,23 +199,6 @@ static ngx_http_v2_handler_pt ngx_http_v (sizeof(ngx_http_v2_frame_states) / sizeof(ngx_http_v2_handler_pt)) -static ngx_http_v2_parse_header_t ngx_http_v2_parse_headers[] = { - { ngx_string("host"), - offsetof(ngx_http_headers_in_t, host), 0, NULL }, - - { ngx_string("accept-encoding"), - offsetof(ngx_http_headers_in_t, accept_encoding), 0, NULL }, - - { ngx_string("accept-language"), - offsetof(ngx_http_headers_in_t, accept_language), 0, NULL }, - - { ngx_string("user-agent"), - offsetof(ngx_http_headers_in_t, user_agent), 0, NULL }, - - { ngx_null_string, 0, 0, NULL } -}; - - void ngx_http_v2_init(ngx_event_t *rev) { @@ -275,7 +247,6 @@ ngx_http_v2_init(ngx_event_t *rev) h2scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v2_module); - h2c->concurrent_pushes = h2scf->concurrent_pushes; h2c->priority_limit = ngx_max(h2scf->concurrent_streams, 100); h2c->pool = ngx_create_pool(h2scf->pool_size, h2c->connection->log); @@ -384,7 +355,7 @@ ngx_http_v2_read_handler(ngx_event_t *re return; } - if (!h2c->processing && !h2c->pushing) { + if (!h2c->processing) { ngx_http_v2_finalize_connection(h2c, NGX_HTTP_V2_NO_ERROR); return; } @@ -427,8 +398,7 @@ ngx_http_v2_read_handler(ngx_event_t *re break; } - if (n == 0 - && (h2c->state.incomplete || h2c->processing || h2c->pushing)) + if (n == 0 && (h2c->state.incomplete || h2c->processing)) { ngx_log_error(NGX_LOG_INFO, c->log, 0, "client prematurely closed connection"); @@ -652,7 +622,7 @@ ngx_http_v2_handle_connection(ngx_http_v ngx_connection_t *c; ngx_http_core_loc_conf_t *clcf; - if (h2c->last_out || h2c->processing || h2c->pushing) { + if (h2c->last_out || h2c->processing) { return; } @@ -1337,7 +1307,7 @@ ngx_http_v2_state_headers(ngx_http_v2_co h2c->closed_nodes--; } - stream = ngx_http_v2_create_stream(h2c, 0); + stream = ngx_http_v2_create_stream(h2c); if (stream == NULL) { return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR); } @@ -2198,7 +2168,6 @@ ngx_http_v2_state_settings_params(ngx_ht { ssize_t window_delta; ngx_uint_t id, value; - ngx_http_v2_srv_conf_t *h2scf; ngx_http_v2_out_frame_t *frame; window_delta = 0; @@ -2260,14 +2229,6 @@ ngx_http_v2_state_settings_params(ngx_ht NGX_HTTP_V2_PROTOCOL_ERROR); } - h2c->push_disabled = !value; - break; - - case NGX_HTTP_V2_MAX_STREAMS_SETTING: - h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx, - ngx_http_v2_module); - - h2c->concurrent_pushes = ngx_min(value, h2scf->concurrent_pushes); break; case NGX_HTTP_V2_HEADER_TABLE_SIZE_SETTING: @@ -2722,163 +2683,6 @@ ngx_http_v2_parse_int(ngx_http_v2_connec } -ngx_http_v2_stream_t * -ngx_http_v2_push_stream(ngx_http_v2_stream_t *parent, ngx_str_t *path) -{ - ngx_int_t rc; - ngx_str_t value; - ngx_pool_t *pool; - ngx_uint_t index; - ngx_table_elt_t **h; - ngx_connection_t *fc; - ngx_http_request_t *r; - ngx_http_v2_node_t *node; - ngx_http_v2_stream_t *stream; - ngx_http_v2_srv_conf_t *h2scf; - ngx_http_v2_connection_t *h2c; - ngx_http_v2_parse_header_t *header; - - h2c = parent->connection; - - pool = ngx_create_pool(1024, h2c->connection->log); - if (pool == NULL) { - goto rst_stream; - } - - node = ngx_http_v2_get_node_by_id(h2c, h2c->last_push, 1); - - if (node == NULL) { - ngx_destroy_pool(pool); - goto rst_stream; - } - - stream = ngx_http_v2_create_stream(h2c, 1); - if (stream == NULL) { - - if (node->parent == NULL) { - h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx, - ngx_http_v2_module); - - index = ngx_http_v2_index(h2scf, h2c->last_push); - h2c->streams_index[index] = node->index; - - ngx_queue_insert_tail(&h2c->closed, &node->reuse); - h2c->closed_nodes++; - } - - ngx_destroy_pool(pool); - goto rst_stream; - } - - if (node->parent) { - ngx_queue_remove(&node->reuse); - h2c->closed_nodes--; - } - - stream->pool = pool; - - r = stream->request; - fc = r->connection; - - stream->in_closed = 1; - stream->node = node; - - node->stream = stream; - - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, - "http2 push stream sid:%ui " - "depends on %ui excl:0 weight:16", - h2c->last_push, parent->node->id); - - node->weight = NGX_HTTP_V2_DEFAULT_WEIGHT; - ngx_http_v2_set_dependency(h2c, node, parent->node->id, 0); - - r->method_name = ngx_http_core_get_method; - r->method = NGX_HTTP_GET; - - r->schema.data = ngx_pstrdup(pool, &parent->request->schema); - if (r->schema.data == NULL) { - goto close; - } - - r->schema.len = parent->request->schema.len; - - value.data = ngx_pstrdup(pool, path); - if (value.data == NULL) { - goto close; - } - - value.len = path->len; - - rc = ngx_http_v2_parse_path(r, &value); - - if (rc != NGX_OK) { - goto error; - } - - for (header = ngx_http_v2_parse_headers; header->name.len; header++) { - h = (ngx_table_elt_t **) - ((char *) &parent->request->headers_in + header->offset); - - if (*h == NULL) { - continue; - } - - value.len = (*h)->value.len; - - value.data = ngx_pnalloc(pool, value.len + 1); - if (value.data == NULL) { - goto close; - } - - ngx_memcpy(value.data, (*h)->value.data, value.len); - value.data[value.len] = '\0'; - - rc = ngx_http_v2_parse_header(r, header, &value); - - if (rc != NGX_OK) { - goto error; - } - } - - fc->write->handler = ngx_http_v2_run_request_handler; - ngx_post_event(fc->write, &ngx_posted_events); - - return stream; - -error: - - if (rc == NGX_ABORT) { - /* header handler has already finalized request */ - ngx_http_run_posted_requests(fc); - return NULL; - } - - if (rc == NGX_DECLINED) { - ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); - ngx_http_run_posted_requests(fc); - return NULL; - } - -close: - - ngx_http_v2_close_stream(stream, NGX_HTTP_INTERNAL_SERVER_ERROR); - - return NULL; - -rst_stream: - - if (ngx_http_v2_send_rst_stream(h2c, h2c->last_push, - NGX_HTTP_INTERNAL_SERVER_ERROR) - != NGX_OK) - { - h2c->connection->error = 1; - } - - return NULL; -} - - static ngx_int_t ngx_http_v2_send_settings(ngx_http_v2_connection_t *h2c) { @@ -3150,7 +2954,7 @@ ngx_http_v2_frame_handler(ngx_http_v2_co static ngx_http_v2_stream_t * -ngx_http_v2_create_stream(ngx_http_v2_connection_t *h2c, ngx_uint_t push) +ngx_http_v2_create_stream(ngx_http_v2_connection_t *h2c) { ngx_log_t *log; ngx_event_t *rev, *wev; @@ -3205,13 +3009,7 @@ ngx_http_v2_create_stream(ngx_http_v2_co ngx_memcpy(log, h2c->connection->log, sizeof(ngx_log_t)); log->data = ctx; - - if (push) { - log->action = "processing pushed request headers"; - - } else { - log->action = "reading client request headers"; - } + log->action = "reading client request headers"; ngx_memzero(rev, sizeof(ngx_event_t)); @@ -3283,12 +3081,7 @@ ngx_http_v2_create_stream(ngx_http_v2_co stream->send_window = h2c->init_window; stream->recv_window = h2scf->preread_size; - if (push) { - h2c->pushing++; - - } else { - h2c->processing++; - } + h2c->processing++; h2c->priority_limit += h2scf->concurrent_streams; @@ -3711,45 +3504,40 @@ ngx_http_v2_parse_scheme(ngx_http_reques static ngx_int_t ngx_http_v2_parse_authority(ngx_http_request_t *r, ngx_str_t *value) { - return ngx_http_v2_parse_header(r, &ngx_http_v2_parse_headers[0], value); -} - - -static ngx_int_t -ngx_http_v2_parse_header(ngx_http_request_t *r, - ngx_http_v2_parse_header_t *header, ngx_str_t *value) -{ ngx_table_elt_t *h; + ngx_http_header_t *hh; ngx_http_core_main_conf_t *cmcf; + static ngx_str_t host = ngx_string("host"); + h = ngx_list_push(&r->headers_in.headers); if (h == NULL) { return NGX_ERROR; } - h->key.len = header->name.len; - h->key.data = header->name.data; - h->lowcase_key = header->name.data; - - if (header->hh == NULL) { - header->hash = ngx_hash_key(header->name.data, header->name.len); - - cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); - - header->hh = ngx_hash_find(&cmcf->headers_in_hash, header->hash, - h->lowcase_key, h->key.len); - if (header->hh == NULL) { - return NGX_ERROR; - } - } - - h->hash = header->hash; + h->key.len = host.len; + h->key.data = host.data; + h->lowcase_key = host.data; + + h->hash = ngx_hash(ngx_hash(ngx_hash('h', 'o'), 's'), 't'); h->value.len = value->len; h->value.data = value->data; - if (header->hh->handler(r, h, header->hh->offset) != NGX_OK) { - /* header handler has already finalized request */ + cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); + + hh = ngx_hash_find(&cmcf->headers_in_hash, h->hash, + h->lowcase_key, h->key.len); + + if (hh == NULL) { + return NGX_ERROR; + } + + if (hh->handler(r, h, hh->offset) != NGX_OK) { + /* + * request has been finalized already + * in ngx_http_process_host() + */ return NGX_ABORT; } @@ -3992,22 +3780,6 @@ failed: } -static void -ngx_http_v2_run_request_handler(ngx_event_t *ev) -{ - ngx_connection_t *fc; - ngx_http_request_t *r; - - fc = ev->data; - r = fc->data; - - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0, - "http2 run request handler"); - - ngx_http_v2_run_request(r); -} - - ngx_int_t ngx_http_v2_read_request_body(ngx_http_request_t *r) { @@ -4611,7 +4383,6 @@ void ngx_http_v2_close_stream(ngx_http_v2_stream_t *stream, ngx_int_t rc) { ngx_pool_t *pool; - ngx_uint_t push; ngx_event_t *ev; ngx_connection_t *fc; ngx_http_v2_node_t *node; @@ -4620,10 +4391,9 @@ ngx_http_v2_close_stream(ngx_http_v2_str h2c = stream->connection; node = stream->node; - ngx_log_debug4(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, - "http2 close stream %ui, queued %ui, " - "processing %ui, pushing %ui", - node->id, stream->queued, h2c->processing, h2c->pushing); + ngx_log_debug3(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, + "http2 close stream %ui, queued %ui, processing %ui", + node->id, stream->queued, h2c->processing); fc = stream->request->connection; @@ -4658,8 +4428,6 @@ ngx_http_v2_close_stream(ngx_http_v2_str h2c->state.stream = NULL; } - push = stream->node->id % 2 == 0; - node->stream = NULL; ngx_queue_insert_tail(&h2c->closed, &node->reuse); @@ -4709,14 +4477,9 @@ ngx_http_v2_close_stream(ngx_http_v2_str fc->data = h2c->free_fake_connections; h2c->free_fake_connections = fc; - if (push) { - h2c->pushing--; - - } else { - h2c->processing--; - } - - if (h2c->processing || h2c->pushing || h2c->blocked) { + h2c->processing--; + + if (h2c->processing || h2c->blocked) { return; } @@ -4892,7 +4655,7 @@ ngx_http_v2_finalize_connection(ngx_http } } - if (!h2c->processing && !h2c->pushing) { + if (!h2c->processing) { goto done; } @@ -4940,7 +4703,7 @@ ngx_http_v2_finalize_connection(ngx_http h2c->blocked = 0; - if (h2c->processing || h2c->pushing) { + if (h2c->processing) { c->error = 1; return; } diff --git a/src/http/v2/ngx_http_v2.h b/src/http/v2/ngx_http_v2.h --- a/src/http/v2/ngx_http_v2.h +++ b/src/http/v2/ngx_http_v2.h @@ -24,8 +24,6 @@ #define NGX_HTTP_V2_MAX_FIELD \ (127 + (1 << (NGX_HTTP_V2_INT_OCTETS - 1) * 7) - 1) -#define NGX_HTTP_V2_STREAM_ID_SIZE 4 - #define NGX_HTTP_V2_FRAME_HEADER_SIZE 9 /* frame types */ @@ -67,7 +65,6 @@ typedef struct { ngx_flag_t enable; size_t pool_size; ngx_uint_t concurrent_streams; - ngx_uint_t concurrent_pushes; size_t preread_size; ngx_uint_t streams_index_mask; } ngx_http_v2_srv_conf_t; @@ -136,9 +133,6 @@ struct ngx_http_v2_connection_s { ngx_uint_t idle; ngx_uint_t priority_limit; - ngx_uint_t pushing; - ngx_uint_t concurrent_pushes; - size_t send_window; size_t recv_window; size_t init_window; @@ -165,7 +159,6 @@ struct ngx_http_v2_connection_s { ngx_uint_t closed_nodes; ngx_uint_t last_sid; - ngx_uint_t last_push; time_t lingering_time; @@ -173,7 +166,6 @@ struct ngx_http_v2_connection_s { unsigned table_update:1; unsigned blocked:1; unsigned goaway:1; - unsigned push_disabled:1; }; @@ -303,9 +295,6 @@ void ngx_http_v2_init(ngx_event_t *rev); ngx_int_t ngx_http_v2_read_request_body(ngx_http_request_t *r); ngx_int_t ngx_http_v2_read_unbuffered_request_body(ngx_http_request_t *r); -ngx_http_v2_stream_t *ngx_http_v2_push_stream(ngx_http_v2_stream_t *parent, - ngx_str_t *path); - void ngx_http_v2_close_stream(ngx_http_v2_stream_t *stream, ngx_int_t rc); ngx_int_t ngx_http_v2_send_output_queue(ngx_http_v2_connection_t *h2c); @@ -407,15 +396,12 @@ ngx_int_t ngx_http_v2_table_size(ngx_htt #define NGX_HTTP_V2_STATUS_404_INDEX 13 #define NGX_HTTP_V2_STATUS_500_INDEX 14 -#define NGX_HTTP_V2_ACCEPT_ENCODING_INDEX 16 -#define NGX_HTTP_V2_ACCEPT_LANGUAGE_INDEX 17 #define NGX_HTTP_V2_CONTENT_LENGTH_INDEX 28 #define NGX_HTTP_V2_CONTENT_TYPE_INDEX 31 #define NGX_HTTP_V2_DATE_INDEX 33 #define NGX_HTTP_V2_LAST_MODIFIED_INDEX 44 #define NGX_HTTP_V2_LOCATION_INDEX 46 #define NGX_HTTP_V2_SERVER_INDEX 54 -#define NGX_HTTP_V2_USER_AGENT_INDEX 58 #define NGX_HTTP_V2_VARY_INDEX 59 #define NGX_HTTP_V2_PREFACE_START "PRI * HTTP/2.0\r\n" diff --git a/src/http/v2/ngx_http_v2_filter_module.c b/src/http/v2/ngx_http_v2_filter_module.c --- a/src/http/v2/ngx_http_v2_filter_module.c +++ b/src/http/v2/ngx_http_v2_filter_module.c @@ -27,39 +27,8 @@ #define NGX_HTTP_V2_NO_TRAILERS (ngx_http_v2_out_frame_t *) -1 -typedef struct { - ngx_str_t name; - u_char index; - ngx_uint_t offset; -} ngx_http_v2_push_header_t; - - -static ngx_http_v2_push_header_t ngx_http_v2_push_headers[] = { - { ngx_string(":authority"), NGX_HTTP_V2_AUTHORITY_INDEX, - offsetof(ngx_http_headers_in_t, host) }, - - { ngx_string("accept-encoding"), NGX_HTTP_V2_ACCEPT_ENCODING_INDEX, - offsetof(ngx_http_headers_in_t, accept_encoding) }, - - { ngx_string("accept-language"), NGX_HTTP_V2_ACCEPT_LANGUAGE_INDEX, - offsetof(ngx_http_headers_in_t, accept_language) }, - - { ngx_string("user-agent"), NGX_HTTP_V2_USER_AGENT_INDEX, - offsetof(ngx_http_headers_in_t, user_agent) }, -}; - -#define NGX_HTTP_V2_PUSH_HEADERS \ - (sizeof(ngx_http_v2_push_headers) / sizeof(ngx_http_v2_push_header_t)) - - -static ngx_int_t ngx_http_v2_push_resources(ngx_http_request_t *r); -static ngx_int_t ngx_http_v2_push_resource(ngx_http_request_t *r, - ngx_str_t *path, ngx_str_t *binary); - static ngx_http_v2_out_frame_t *ngx_http_v2_create_headers_frame( ngx_http_request_t *r, u_char *pos, u_char *end, ngx_uint_t fin); -static ngx_http_v2_out_frame_t *ngx_http_v2_create_push_frame( - ngx_http_request_t *r, u_char *pos, u_char *end); static ngx_http_v2_out_frame_t *ngx_http_v2_create_trailers_frame( ngx_http_request_t *r); @@ -82,8 +51,6 @@ static ngx_inline ngx_int_t ngx_http_v2_ static ngx_int_t ngx_http_v2_headers_frame_handler( ngx_http_v2_connection_t *h2c, ngx_http_v2_out_frame_t *frame); -static ngx_int_t ngx_http_v2_push_frame_handler( - ngx_http_v2_connection_t *h2c, ngx_http_v2_out_frame_t *frame); static ngx_int_t ngx_http_v2_data_frame_handler( ngx_http_v2_connection_t *h2c, ngx_http_v2_out_frame_t *frame); static ngx_inline void ngx_http_v2_handle_frame( @@ -244,15 +211,6 @@ ngx_http_v2_header_filter(ngx_http_reque h2c = stream->connection; - if (!h2c->push_disabled && !h2c->goaway - && stream->node->id % 2 == 1 - && r->method != NGX_HTTP_HEAD) - { - if (ngx_http_v2_push_resources(r) != NGX_OK) { - return NGX_ERROR; - } - } - len = h2c->table_update ? 1 : 0; len += status ? 1 : 1 + ngx_http_v2_literal_size("418"); @@ -653,7 +611,7 @@ ngx_http_v2_header_filter(ngx_http_reque ngx_http_v2_queue_blocked_frame(h2c, frame); - stream->queued++; + stream->queued = 1; cln = ngx_http_cleanup_add(r, 0); if (cln == NULL) { @@ -671,409 +629,6 @@ ngx_http_v2_header_filter(ngx_http_reque } -static ngx_int_t -ngx_http_v2_push_resources(ngx_http_request_t *r) -{ - u_char *start, *end, *last; - ngx_int_t rc; - ngx_str_t path; - ngx_uint_t i, push; - ngx_table_elt_t *h; - ngx_http_v2_loc_conf_t *h2lcf; - ngx_http_complex_value_t *pushes; - ngx_str_t binary[NGX_HTTP_V2_PUSH_HEADERS]; - - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http2 push resources"); - - ngx_memzero(binary, NGX_HTTP_V2_PUSH_HEADERS * sizeof(ngx_str_t)); - - h2lcf = ngx_http_get_module_loc_conf(r, ngx_http_v2_module); - - if (h2lcf->pushes) { - pushes = h2lcf->pushes->elts; - - for (i = 0; i < h2lcf->pushes->nelts; i++) { - - if (ngx_http_complex_value(r, &pushes[i], &path) != NGX_OK) { - return NGX_ERROR; - } - - if (path.len == 0) { - continue; - } - - if (path.len == 3 && ngx_strncmp(path.data, "off", 3) == 0) { - continue; - } - - rc = ngx_http_v2_push_resource(r, &path, binary); - - if (rc == NGX_ERROR) { - return NGX_ERROR; - } - - if (rc == NGX_ABORT) { - return NGX_OK; - } - - /* NGX_OK, NGX_DECLINED */ - } - } - - if (!h2lcf->push_preload) { - return NGX_OK; - } - - for (h = r->headers_out.link; h; h = h->next) { - - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http2 parse link: \"%V\"", &h->value); - - start = h->value.data; - end = h->value.data + h->value.len; - - next_link: - - while (start < end && *start == ' ') { start++; } - - if (start == end || *start++ != '<') { - continue; - } - - while (start < end && *start == ' ') { start++; } - - for (last = start; last < end && *last != '>'; last++) { - /* void */ - } - - if (last == start || last == end) { - continue; - } - - path.len = last - start; - path.data = start; - - start = last + 1; - - while (start < end && *start == ' ') { start++; } - - if (start == end) { - continue; - } - - if (*start == ',') { - start++; - goto next_link; - } - - if (*start++ != ';') { - continue; - } - - last = ngx_strlchr(start, end, ','); - - if (last == NULL) { - last = end; - } - - push = 0; - - for ( ;; ) { - - while (start < last && *start == ' ') { start++; } - - if (last - start >= 6 - && ngx_strncasecmp(start, (u_char *) "nopush", 6) == 0) - { - start += 6; - - if (start == last || *start == ' ' || *start == ';') { - push = 0; - break; - } - - goto next_param; - } - - if (last - start >= 11 - && ngx_strncasecmp(start, (u_char *) "rel=preload", 11) == 0) - { - start += 11; - - if (start == last || *start == ' ' || *start == ';') { - push = 1; - } - - goto next_param; - } - - if (last - start >= 4 - && ngx_strncasecmp(start, (u_char *) "rel=", 4) == 0) - { - start += 4; - - while (start < last && *start == ' ') { start++; } - - if (start == last || *start++ != '"') { - goto next_param; - } - - for ( ;; ) { - - while (start < last && *start == ' ') { start++; } - - if (last - start >= 7 - && ngx_strncasecmp(start, (u_char *) "preload", 7) == 0) - { - start += 7; - - if (start < last && (*start == ' ' || *start == '"')) { - push = 1; - break; - } - } - - while (start < last && *start != ' ' && *start != '"') { - start++; - } - - if (start == last) { - break; - } - - if (*start == '"') { - break; - } - - start++; - } - } - - next_param: - - start = ngx_strlchr(start, last, ';'); - - if (start == NULL) { - break; - } - - start++; - } - - if (push) { - while (path.len && path.data[path.len - 1] == ' ') { - path.len--; - } - } - - if (push && path.len - && !(path.len > 1 && path.data[0] == '/' && path.data[1] == '/')) - { - rc = ngx_http_v2_push_resource(r, &path, binary); - - if (rc == NGX_ERROR) { - return NGX_ERROR; - } - - if (rc == NGX_ABORT) { - return NGX_OK; - } - - /* NGX_OK, NGX_DECLINED */ - } - - if (last < end) { - start = last + 1; - goto next_link; - } - } - - return NGX_OK; -} - - -static ngx_int_t -ngx_http_v2_push_resource(ngx_http_request_t *r, ngx_str_t *path, - ngx_str_t *binary) -{ - u_char *start, *pos, *tmp; - size_t len; - ngx_str_t *value; - ngx_uint_t i; - ngx_table_elt_t **h; - ngx_connection_t *fc; - ngx_http_v2_stream_t *stream; - ngx_http_v2_out_frame_t *frame; - ngx_http_v2_connection_t *h2c; - ngx_http_v2_push_header_t *ph; - - fc = r->connection; - - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0, "http2 push resource"); - - stream = r->stream; - h2c = stream->connection; - - if (!ngx_path_separator(path->data[0])) { - ngx_log_error(NGX_LOG_WARN, fc->log, 0, - "non-absolute path \"%V\" not pushed", path); - return NGX_DECLINED; - } - - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, - "http2 pushing:%ui limit:%ui", - h2c->pushing, h2c->concurrent_pushes); - - if (h2c->pushing >= h2c->concurrent_pushes) { - return NGX_ABORT; - } - - if (h2c->last_push == 0x7ffffffe) { - return NGX_ABORT; - } - - if (path->len > NGX_HTTP_V2_MAX_FIELD) { - return NGX_DECLINED; - } - - if (r->headers_in.host == NULL) { - return NGX_ABORT; - } - - ph = ngx_http_v2_push_headers; - - len = ngx_max(r->schema.len, path->len); - - if (binary[0].len) { - tmp = ngx_palloc(r->pool, len); - if (tmp == NULL) { - return NGX_ERROR; - } - - } else { - for (i = 0; i < NGX_HTTP_V2_PUSH_HEADERS; i++) { - h = (ngx_table_elt_t **) ((char *) &r->headers_in + ph[i].offset); - - if (*h) { - len = ngx_max(len, (*h)->value.len); - } - } - - tmp = ngx_palloc(r->pool, len); - if (tmp == NULL) { - return NGX_ERROR; - } - - for (i = 0; i < NGX_HTTP_V2_PUSH_HEADERS; i++) { - h = (ngx_table_elt_t **) ((char *) &r->headers_in + ph[i].offset); - - if (*h == NULL) { - continue; - } - - value = &(*h)->value; - - len = 1 + NGX_HTTP_V2_INT_OCTETS + value->len; - - pos = ngx_pnalloc(r->pool, len); - if (pos == NULL) { - return NGX_ERROR; - } - - binary[i].data = pos; - - *pos++ = ngx_http_v2_inc_indexed(ph[i].index); - pos = ngx_http_v2_write_value(pos, value->data, value->len, tmp); - - binary[i].len = pos - binary[i].data; - } - } - - len = (h2c->table_update ? 1 : 0) - + 1 - + 1 + NGX_HTTP_V2_INT_OCTETS + path->len - + 1 + NGX_HTTP_V2_INT_OCTETS + r->schema.len; - - for (i = 0; i < NGX_HTTP_V2_PUSH_HEADERS; i++) { - len += binary[i].len; - } - - pos = ngx_pnalloc(r->pool, len); - if (pos == NULL) { - return NGX_ERROR; - } - - start = pos; - - if (h2c->table_update) { - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0, - "http2 table size update: 0"); - *pos++ = (1 << 5) | 0; - h2c->table_update = 0; - } - - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0, - "http2 push header: \":method: GET\""); - - *pos++ = ngx_http_v2_indexed(NGX_HTTP_V2_METHOD_GET_INDEX); - - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, fc->log, 0, - "http2 push header: \":path: %V\"", path); - - *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_PATH_INDEX); - pos = ngx_http_v2_write_value(pos, path->data, path->len, tmp); - - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, fc->log, 0, - "http2 push header: \":scheme: %V\"", &r->schema); - - if (r->schema.len == 5 && ngx_strncmp(r->schema.data, "https", 5) == 0) { - *pos++ = ngx_http_v2_indexed(NGX_HTTP_V2_SCHEME_HTTPS_INDEX); - - } else if (r->schema.len == 4 - && ngx_strncmp(r->schema.data, "http", 4) == 0) - { - *pos++ = ngx_http_v2_indexed(NGX_HTTP_V2_SCHEME_HTTP_INDEX); - - } else { - *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_SCHEME_HTTP_INDEX); - pos = ngx_http_v2_write_value(pos, r->schema.data, r->schema.len, tmp); - } - - for (i = 0; i < NGX_HTTP_V2_PUSH_HEADERS; i++) { - h = (ngx_table_elt_t **) ((char *) &r->headers_in + ph[i].offset); - - if (*h == NULL) { - continue; - } - - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, fc->log, 0, - "http2 push header: \"%V: %V\"", - &ph[i].name, &(*h)->value); - - pos = ngx_cpymem(pos, binary[i].data, binary[i].len); - } - - frame = ngx_http_v2_create_push_frame(r, start, pos); - if (frame == NULL) { - return NGX_ERROR; - } - - ngx_http_v2_queue_blocked_frame(h2c, frame); - - stream->queued++; - - stream = ngx_http_v2_push_stream(stream, path); - - if (stream) { - stream->request->request_length = pos - start; - return NGX_OK; - } - - return NGX_ERROR; -} - - static ngx_http_v2_out_frame_t * ngx_http_v2_create_headers_frame(ngx_http_request_t *r, u_char *pos, u_char *end, ngx_uint_t fin) @@ -1180,125 +735,6 @@ ngx_http_v2_create_headers_frame(ngx_htt static ngx_http_v2_out_frame_t * -ngx_http_v2_create_push_frame(ngx_http_request_t *r, u_char *pos, u_char *end) -{ - u_char type, flags; - size_t rest, frame_size, len; - ngx_buf_t *b; - ngx_chain_t *cl, **ll; - ngx_http_v2_stream_t *stream; - ngx_http_v2_out_frame_t *frame; - ngx_http_v2_connection_t *h2c; - - stream = r->stream; - h2c = stream->connection; - rest = NGX_HTTP_V2_STREAM_ID_SIZE + (end - pos); - - frame = ngx_palloc(r->pool, sizeof(ngx_http_v2_out_frame_t)); - if (frame == NULL) { - return NULL; - } - - frame->handler = ngx_http_v2_push_frame_handler; - frame->stream = stream; - frame->length = rest; - frame->blocked = 1; - frame->fin = 0; - - ll = &frame->first; - - type = NGX_HTTP_V2_PUSH_PROMISE_FRAME; - flags = NGX_HTTP_V2_NO_FLAG; - frame_size = h2c->frame_size; - - for ( ;; ) { - if (rest <= frame_size) { - frame_size = rest; - flags |= NGX_HTTP_V2_END_HEADERS_FLAG; - } - - b = ngx_create_temp_buf(r->pool, - NGX_HTTP_V2_FRAME_HEADER_SIZE - + ((type == NGX_HTTP_V2_PUSH_PROMISE_FRAME) - ? NGX_HTTP_V2_STREAM_ID_SIZE : 0)); - if (b == NULL) { - return NULL; - } - - b->last = ngx_http_v2_write_len_and_type(b->last, frame_size, type); - *b->last++ = flags; - b->last = ngx_http_v2_write_sid(b->last, stream->node->id); - - b->tag = (ngx_buf_tag_t) &ngx_http_v2_module; - - if (type == NGX_HTTP_V2_PUSH_PROMISE_FRAME) { - h2c->last_push += 2; - - b->last = ngx_http_v2_write_sid(b->last, h2c->last_push); - len = frame_size - NGX_HTTP_V2_STREAM_ID_SIZE; - - } else { - len = frame_size; - } - - cl = ngx_alloc_chain_link(r->pool); - if (cl == NULL) { - return NULL; - } - - cl->buf = b; - - *ll = cl; - ll = &cl->next; - - b = ngx_calloc_buf(r->pool); - if (b == NULL) { - return NULL; - } - - b->pos = pos; - - pos += len; - - b->last = pos; - b->start = b->pos; - b->end = b->last; - b->temporary = 1; - - cl = ngx_alloc_chain_link(r->pool); - if (cl == NULL) { - return NULL; - } - - cl->buf = b; - - *ll = cl; - ll = &cl->next; - - rest -= frame_size; - - if (rest) { - frame->length += NGX_HTTP_V2_FRAME_HEADER_SIZE; - - type = NGX_HTTP_V2_CONTINUATION_FRAME; - continue; - } - - cl->next = NULL; - frame->last = cl; - - ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http2:%ui create PUSH_PROMISE frame %p: " - "sid:%ui len:%uz", - stream->node->id, frame, h2c->last_push, - frame->length); - - return frame; - } -} - - -static ngx_http_v2_out_frame_t * ngx_http_v2_create_trailers_frame(ngx_http_request_t *r) { u_char *pos, *start, *tmp; @@ -1902,62 +1338,6 @@ ngx_http_v2_headers_frame_handler(ngx_ht static ngx_int_t -ngx_http_v2_push_frame_handler(ngx_http_v2_connection_t *h2c, - ngx_http_v2_out_frame_t *frame) -{ - ngx_chain_t *cl, *ln; - ngx_http_v2_stream_t *stream; - - stream = frame->stream; - cl = frame->first; - - for ( ;; ) { - if (cl->buf->pos != cl->buf->last) { - frame->first = cl; - - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, - "http2:%ui PUSH_PROMISE frame %p was sent partially", - stream->node->id, frame); - - return NGX_AGAIN; - } - - ln = cl->next; - - if (cl->buf->tag == (ngx_buf_tag_t) &ngx_http_v2_module) { - cl->next = stream->free_frame_headers; - stream->free_frame_headers = cl; - - } else { - cl->next = stream->free_bufs; - stream->free_bufs = cl; - } - - if (cl == frame->last) { - break; - } - - cl = ln; - } - - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, - "http2:%ui PUSH_PROMISE frame %p was sent", - stream->node->id, frame); - - stream->request->header_size += NGX_HTTP_V2_FRAME_HEADER_SIZE - + frame->length; - - h2c->payload_bytes += frame->length; - - ngx_http_v2_handle_frame(stream, frame); - - ngx_http_v2_handle_stream(h2c, stream); - - return NGX_OK; -} - - -static ngx_int_t ngx_http_v2_data_frame_handler(ngx_http_v2_connection_t *h2c, ngx_http_v2_out_frame_t *frame) { diff --git a/src/http/v2/ngx_http_v2_module.c b/src/http/v2/ngx_http_v2_module.c --- a/src/http/v2/ngx_http_v2_module.c +++ b/src/http/v2/ngx_http_v2_module.c @@ -27,8 +27,6 @@ static void *ngx_http_v2_create_loc_conf static char *ngx_http_v2_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child); -static char *ngx_http_v2_push(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); - static char *ngx_http_v2_recv_buffer_size(ngx_conf_t *cf, void *post, void *data); static char *ngx_http_v2_pool_size(ngx_conf_t *cf, void *post, void *data); @@ -38,6 +36,8 @@ static char *ngx_http_v2_streams_index_m static char *ngx_http_v2_chunk_size(ngx_conf_t *cf, void *post, void *data); static char *ngx_http_v2_obsolete(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +static char *ngx_http_v2_obsolete_push(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); static ngx_conf_deprecated_t ngx_http_v2_recv_timeout_deprecated = { @@ -105,9 +105,9 @@ static ngx_command_t ngx_http_v2_comman { ngx_string("http2_max_concurrent_pushes"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_num_slot, - NGX_HTTP_SRV_CONF_OFFSET, - offsetof(ngx_http_v2_srv_conf_t, concurrent_pushes), + ngx_http_v2_obsolete_push, + 0, + 0, NULL }, { ngx_string("http2_max_requests"), @@ -168,15 +168,15 @@ static ngx_command_t ngx_http_v2_comman { ngx_string("http2_push_preload"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, - ngx_conf_set_flag_slot, - NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_v2_loc_conf_t, push_preload), + ngx_http_v2_obsolete_push, + 0, + 0, NULL }, { ngx_string("http2_push"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, - ngx_http_v2_push, - NGX_HTTP_LOC_CONF_OFFSET, + ngx_http_v2_obsolete_push, + 0, 0, NULL }, @@ -326,7 +326,6 @@ ngx_http_v2_create_srv_conf(ngx_conf_t * h2scf->pool_size = NGX_CONF_UNSET_SIZE; h2scf->concurrent_streams = NGX_CONF_UNSET_UINT; - h2scf->concurrent_pushes = NGX_CONF_UNSET_UINT; h2scf->preread_size = NGX_CONF_UNSET_SIZE; @@ -348,8 +347,6 @@ ngx_http_v2_merge_srv_conf(ngx_conf_t *c ngx_conf_merge_uint_value(conf->concurrent_streams, prev->concurrent_streams, 128); - ngx_conf_merge_uint_value(conf->concurrent_pushes, - prev->concurrent_pushes, 10); ngx_conf_merge_size_value(conf->preread_size, prev->preread_size, 65536); @@ -370,17 +367,8 @@ ngx_http_v2_create_loc_conf(ngx_conf_t * return NULL; } - /* - * set by ngx_pcalloc(): - * - * h2lcf->pushes = NULL; - */ - h2lcf->chunk_size = NGX_CONF_UNSET_SIZE; - h2lcf->push_preload = NGX_CONF_UNSET; - h2lcf->push = NGX_CONF_UNSET; - return h2lcf; } @@ -393,72 +381,6 @@ ngx_http_v2_merge_loc_conf(ngx_conf_t *c ngx_conf_merge_size_value(conf->chunk_size, prev->chunk_size, 8 * 1024); - ngx_conf_merge_value(conf->push, prev->push, 1); - - if (conf->push && conf->pushes == NULL) { - conf->pushes = prev->pushes; - } - - ngx_conf_merge_value(conf->push_preload, prev->push_preload, 0); - - return NGX_CONF_OK; -} - - -static char * -ngx_http_v2_push(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_http_v2_loc_conf_t *h2lcf = conf; - - ngx_str_t *value; - ngx_http_complex_value_t *cv; - ngx_http_compile_complex_value_t ccv; - - value = cf->args->elts; - - if (ngx_strcmp(value[1].data, "off") == 0) { - - if (h2lcf->pushes) { - return "\"off\" parameter cannot be used with URI"; - } - - if (h2lcf->push == 0) { - return "is duplicate"; - } - - h2lcf->push = 0; - return NGX_CONF_OK; - } - - if (h2lcf->push == 0) { - return "URI cannot be used with \"off\" parameter"; - } - - h2lcf->push = 1; - - if (h2lcf->pushes == NULL) { - h2lcf->pushes = ngx_array_create(cf->pool, 1, - sizeof(ngx_http_complex_value_t)); - if (h2lcf->pushes == NULL) { - return NGX_CONF_ERROR; - } - } - - cv = ngx_array_push(h2lcf->pushes); - if (cv == NULL) { - return NGX_CONF_ERROR; - } - - ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); - - ccv.cf = cf; - ccv.value = &value[1]; - ccv.complex_value = cv; - - if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { - return NGX_CONF_ERROR; - } - return NGX_CONF_OK; } @@ -569,3 +491,14 @@ ngx_http_v2_obsolete(ngx_conf_t *cf, ngx return NGX_CONF_OK; } + + +static char * +ngx_http_v2_obsolete_push(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + ngx_conf_log_error(NGX_LOG_WARN, cf, 0, + "HTTP/2 server push was removed, " + "the \"%V\" directive is obsolete", &cmd->name); + + return NGX_CONF_OK; +} diff --git a/src/http/v2/ngx_http_v2_module.h b/src/http/v2/ngx_http_v2_module.h --- a/src/http/v2/ngx_http_v2_module.h +++ b/src/http/v2/ngx_http_v2_module.h @@ -22,11 +22,6 @@ typedef struct { typedef struct { size_t chunk_size; - - ngx_flag_t push_preload; - - ngx_flag_t push; - ngx_array_t *pushes; } ngx_http_v2_loc_conf_t; From mat999 at gmail.com Thu Jun 1 11:29:58 2023 From: mat999 at gmail.com (Mathew Heard) Date: Thu, 1 Jun 2023 21:29:58 +1000 Subject: Thread Pool memory ownership In-Reply-To: References: Message-ID: Thank you, I understand and it makes sense. Do you have any advice for how third party modules could acheive the same? The blocked field might be safe to use within other phases but it's difficult to fully verify. I'm no longer using that module (having found an alternative) but I'm willing to push an issue to them in the spirit of oss. Perhaps a comment in the nginx developer docs regarding the correct way to get memory for a thread pool task would be a good idea? It seems like a common problem for which there is limited examples for reference. Thanks again for your help Maxim - Mathew On Wed, 31 May 2023, 12:15 pm Maxim Dounin, wrote: > Hello! > > On Wed, May 31, 2023 at 01:26:35AM +1000, Mathew Heard wrote: > > > I've been going through the threadpool code for native modules in an > > attempt to fix a third party module with what appears to be a > > use-after free error looking for inspiration. > > > > I thought I would see a strategy to prevent thread pool tasks that are > > in the queue for processing being freed when the request / connection > > their memory is allocated from is cleared but I'm not. > > > > For example there does not for example appear to be any protection > > against linux sendfile tasks from reading memory allocated from the > > ngx_connection_t if the connection is closed while the task is in the > > task queue. > > > > Is this correct? Is this a bug? > > As long as there is a thread task or an AIO request scheduled, the > request is expected to be blocked with r->blocked, so it won't be > freed. > > For sendfile in threads, this is done by > ngx_http_copy_thread_handler() (in > src/http/ngx_http_copy_filter_module.c), which is called by > ngx_linux_sendfile_thread() as file->file->thread_handler() when a > sendfile task is queued. > > -- > Maxim Dounin > http://mdounin.ru/ > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > https://mailman.nginx.org/mailman/listinfo/nginx-devel > -------------- next part -------------- An HTML attachment was scrubbed... URL: From stephen.farrell at cs.tcd.ie Thu Jun 1 11:31:16 2023 From: stephen.farrell at cs.tcd.ie (Stephen Farrell) Date: Thu, 1 Jun 2023 12:31:16 +0100 Subject: encrypted client hello (ECH) question Message-ID: <9d40cc8c-eada-6c8a-ee35-45e9e458d9fd@cs.tcd.ie> Hi all, I've been working on implementing TLS encrypted client hello (ECH, [1]) in the OpenSSL library (current branch at [2]). Apologies that this mail requires a bit of knowledge of what ECH does - I'd guess some folks on here will know that already but I'm happy to explain as needed. I have various proof of concept integrations for my code including with nginx (branch at [3]). Adding support for ECH when nginx terminates TLS was pretty straightforward but I have a question about whether the direction I've taken for ECH in "split-mode" is sensible or not. ECH "split-mode" is where nginx will do the ECH decryption but the TLS session is negotiated between the client and the upstream. I added some code [4] to the ssl preread stream module that does the ECH decryption of the initial ClientHello, then forwards on the decrypted ClientHello to the upstream. Again that was pretty easy and seems to work fine. The question that I have relates to when the TLS handshake between client and upstream hits a HelloRetryRequest. In that case the client will ECH encrypt it's second ClientHello but the ssl preread module doesn't get to see that 2nd ClientHello to attempt ECH decryption. So I ended up adding code [5] to the stream proxy module that checks if we're in that ECH split-mode + "pending" HRR state and attempts the ECH decryption if so. After (a lot:-) of trying to figure out where to put that code, it now also seems to work ok. But, I'm wondering if that's the right way to handle doing things with the 2nd ClientHello when we hit HRR and are using the stream module(s) but nginx is not terminating the TLS session? Any comments or advice most welcome! Thanks, Stephen. PS: It'll be a while before ECH is part of the OpenSSL library but once that's happening I do plan to follow up submitting these changes as they are at that time. [1] https://datatracker.ietf.org/doc/draft-ietf-tls-esni/ [2] https://github.com/sftcd/openssl/tree/ECH-draft-13c [3] https://github.com/sftcd/nginx/tree/ECH-experimental [4] https://github.com/sftcd/nginx/blob/ECH-experimental/src/stream/ngx_stream_ssl_preread_module.c#L129 [5] https://github.com/sftcd/nginx/blob/ECH-experimental/src/stream/ngx_stream_proxy_module.c#L1719 -------------- next part -------------- A non-text attachment was scrubbed... Name: OpenPGP_0xE4D8E9F997A833DD.asc Type: application/pgp-keys Size: 1197 bytes Desc: OpenPGP public key URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: OpenPGP_signature Type: application/pgp-signature Size: 236 bytes Desc: OpenPGP digital signature URL: From mat999 at gmail.com Thu Jun 1 12:14:36 2023 From: mat999 at gmail.com (Mathew Heard) Date: Thu, 1 Jun 2023 22:14:36 +1000 Subject: encrypted client hello (ECH) question In-Reply-To: <9d40cc8c-eada-6c8a-ee35-45e9e458d9fd@cs.tcd.ie> References: <9d40cc8c-eada-6c8a-ee35-45e9e458d9fd@cs.tcd.ie> Message-ID: Pretty cool. I'm still reading up on each but can this also be done for https termination? Is the SSL pre-read limitation the main issue there? On Thu, 1 Jun 2023, 9:31 pm Stephen Farrell, wrote: > > Hi all, > > I've been working on implementing TLS encrypted client hello > (ECH, [1]) in the OpenSSL library (current branch at [2]). > Apologies that this mail requires a bit of knowledge of > what ECH does - I'd guess some folks on here will know that > already but I'm happy to explain as needed. > > I have various proof of concept integrations for my code > including with nginx (branch at [3]). Adding support for > ECH when nginx terminates TLS was pretty straightforward > but I have a question about whether the direction I've > taken for ECH in "split-mode" is sensible or not. > > ECH "split-mode" is where nginx will do the ECH decryption > but the TLS session is negotiated between the client and > the upstream. I added some code [4] to the ssl preread > stream module that does the ECH decryption of the initial > ClientHello, then forwards on the decrypted ClientHello to > the upstream. Again that was pretty easy and seems to work > fine. > > The question that I have relates to when the TLS handshake > between client and upstream hits a HelloRetryRequest. In > that case the client will ECH encrypt it's second ClientHello > but the ssl preread module doesn't get to see that 2nd > ClientHello to attempt ECH decryption. > > So I ended up adding code [5] to the stream proxy module that > checks if we're in that ECH split-mode + "pending" HRR state > and attempts the ECH decryption if so. After (a lot:-) of > trying to figure out where to put that code, it now also > seems to work ok. > > But, I'm wondering if that's the right way to handle doing > things with the 2nd ClientHello when we hit HRR and are > using the stream module(s) but nginx is not terminating > the TLS session? > > Any comments or advice most welcome! > > Thanks, > Stephen. > > PS: It'll be a while before ECH is part of the OpenSSL > library but once that's happening I do plan to follow up > submitting these changes as they are at that time. > > [1] https://datatracker.ietf.org/doc/draft-ietf-tls-esni/ > [2] https://github.com/sftcd/openssl/tree/ECH-draft-13c > [3] https://github.com/sftcd/nginx/tree/ECH-experimental > [4] > > https://github.com/sftcd/nginx/blob/ECH-experimental/src/stream/ngx_stream_ssl_preread_module.c#L129 > [5] > > https://github.com/sftcd/nginx/blob/ECH-experimental/src/stream/ngx_stream_proxy_module.c#L1719 > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > https://mailman.nginx.org/mailman/listinfo/nginx-devel > -------------- next part -------------- An HTML attachment was scrubbed... URL: From artem.konev at nginx.com Thu Jun 1 12:22:22 2023 From: artem.konev at nginx.com (=?iso-8859-1?q?Artem_Konev?=) Date: Thu, 01 Jun 2023 13:22:22 +0100 Subject: [PATCH] Added NGINX Unit community call event Message-ID: xml/index.xml | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) # HG changeset patch # User Artem Konev # Date 1685619162 -3600 # Thu Jun 01 12:32:42 2023 +0100 # Node ID a0d330311dd5841a3641c07a00113ea8b7b4e544 # Parent 203f32f5373458548931a706e728fdf94daa6a77 Added NGINX Unit community call event. diff --git a/xml/index.xml b/xml/index.xml --- a/xml/index.xml +++ b/xml/index.xml @@ -7,6 +7,14 @@ + + +unit community call has been +announced +to facilitate open discussion of new features and the future direction. + + + nginx-1.25.0 From stephen.farrell at cs.tcd.ie Thu Jun 1 12:49:45 2023 From: stephen.farrell at cs.tcd.ie (Stephen Farrell) Date: Thu, 1 Jun 2023 13:49:45 +0100 Subject: encrypted client hello (ECH) question In-Reply-To: References: <9d40cc8c-eada-6c8a-ee35-45e9e458d9fd@cs.tcd.ie> Message-ID: <093527e2-bfd4-abc1-3c3d-5737eb36a9cd@cs.tcd.ie> Hiya, On 01/06/2023 13:14, Mathew Heard wrote: > Pretty cool. > > I'm still reading up on each but can this also be done for https > termination? Not quite sure what you mean by "https termination" but I think the split-mode+HRR case below is the only problematic one caused by ECH. ECH-enabling an nginx server that hosts a web site was pretty simple. In case it helps, the main new thing to configure is where the ECH private keys are stored and that then enables ECH decryption attempts. If that command ("echkeydir") is in the "http" stanza of the config then it'll apply to local web sites, if the command is in the "stream" stanza then it'll be used with relevant upstreams in ECH split-mode. There's a config file I use for testing at [6] that show how to support both ECH split-mode (upstream is foo.example.com on port 9444 which uses lighttpd in my test setup) and a local web site (example.com on port 9442). > Is the SSL pre-read limitation the main issue there? I think the new issue here is yes that the pre-read module was (sensibly) designed to only look at the 1st ClientHello whereas with ECH, something also needs to look at the 2nd one when we hit HRR. (I hit exactly the same problem when doing an haproxy integration.) The "something" I've found so far that works was to put the code at [5] into the proxy module, but I'm uncertain if that's the best way to do it. Cheers, S. [6] https://github.com/sftcd/openssl/blob/ECH-draft-13c/esnistuff/nginx-split.conf > > On Thu, 1 Jun 2023, 9:31 pm Stephen Farrell, > wrote: > >> >> Hi all, >> >> I've been working on implementing TLS encrypted client hello >> (ECH, [1]) in the OpenSSL library (current branch at [2]). >> Apologies that this mail requires a bit of knowledge of >> what ECH does - I'd guess some folks on here will know that >> already but I'm happy to explain as needed. >> >> I have various proof of concept integrations for my code >> including with nginx (branch at [3]). Adding support for >> ECH when nginx terminates TLS was pretty straightforward >> but I have a question about whether the direction I've >> taken for ECH in "split-mode" is sensible or not. >> >> ECH "split-mode" is where nginx will do the ECH decryption >> but the TLS session is negotiated between the client and >> the upstream. I added some code [4] to the ssl preread >> stream module that does the ECH decryption of the initial >> ClientHello, then forwards on the decrypted ClientHello to >> the upstream. Again that was pretty easy and seems to work >> fine. >> >> The question that I have relates to when the TLS handshake >> between client and upstream hits a HelloRetryRequest. In >> that case the client will ECH encrypt it's second ClientHello >> but the ssl preread module doesn't get to see that 2nd >> ClientHello to attempt ECH decryption. >> >> So I ended up adding code [5] to the stream proxy module that >> checks if we're in that ECH split-mode + "pending" HRR state >> and attempts the ECH decryption if so. After (a lot:-) of >> trying to figure out where to put that code, it now also >> seems to work ok. >> >> But, I'm wondering if that's the right way to handle doing >> things with the 2nd ClientHello when we hit HRR and are >> using the stream module(s) but nginx is not terminating >> the TLS session? >> >> Any comments or advice most welcome! >> >> Thanks, >> Stephen. >> >> PS: It'll be a while before ECH is part of the OpenSSL >> library but once that's happening I do plan to follow up >> submitting these changes as they are at that time. >> >> [1] https://datatracker.ietf.org/doc/draft-ietf-tls-esni/ >> [2] https://github.com/sftcd/openssl/tree/ECH-draft-13c >> [3] https://github.com/sftcd/nginx/tree/ECH-experimental >> [4] >> >> https://github.com/sftcd/nginx/blob/ECH-experimental/src/stream/ngx_stream_ssl_preread_module.c#L129 >> [5] >> >> https://github.com/sftcd/nginx/blob/ECH-experimental/src/stream/ngx_stream_proxy_module.c#L1719 >> _______________________________________________ >> nginx-devel mailing list >> nginx-devel at nginx.org >> https://mailman.nginx.org/mailman/listinfo/nginx-devel >> > > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > https://mailman.nginx.org/mailman/listinfo/nginx-devel -------------- next part -------------- A non-text attachment was scrubbed... Name: OpenPGP_0xE4D8E9F997A833DD.asc Type: application/pgp-keys Size: 1197 bytes Desc: OpenPGP public key URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: OpenPGP_signature Type: application/pgp-signature Size: 236 bytes Desc: OpenPGP digital signature URL: From mdounin at mdounin.ru Thu Jun 1 14:06:07 2023 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 1 Jun 2023 17:06:07 +0300 Subject: Thread Pool memory ownership In-Reply-To: References: Message-ID: Hello! On Thu, Jun 01, 2023 at 09:29:58PM +1000, Mathew Heard wrote: > Thank you, > > I understand and it makes sense. > > Do you have any advice for how third party modules could acheive the same? > The blocked field might be safe to use within other phases but it's > difficult to fully verify. > > I'm no longer using that module (having found an alternative) but I'm > willing to push an issue to them in the spirit of oss. For http, using r->blocked to prevent request from being freed is the correct and the only available approach. > Perhaps a comment in the nginx developer docs regarding the correct way to > get memory for a thread pool task would be a good idea? It seems like a > common problem for which there is limited examples for reference. While it might be, I doubt there are people willing to and qualified enough to work on this. In general, nginx is documented in C and commit logs, and existing developer docs only explain some basic concepts. -- Maxim Dounin http://mdounin.ru/ From pluknet at nginx.com Thu Jun 1 14:16:42 2023 From: pluknet at nginx.com (=?iso-8859-1?q?Sergey_Kandaurov?=) Date: Thu, 01 Jun 2023 18:16:42 +0400 Subject: [PATCH 1 of 2] Removed obsolete SPDY documentation Message-ID: # HG changeset patch # User Sergey Kandaurov # Date 1685628905 -14400 # Thu Jun 01 18:15:05 2023 +0400 # Node ID b891dba3aadb77b0a4621a981edbb1c6a8d3c5be # Parent 203f32f5373458548931a706e728fdf94daa6a77 Removed obsolete SPDY documentation. diff --git a/xml/en/docs/http/ngx_http_core_module.xml b/xml/en/docs/http/ngx_http_core_module.xml --- a/xml/en/docs/http/ngx_http_core_module.xml +++ b/xml/en/docs/http/ngx_http_core_module.xml @@ -10,7 +10,7 @@ + rev="105">
@@ -1272,8 +1272,7 @@ The “wait-read-ignore” cycle is repeated, but no longer than specified by the [default_server] [ssl] [http2 | - quic | - spdy] + quic] [proxy_protocol] [setfib=number] [fastopen=number] @@ -1291,8 +1290,7 @@ The “wait-read-ignore” cycle is repeated, but no longer than specified by the [default_server] [ssl] [http2 | - quic | - spdy] + quic] [proxy_protocol] [setfib=number] [fastopen=number] @@ -1310,8 +1308,7 @@ The “wait-read-ignore” cycle is repeated, but no longer than specified by the [default_server] [ssl] [http2 | - quic | - spdy] + quic] [proxy_protocol] [backlog=number] [rcvbuf=size] @@ -1395,14 +1392,6 @@ The quic parameter (1 -The spdy parameter (1.3.15-1.9.4) allows accepting -SPDY connections on this port. -Normally, for this to work the ssl parameter should be -specified as well, but nginx can also be configured to accept SPDY -connections without SSL. - - - The proxy_protocol parameter (1.5.12) allows specifying that all connections accepted on this port should use the PROXY diff --git a/xml/en/docs/http/ngx_http_spdy_module.xml b/xml/en/docs/http/ngx_http_spdy_module.xml --- a/xml/en/docs/http/ngx_http_spdy_module.xml +++ b/xml/en/docs/http/ngx_http_spdy_module.xml @@ -9,155 +9,14 @@ + rev="11">
-The ngx_http_spdy_module module provides experimental -support for SPDY. -Currently, -draft -3.1 of SPDY protocol is implemented. - -Before version 1.5.10, -draft -2 of SPDY protocol was implemented. - - - - -This module is not built by default, it should be enabled with -the --with-http_spdy_module -configuration parameter. - - - - This module was superseded by the ngx_http_v2_module module in 1.9.5. - - - -
- - -
- - -The module is experimental, caveat emptor applies. - - - -Current implementation of SPDY protocol does not support “server push”. - - - -In versions prior to 1.5.9, responses in SPDY connections could not be -rate limited. - - - -Buffering of a client request body cannot be disabled -regardless of -, -, -, and - -directive values. - - -
- - -
- - - -server { - listen 443 ssl spdy; - - ssl_certificate server.crt; - ssl_certificate_key server.key; - ... -} - - -Note that in order to accept both -HTTPS and SPDY connections -simultaneously on the same port, -OpenSSL library used should support -“Next Protocol Negotiation” TLS extension, available since OpenSSL -version 1.0.1. - - - -
- - -
- - -size -8k -http -server -location -1.5.9 - - -Sets the maximum size of chunks -into which the response body is - -sliced. -A too low value results in higher overhead. -A too high value impairs prioritization due to - -HOL blocking. - - - - - - -level -0 -http -server - - -Sets the header compression level of a response in a range from -1 (fastest, less compression) to 9 (slowest, best compression). -The special value 0 turns off the header compression. - - - - -
- - -
- - -The ngx_http_spdy_module module -supports the following embedded variables: - - -$spdy - -SPDY protocol version for SPDY connections, -or an empty string otherwise; - - -$spdy_request_priority - - -request priority for SPDY connections, -or an empty string otherwise. - - -
diff --git a/xml/en/docs/http/ngx_http_v2_module.xml b/xml/en/docs/http/ngx_http_v2_module.xml --- a/xml/en/docs/http/ngx_http_v2_module.xml +++ b/xml/en/docs/http/ngx_http_v2_module.xml @@ -15,9 +15,8 @@ The ngx_http_v2_module module (1.9.5) provides -support for HTTP/2 -and supersedes the -ngx_http_spdy_module module. +support for +HTTP/2. diff --git a/xml/en/docs/index.xml b/xml/en/docs/index.xml --- a/xml/en/docs/index.xml +++ b/xml/en/docs/index.xml @@ -8,7 +8,7 @@
@@ -434,11 +434,6 @@ ngx_http_slice_module - -ngx_http_spdy_module - - - ngx_http_split_clients_module diff --git a/xml/ru/docs/http/ngx_http_core_module.xml b/xml/ru/docs/http/ngx_http_core_module.xml --- a/xml/ru/docs/http/ngx_http_core_module.xml +++ b/xml/ru/docs/http/ngx_http_core_module.xml @@ -10,7 +10,7 @@ + rev="105">
@@ -1266,8 +1266,7 @@ location /flv/ { [default_server] [ssl] [http2 | - quic | - spdy] + quic] [proxy_protocol] [setfib=число] [fastopen=число] @@ -1285,8 +1284,7 @@ location /flv/ { [default_server] [ssl] [http2 | - quic | - spdy] + quic] [proxy_protocol] [setfib=число] [fastopen=число] @@ -1304,8 +1302,7 @@ location /flv/ { [default_server] [ssl] [http2 | - quic | - spdy] + quic] [proxy_protocol] [backlog=число] [rcvbuf=размер] @@ -1387,14 +1384,6 @@ HTTP/2-соединений без SSL. -Параметр spdy (1.3.15-1.9.4) позволяет принимать на этом порту -SPDY-соединения. -Обычно, чтобы это работало, следует также указать параметр -ssl, однако nginx можно также настроить и на приём -SPDY-соединений без SSL. - - - Параметр proxy_protocol (1.5.12) указывает на то, что все соединения, принимаемые на данном порту, должны использовать diff --git a/xml/ru/docs/http/ngx_http_spdy_module.xml b/xml/ru/docs/http/ngx_http_spdy_module.xml --- a/xml/ru/docs/http/ngx_http_spdy_module.xml +++ b/xml/ru/docs/http/ngx_http_spdy_module.xml @@ -9,156 +9,14 @@ + rev="11">
-Модуль ngx_http_spdy_module обеспечивает экспериментальную -поддержку SPDY. -В настоящий момент реализован -draft -3.1 протокола SPDY. - -До версии 1.5.10 был реализован -draft -2 протокола SPDY. - - - - -По умолчанию этот модуль не собирается, его сборку необходимо -разрешить с помощью конфигурационного параметра ---with-http_spdy_module. - - - - Этот модуль был заменён модулем ngx_http_v2_module в версии 1.9.5. - - - -
- - -
- - -Модуль экспериментальный, поэтому возможно всё. - - - -Текущая реализация протокола SPDY не поддерживает server push. - - - -До версии 1.5.9 скорость передачи ответа клиенту в SPDY-соединении не могла быть -ограничена. - - - -Буферизация тела запроса клиента не может быть выключена -независимо от значения директив -, -, - и -. - - -
- - -
- - - -server { - listen 443 ssl spdy; - - ssl_certificate server.crt; - ssl_certificate_key server.key; - ... -} - - -Для того чтобы одновременно принимать -HTTPS и -SPDY соединения на том же порту, -используемая библиотека OpenSSL -должна поддерживать расширение Next Protocol Negotiation протокола TLS, -доступное с версии OpenSSL 1.0.1. - - - -
- - -
- - -размер -8k -http -server -location -1.5.9 - - -Задаёт максимальный размер частей, -на которые будет - -разделяться тело ответа. -Слишком маленькое значение может -привести к росту накладных расходов. -Слишком большое значение может -негативно сказаться на приоритизации из-за - -блокировки очереди. - - - - - - -степень -0 -http -server - - -Устанавливает степень сжатия заголовков ответа -в диапазоне от 1 (быстрее, но хуже сжатие) до 9 (медленнее, лучшее сжатие). -Специальное значение 0 отключает сжатие заголовков. - - - - -
- - -
- - -Модуль ngx_http_spdy_module -поддерживает следующие встроенные переменные: - - -$spdy - -версия протокола SPDY для SPDY-соединений, -либо пустая строка; - - -$spdy_request_priority - - -приоритет запроса для SPDY-соединений, -либо пустая строка. - - -
diff --git a/xml/ru/docs/http/ngx_http_v2_module.xml b/xml/ru/docs/http/ngx_http_v2_module.xml --- a/xml/ru/docs/http/ngx_http_v2_module.xml +++ b/xml/ru/docs/http/ngx_http_v2_module.xml @@ -15,9 +15,8 @@ Модуль ngx_http_v2_module (1.9.5) обеспечивает -поддержку HTTP/2 -и заменяет -модуль ngx_http_spdy_module. +поддержку +HTTP/2. diff --git a/xml/ru/docs/index.xml b/xml/ru/docs/index.xml --- a/xml/ru/docs/index.xml +++ b/xml/ru/docs/index.xml @@ -8,7 +8,7 @@
@@ -439,11 +439,6 @@ ngx_http_slice_module - -ngx_http_spdy_module - - - ngx_http_split_clients_module From pluknet at nginx.com Thu Jun 1 14:16:43 2023 From: pluknet at nginx.com (=?iso-8859-1?q?Sergey_Kandaurov?=) Date: Thu, 01 Jun 2023 18:16:43 +0400 Subject: [PATCH 2 of 2] Mention HTTP/3 on the index page In-Reply-To: References: Message-ID: <08e1ceba17535e7f42a8.1685629003@enoparse.local> # HG changeset patch # User Sergey Kandaurov # Date 1685628906 -14400 # Thu Jun 01 18:15:06 2023 +0400 # Node ID 08e1ceba17535e7f42a8ece311686f977b593a78 # Parent b891dba3aadb77b0a4621a981edbb1c6a8d3c5be Mention HTTP/3 on the index page. diff --git a/xml/en/index.xml b/xml/en/index.xml --- a/xml/en/index.xml +++ b/xml/en/index.xml @@ -8,7 +8,7 @@
+ rev="156">
@@ -100,7 +100,11 @@ TLS SNI support; Support for HTTP/2 -with weighted and dependency-based prioritization. +with weighted and dependency-based prioritization; + + + +Support for HTTP/3. diff --git a/xml/ru/index.xml b/xml/ru/index.xml --- a/xml/ru/index.xml +++ b/xml/ru/index.xml @@ -8,7 +8,7 @@
+ rev="156">
@@ -101,7 +101,11 @@ chunked ответы, Поддержка HTTP/2 -с приоритизацией на основе весов и зависимостей. +с приоритизацией на основе весов и зависимостей; + + + +Поддержка HTTP/3. From pluknet at nginx.com Thu Jun 1 14:29:38 2023 From: pluknet at nginx.com (Sergey Kandaurov) Date: Thu, 1 Jun 2023 18:29:38 +0400 Subject: [PATCH] Added NGINX Unit community call event In-Reply-To: References: Message-ID: <9B8F52FD-AE53-4A7D-AEC7-FAE5ADB10BFF@nginx.com> > On 1 Jun 2023, at 16:22, Artem Konev wrote: > > xml/index.xml | 8 ++++++++ > 1 files changed, 8 insertions(+), 0 deletions(-) > > > # HG changeset patch > # User Artem Konev > # Date 1685619162 -3600 > # Thu Jun 01 12:32:42 2023 +0100 > # Node ID a0d330311dd5841a3641c07a00113ea8b7b4e544 > # Parent 203f32f5373458548931a706e728fdf94daa6a77 > Added NGINX Unit community call event. > > diff --git a/xml/index.xml b/xml/index.xml > --- a/xml/index.xml > +++ b/xml/index.xml > @@ -7,6 +7,14 @@ > > > > + > + > +unit community call has been > +announced > +to facilitate open discussion of new features and the future direction. > + > + > + > > > nginx-1.25.0 Looks good. -- Sergey Kandaurov From v.zhestikov at f5.com Thu Jun 1 16:41:59 2023 From: v.zhestikov at f5.com (Vadim Zhestikov) Date: Thu, 01 Jun 2023 16:41:59 +0000 Subject: [njs] Fixed parsing of invalid for-in statement. Message-ID: details: https://hg.nginx.org/njs/rev/aa05db6d896f branches: changeset: 2144:aa05db6d896f user: Vadim Zhestikov date: Thu Jun 01 09:39:25 2023 -0700 description: Fixed parsing of invalid for-in statement. The issue was introduced in: b9d18d4dd34e diffstat: src/njs_parser.c | 4 ++++ src/test/njs_unit_test.c | 3 +++ 2 files changed, 7 insertions(+), 0 deletions(-) diffs (27 lines): diff -r ab54ef24feac -r aa05db6d896f src/njs_parser.c --- a/src/njs_parser.c Sun May 28 15:36:46 2023 +0100 +++ b/src/njs_parser.c Thu Jun 01 09:39:25 2023 -0700 @@ -5496,6 +5496,10 @@ njs_parser_for_expression_map_reparse(nj { njs_str_t *text; + if (parser->ret != NJS_OK && parser->node != NULL) { + return njs_parser_failed(parser); + } + if (parser->node == NULL) { njs_lexer_in_fail_set(parser->lexer, 1); diff -r ab54ef24feac -r aa05db6d896f src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Sun May 28 15:36:46 2023 +0100 +++ b/src/test/njs_unit_test.c Thu Jun 01 09:39:25 2023 -0700 @@ -2969,6 +2969,9 @@ static njs_unit_test_t njs_test[] = { njs_str("for (a(b * in d) ;"), njs_str("SyntaxError: Unexpected token \"in\" in 1") }, + { njs_str("for(c=let c"), + njs_str("SyntaxError: Unexpected token \"let\" in 1") }, + /* switch. */ { njs_str("switch"), From v.zhestikov at f5.com Thu Jun 1 16:42:01 2023 From: v.zhestikov at f5.com (Vadim Zhestikov) Date: Thu, 01 Jun 2023 16:42:01 +0000 Subject: [njs] Fixed parsing of invalid for-var statement. Message-ID: details: https://hg.nginx.org/njs/rev/d73bfec720b9 branches: changeset: 2145:d73bfec720b9 user: Vadim Zhestikov date: Thu Jun 01 09:39:27 2023 -0700 description: Fixed parsing of invalid for-var statement. diffstat: src/njs_parser.c | 10 ++++------ src/test/njs_unit_test.c | 3 +++ 2 files changed, 7 insertions(+), 6 deletions(-) diffs (33 lines): diff -r aa05db6d896f -r d73bfec720b9 src/njs_parser.c --- a/src/njs_parser.c Thu Jun 01 09:39:25 2023 -0700 +++ b/src/njs_parser.c Thu Jun 01 09:39:27 2023 -0700 @@ -5908,12 +5908,10 @@ njs_parser_for_var_binding_or_var_list(n njs_lexer_consume_token(parser->lexer, 2); return NJS_DONE; - } - - parser->node = NULL; - - njs_parser_next(parser, njs_parser_expression); - return NJS_OK; + + } else { + return njs_parser_failed(parser); + } } } diff -r aa05db6d896f -r d73bfec720b9 src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Thu Jun 01 09:39:25 2023 -0700 +++ b/src/test/njs_unit_test.c Thu Jun 01 09:39:27 2023 -0700 @@ -2972,6 +2972,9 @@ static njs_unit_test_t njs_test[] = { njs_str("for(c=let c"), njs_str("SyntaxError: Unexpected token \"let\" in 1") }, + { njs_str("for(var``>0; 0 ;) ;"), + njs_str("SyntaxError: Unexpected token \"`\" in 1") }, + /* switch. */ { njs_str("switch"), From arut at nginx.com Fri Jun 2 07:28:22 2023 From: arut at nginx.com (=?iso-8859-1?q?Roman_Arutyunyan?=) Date: Fri, 02 Jun 2023 11:28:22 +0400 Subject: [PATCH] SSL: removed the "ssl" directive Message-ID: <564c8f447ea4d76d8025.1685690902@arut-laptop> # HG changeset patch # User Roman Arutyunyan # Date 1685447035 -14400 # Tue May 30 15:43:55 2023 +0400 # Node ID 564c8f447ea4d76d80251bbf07df412942a2261f # Parent b4a57278bf24dd28d39afea0eb09732c05bf1606 SSL: removed the "ssl" directive. It has been deprecated since 46c0c7ef4913 (1.15.0); diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c --- a/src/http/modules/ngx_http_ssl_module.c +++ b/src/http/modules/ngx_http_ssl_module.c @@ -43,8 +43,6 @@ static char *ngx_http_ssl_merge_srv_conf static ngx_int_t ngx_http_ssl_compile_certificates(ngx_conf_t *cf, ngx_http_ssl_srv_conf_t *conf); -static char *ngx_http_ssl_enable(ngx_conf_t *cf, ngx_command_t *cmd, - void *conf); static char *ngx_http_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char *ngx_http_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd, @@ -90,24 +88,12 @@ static ngx_conf_enum_t ngx_http_ssl_ocs }; -static ngx_conf_deprecated_t ngx_http_ssl_deprecated = { - ngx_conf_deprecated, "ssl", "listen ... ssl" -}; - - static ngx_conf_post_t ngx_http_ssl_conf_command_post = { ngx_http_ssl_conf_command_check }; static ngx_command_t ngx_http_ssl_commands[] = { - { ngx_string("ssl"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG, - ngx_http_ssl_enable, - NGX_HTTP_SRV_CONF_OFFSET, - offsetof(ngx_http_ssl_srv_conf_t, enable), - &ngx_http_ssl_deprecated }, - { ngx_string("ssl_certificate"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, ngx_conf_set_str_array_slot, @@ -617,7 +603,6 @@ ngx_http_ssl_create_srv_conf(ngx_conf_t * sscf->stapling_responder = { 0, NULL }; */ - sscf->enable = NGX_CONF_UNSET; sscf->prefer_server_ciphers = NGX_CONF_UNSET; sscf->early_data = NGX_CONF_UNSET; sscf->reject_handshake = NGX_CONF_UNSET; @@ -649,17 +634,6 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t * ngx_pool_cleanup_t *cln; - if (conf->enable == NGX_CONF_UNSET) { - if (prev->enable == NGX_CONF_UNSET) { - conf->enable = 0; - - } else { - conf->enable = prev->enable; - conf->file = prev->file; - conf->line = prev->line; - } - } - ngx_conf_merge_value(conf->session_timeout, prev->session_timeout, 300); @@ -714,37 +688,7 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t * conf->ssl.log = cf->log; - if (conf->enable) { - - if (conf->certificates) { - if (conf->certificate_keys == NULL) { - ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "no \"ssl_certificate_key\" is defined for " - "the \"ssl\" directive in %s:%ui", - conf->file, conf->line); - return NGX_CONF_ERROR; - } - - if (conf->certificate_keys->nelts < conf->certificates->nelts) { - ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "no \"ssl_certificate_key\" is defined " - "for certificate \"%V\" and " - "the \"ssl\" directive in %s:%ui", - ((ngx_str_t *) conf->certificates->elts) - + conf->certificates->nelts - 1, - conf->file, conf->line); - return NGX_CONF_ERROR; - } - - } else if (!conf->reject_handshake) { - ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "no \"ssl_certificate\" is defined for " - "the \"ssl\" directive in %s:%ui", - conf->file, conf->line); - return NGX_CONF_ERROR; - } - - } else if (conf->certificates) { + if (conf->certificates) { if (conf->certificate_keys == NULL || conf->certificate_keys->nelts < conf->certificates->nelts) @@ -1031,26 +975,6 @@ found: static char * -ngx_http_ssl_enable(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_http_ssl_srv_conf_t *sscf = conf; - - char *rv; - - rv = ngx_conf_set_flag_slot(cf, cmd, conf); - - if (rv != NGX_CONF_OK) { - return rv; - } - - sscf->file = cf->conf_file->file.name.data; - sscf->line = cf->conf_file->line; - - return NGX_CONF_OK; -} - - -static char * ngx_http_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_ssl_srv_conf_t *sscf = conf; diff --git a/src/http/modules/ngx_http_ssl_module.h b/src/http/modules/ngx_http_ssl_module.h --- a/src/http/modules/ngx_http_ssl_module.h +++ b/src/http/modules/ngx_http_ssl_module.h @@ -15,8 +15,6 @@ typedef struct { - ngx_flag_t enable; - ngx_ssl_t ssl; ngx_flag_t prefer_server_ciphers; @@ -64,9 +62,6 @@ typedef struct { ngx_flag_t stapling_verify; ngx_str_t stapling_file; ngx_str_t stapling_responder; - - u_char *file; - ngx_uint_t line; } ngx_http_ssl_srv_conf_t; diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -332,17 +332,11 @@ ngx_http_init_connection(ngx_connection_ #endif #if (NGX_HTTP_SSL) - { - ngx_http_ssl_srv_conf_t *sscf; - - sscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_ssl_module); - - if (sscf->enable || hc->addr_conf->ssl) { + if (hc->addr_conf->ssl) { hc->ssl = 1; c->log->action = "SSL handshaking"; rev->handler = ngx_http_ssl_handshake; } - } #endif if (hc->addr_conf->proxy_protocol) { diff --git a/src/mail/ngx_mail_handler.c b/src/mail/ngx_mail_handler.c --- a/src/mail/ngx_mail_handler.c +++ b/src/mail/ngx_mail_handler.c @@ -283,10 +283,10 @@ ngx_mail_init_session_handler(ngx_event_ s = c->data; - sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); + if (s->ssl) { + c->log->action = "SSL handshaking"; - if (sslcf->enable || s->ssl) { - c->log->action = "SSL handshaking"; + sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); ngx_mail_ssl_init_connection(&sslcf->ssl, c); return; diff --git a/src/mail/ngx_mail_ssl_module.c b/src/mail/ngx_mail_ssl_module.c --- a/src/mail/ngx_mail_ssl_module.c +++ b/src/mail/ngx_mail_ssl_module.c @@ -23,8 +23,6 @@ static int ngx_mail_ssl_alpn_select(ngx_ static void *ngx_mail_ssl_create_conf(ngx_conf_t *cf); static char *ngx_mail_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child); -static char *ngx_mail_ssl_enable(ngx_conf_t *cf, ngx_command_t *cmd, - void *conf); static char *ngx_mail_ssl_starttls(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char *ngx_mail_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, @@ -65,24 +63,12 @@ static ngx_conf_enum_t ngx_mail_ssl_ver }; -static ngx_conf_deprecated_t ngx_mail_ssl_deprecated = { - ngx_conf_deprecated, "ssl", "listen ... ssl" -}; - - static ngx_conf_post_t ngx_mail_ssl_conf_command_post = { ngx_mail_ssl_conf_command_check }; static ngx_command_t ngx_mail_ssl_commands[] = { - { ngx_string("ssl"), - NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_FLAG, - ngx_mail_ssl_enable, - NGX_MAIL_SRV_CONF_OFFSET, - offsetof(ngx_mail_ssl_conf_t, enable), - &ngx_mail_ssl_deprecated }, - { ngx_string("starttls"), NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, ngx_mail_ssl_starttls, @@ -322,7 +308,6 @@ ngx_mail_ssl_create_conf(ngx_conf_t *cf) * scf->shm_zone = NULL; */ - scf->enable = NGX_CONF_UNSET; scf->starttls = NGX_CONF_UNSET_UINT; scf->certificates = NGX_CONF_UNSET_PTR; scf->certificate_keys = NGX_CONF_UNSET_PTR; @@ -349,7 +334,6 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, char *mode; ngx_pool_cleanup_t *cln; - ngx_conf_merge_value(conf->enable, prev->enable, 0); ngx_conf_merge_uint_value(conf->starttls, prev->starttls, NGX_MAIL_STARTTLS_OFF); @@ -394,9 +378,6 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, if (conf->listen) { mode = "listen ... ssl"; - } else if (conf->enable) { - mode = "ssl"; - } else if (conf->starttls != NGX_MAIL_STARTTLS_OFF) { mode = "starttls"; @@ -546,34 +527,6 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, static char * -ngx_mail_ssl_enable(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_mail_ssl_conf_t *scf = conf; - - char *rv; - - rv = ngx_conf_set_flag_slot(cf, cmd, conf); - - if (rv != NGX_CONF_OK) { - return rv; - } - - if (scf->enable && (ngx_int_t) scf->starttls > NGX_MAIL_STARTTLS_OFF) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "\"starttls\" directive conflicts with \"ssl on\""); - return NGX_CONF_ERROR; - } - - if (!scf->listen) { - scf->file = cf->conf_file->file.name.data; - scf->line = cf->conf_file->line; - } - - return NGX_CONF_OK; -} - - -static char * ngx_mail_ssl_starttls(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_mail_ssl_conf_t *scf = conf; @@ -586,12 +539,6 @@ ngx_mail_ssl_starttls(ngx_conf_t *cf, ng return rv; } - if (scf->enable == 1 && (ngx_int_t) scf->starttls > NGX_MAIL_STARTTLS_OFF) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "\"ssl\" directive conflicts with \"starttls\""); - return NGX_CONF_ERROR; - } - if (!scf->listen) { scf->file = cf->conf_file->file.name.data; scf->line = cf->conf_file->line; diff --git a/src/mail/ngx_mail_ssl_module.h b/src/mail/ngx_mail_ssl_module.h --- a/src/mail/ngx_mail_ssl_module.h +++ b/src/mail/ngx_mail_ssl_module.h @@ -20,7 +20,6 @@ typedef struct { - ngx_flag_t enable; ngx_flag_t prefer_server_ciphers; ngx_ssl_t ssl; From mdounin at mdounin.ru Fri Jun 2 21:37:03 2023 From: mdounin at mdounin.ru (Maxim Dounin) Date: Sat, 3 Jun 2023 00:37:03 +0300 Subject: [PATCH 2 of 3] HTTP/2: "http2" directive In-Reply-To: <20230516123938.rgrmdpern3i5hq5n@N00W24XTQX> References: <735f9e501922e4b0a1b2.1675781431@arut-laptop> <20230209120234.rttyjviwir4sneed@N00W24XTQX> <20230209123359.i6fosl5r6tdhpvhv@N00W24XTQX> <71CADCEB-5BD1-4F67-AE85-581943918D5B@nginx.com> <20230516123938.rgrmdpern3i5hq5n@N00W24XTQX> Message-ID: Hello! On Tue, May 16, 2023 at 04:39:38PM +0400, Roman Arutyunyan wrote: > On Thu, Feb 09, 2023 at 07:56:55PM +0400, Sergey Kandaurov wrote: > > > > > On 9 Feb 2023, at 16:33, Roman Arutyunyan wrote: > > > > > > Hi, > > > > > > On Thu, Feb 09, 2023 at 04:02:34PM +0400, Roman Arutyunyan wrote: > > > > > > [..] > > > > > >> diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c > > >> --- a/src/http/ngx_http_request.c > > >> +++ b/src/http/ngx_http_request.c > > >> @@ -318,12 +318,6 @@ ngx_http_init_connection(ngx_connection_ > > >> rev->handler = ngx_http_wait_request_handler; > > >> c->write->handler = ngx_http_empty_handler; > > >> > > >> -#if (NGX_HTTP_V2) > > >> - if (hc->addr_conf->http2) { > > >> - rev->handler = ngx_http_v2_init; > > >> - } > > >> -#endif > > >> - > > >> #if (NGX_HTTP_V3) > > >> if (hc->addr_conf->quic) { > > >> ngx_http_v3_init_stream(c); > > >> @@ -383,6 +377,9 @@ ngx_http_wait_request_handler(ngx_event_ > > >> ngx_buf_t *b; > > >> ngx_connection_t *c; > > >> ngx_http_connection_t *hc; > > >> +#if (NGX_HTTP_V2) > > >> + ngx_http_v2_srv_conf_t *h2scf; > > >> +#endif > > >> ngx_http_core_srv_conf_t *cscf; > > >> > > >> c = rev->data; > > >> @@ -429,6 +426,8 @@ ngx_http_wait_request_handler(ngx_event_ > > >> b->end = b->last + size; > > >> } > > >> > > >> + size = b->end - b->last; > > >> + > > >> n = c->recv(c, b->last, size); > > >> > > >> if (n == NGX_AGAIN) { > > >> @@ -443,12 +442,16 @@ ngx_http_wait_request_handler(ngx_event_ > > >> return; > > >> } > > >> > > >> - /* > > >> - * We are trying to not hold c->buffer's memory for an idle connection. > > >> - */ > > >> - > > >> - if (ngx_pfree(c->pool, b->start) == NGX_OK) { > > >> - b->start = NULL; > > >> + if (b->pos == b->last) { > > >> + > > >> + /* > > >> + * We are trying to not hold c->buffer's memory for an > > >> + * idle connection. > > >> + */ > > >> + > > >> + if (ngx_pfree(c->pool, b->start) == NGX_OK) { > > >> + b->start = NULL; > > >> + } > > >> } > > >> > > >> return; > > >> @@ -489,10 +492,34 @@ ngx_http_wait_request_handler(ngx_event_ > > >> } > > >> } > > >> > > >> + ngx_reusable_connection(c, 0); > > >> + > > >> +#if (NGX_HTTP_V2) > > >> + > > >> + h2scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v2_module); > > >> + > > >> + if (!c->ssl && (h2scf->enable || hc->addr_conf->http2)) { > > > > > > And one more fix for compilation with HTTP/2, but without SSL: > > > > > > diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c > > > --- a/src/http/ngx_http_request.c > > > +++ b/src/http/ngx_http_request.c > > > @@ -498,8 +498,12 @@ ngx_http_wait_request_handler(ngx_event_ > > > > > > h2scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v2_module); > > > > > > - if (!c->ssl && (h2scf->enable || hc->addr_conf->http2)) { > > > - > > > + if ((h2scf->enable || hc->addr_conf->http2) > > > +#if (NGX_HTTP_SSL) > > > + && !c->ssl > > > +#endif > > > + ) > > > + { > > > size = ngx_min(sizeof(NGX_HTTP_V2_PREFACE) - 1, > > > (size_t) (b->last - b->pos)); > > > > > > > I think this test needs to be replaced with !hc->ssl. > > Otherwise, it would allow to establish (and keep) h2c on ssl-enabled > > sockets, which we likely do not want to allow. > > After a series of discussions we decided to go with !hc->ssl. As a result, > any non-SSL connection on an SSL port will trigger the HTTP/1 error page. > Previous attempt to trigger the HTTP/2 error in case client request is > recognized as HTTP/2, is discarded since the situation is unlikely. > > [..] > > -- > Roman Arutyunyan > # HG changeset patch > # User Roman Arutyunyan > # Date 1684240208 -14400 > # Tue May 16 16:30:08 2023 +0400 > # Branch quic > # Node ID 4dcd2b42c23973815a6b8a7f54bbd1460c314c93 > # Parent d8272b84031bea1940ef8a5b8e2f79ec6a2dcfc1 > HTTP/2: "http2" directive. > > The directive enables HTTP/2 in the current server. The previous way to > enable HTTP/2 via "listen ... http2" is now deprecated. The new approach > allows to share HTTP/2 and HTTP/0.9-1.1 on the same port. > > For SSL connections, HTTP/2 is now selected by ALPN callback based on whether > the protocol is enabled in the virtual server chosen by SNI. This however only > works since OpenSSL 1.0.2h, where ALPN callback is invoked after SNI callback. > For older versions of OpenSSL, HTTP/2 is enabled based on the default virtual > server configuration. > > For plain TCP connections, HTTP/2 is now auto-detected by HTTP/2 preface, if > HTTP/2 is enabled in the default virtual server. If preface is not matched, > HTTP/0.9-1.1 is assumed. > > diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c > --- a/src/http/modules/ngx_http_ssl_module.c > +++ b/src/http/modules/ngx_http_ssl_module.c > @@ -435,6 +435,9 @@ ngx_http_ssl_alpn_select(ngx_ssl_conn_t > #if (NGX_HTTP_V2 || NGX_HTTP_V3) > ngx_http_connection_t *hc; > #endif > +#if (NGX_HTTP_V2) > + ngx_http_v2_srv_conf_t *h2scf; > +#endif > #if (NGX_HTTP_V3) > ngx_http_v3_srv_conf_t *h3scf; > #endif > @@ -456,12 +459,6 @@ ngx_http_ssl_alpn_select(ngx_ssl_conn_t > hc = c->data; > #endif > > -#if (NGX_HTTP_V2) > - if (hc->addr_conf->http2) { > - srv = (unsigned char *) NGX_HTTP_V2_ALPN_PROTO NGX_HTTP_ALPN_PROTOS; > - srvlen = sizeof(NGX_HTTP_V2_ALPN_PROTO NGX_HTTP_ALPN_PROTOS) - 1; > - } else > -#endif > #if (NGX_HTTP_V3) > if (hc->addr_conf->quic) { > > @@ -488,8 +485,19 @@ ngx_http_ssl_alpn_select(ngx_ssl_conn_t > } else > #endif > { > - srv = (unsigned char *) NGX_HTTP_ALPN_PROTOS; > - srvlen = sizeof(NGX_HTTP_ALPN_PROTOS) - 1; > +#if (NGX_HTTP_V2) > + h2scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v2_module); > + > + if (h2scf->enable || hc->addr_conf->http2) { > + srv = (unsigned char *) NGX_HTTP_V2_ALPN_PROTO NGX_HTTP_ALPN_PROTOS; > + srvlen = sizeof(NGX_HTTP_V2_ALPN_PROTO NGX_HTTP_ALPN_PROTOS) - 1; > + > + } else > +#endif > + { > + srv = (unsigned char *) NGX_HTTP_ALPN_PROTOS; > + srvlen = sizeof(NGX_HTTP_ALPN_PROTOS) - 1; > + } > } > > if (SSL_select_next_proto((unsigned char **) out, outlen, srv, srvlen, > diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c > --- a/src/http/ngx_http_core_module.c > +++ b/src/http/ngx_http_core_module.c > @@ -4176,6 +4176,11 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx > > if (ngx_strcmp(value[n].data, "http2") == 0) { > #if (NGX_HTTP_V2) > + ngx_conf_log_error(NGX_LOG_WARN, cf, 0, > + "the \"listen ... http2\" directive " > + "is deprecated, use " > + "the \"http2\" directive instead"); > + > lsopt.http2 = 1; > continue; > #else > diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c > --- a/src/http/ngx_http_request.c > +++ b/src/http/ngx_http_request.c > @@ -318,12 +318,6 @@ ngx_http_init_connection(ngx_connection_ > rev->handler = ngx_http_wait_request_handler; > c->write->handler = ngx_http_empty_handler; > > -#if (NGX_HTTP_V2) > - if (hc->addr_conf->http2) { > - rev->handler = ngx_http_v2_init; > - } > -#endif > - > #if (NGX_HTTP_V3) > if (hc->addr_conf->quic) { > ngx_http_v3_init_stream(c); > @@ -383,6 +377,9 @@ ngx_http_wait_request_handler(ngx_event_ > ngx_buf_t *b; > ngx_connection_t *c; > ngx_http_connection_t *hc; > +#if (NGX_HTTP_V2) > + ngx_http_v2_srv_conf_t *h2scf; > +#endif > ngx_http_core_srv_conf_t *cscf; > > c = rev->data; > @@ -429,6 +426,8 @@ ngx_http_wait_request_handler(ngx_event_ > b->end = b->last + size; > } > > + size = b->end - b->last; > + > n = c->recv(c, b->last, size); > > if (n == NGX_AGAIN) { > @@ -443,12 +442,16 @@ ngx_http_wait_request_handler(ngx_event_ > return; > } > > - /* > - * We are trying to not hold c->buffer's memory for an idle connection. > - */ > - > - if (ngx_pfree(c->pool, b->start) == NGX_OK) { > - b->start = NULL; > + if (b->pos == b->last) { > + > + /* > + * We are trying to not hold c->buffer's memory for an > + * idle connection. > + */ > + > + if (ngx_pfree(c->pool, b->start) == NGX_OK) { > + b->start = NULL; > + } > } > > return; > @@ -489,10 +492,34 @@ ngx_http_wait_request_handler(ngx_event_ > } > } > > + ngx_reusable_connection(c, 0); I don't think it should be moved. Non-reusable connections are basically ones with a request created, so nginx won't try to terminate running requests. This does not apply to a connection waiting for an HTTP/2 preface. It might need to be called in (or just before) ngx_http_v2_init() though, since HTTP/2 code assumes that the connection is not reusable by default. > + > +#if (NGX_HTTP_V2) > + > + h2scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v2_module); > + > + if (!hc->ssl && (h2scf->enable || hc->addr_conf->http2)) { For the record: we might consider introducing a way to explicitly control "establishment of HTTP/2 connections over cleartext TCP" (quote from RFC 9113, section 3.3. "Starting HTTP/2 with Prior Knowledge"), something like "http2_cleartext on|off;". Might not worth the effort though. > + > + size = ngx_min(sizeof(NGX_HTTP_V2_PREFACE) - 1, > + (size_t) (b->last - b->pos)); > + > + if (ngx_memcmp(b->pos, NGX_HTTP_V2_PREFACE, size) == 0) { > + > + if (size == sizeof(NGX_HTTP_V2_PREFACE) - 1) { > + ngx_http_v2_init(rev); > + return; > + } > + > + c->log->action = "waiting for request"; Any reasons to change the log action here? Note that for proxy_protocol handling above, c->log->action is set to "reading PROXY protocol", and therefore needs to be reset to "waiting for request" when PROXY protocol header is fully processed. This is not the case for HTTP/2 preface though, as it does not use a special log action. Further, in this particular point HTTP/2 preface reading is not complete, so changing the log action would be wrong if there was a special log action set. > + ngx_post_event(rev, &ngx_posted_events); > + return; For the record: as far as I understand, there is no real need to post an event here, and just adding a timer and calling ngx_handle_read_event() (much like in case of EAGAIN after recv()) would be slightly more optimal. I don't object keeping it this way though, since it's not a hot path, have some chance to actually read the rest of the preface in the posted event, and proxy_protocol handling already uses the same approach. > + } > + } > + > +#endif > + > c->log->action = "reading client request line"; > > - ngx_reusable_connection(c, 0); > - > c->data = ngx_http_create_request(c); > if (c->data == NULL) { > ngx_http_close_connection(c); > @@ -808,13 +835,16 @@ ngx_http_ssl_handshake_handler(ngx_conne > #if (NGX_HTTP_V2 \ > && defined TLSEXT_TYPE_application_layer_protocol_negotiation) > { > - unsigned int len; > - const unsigned char *data; > - ngx_http_connection_t *hc; > + unsigned int len; > + const unsigned char *data; > + ngx_http_connection_t *hc; > + ngx_http_v2_srv_conf_t *h2scf; > > hc = c->data; > > - if (hc->addr_conf->http2) { > + h2scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v2_module); > + > + if (h2scf->enable || hc->addr_conf->http2) { > > SSL_get0_alpn_selected(c->ssl->connection, &data, &len); > > diff --git a/src/http/v2/ngx_http_v2.c b/src/http/v2/ngx_http_v2.c > --- a/src/http/v2/ngx_http_v2.c > +++ b/src/http/v2/ngx_http_v2.c > @@ -63,8 +63,6 @@ static void ngx_http_v2_handle_connectio > static void ngx_http_v2_lingering_close(ngx_connection_t *c); > static void ngx_http_v2_lingering_close_handler(ngx_event_t *rev); > > -static u_char *ngx_http_v2_state_proxy_protocol(ngx_http_v2_connection_t *h2c, > - u_char *pos, u_char *end); > static u_char *ngx_http_v2_state_preface(ngx_http_v2_connection_t *h2c, > u_char *pos, u_char *end); > static u_char *ngx_http_v2_state_preface_end(ngx_http_v2_connection_t *h2c, > @@ -232,6 +230,7 @@ static ngx_http_v2_parse_header_t ngx_h > void > ngx_http_v2_init(ngx_event_t *rev) > { > + u_char *p, *end; > ngx_connection_t *c; > ngx_pool_cleanup_t *cln; > ngx_http_connection_t *hc; > @@ -314,8 +313,7 @@ ngx_http_v2_init(ngx_event_t *rev) > return; > } > > - h2c->state.handler = hc->proxy_protocol ? ngx_http_v2_state_proxy_protocol > - : ngx_http_v2_state_preface; > + h2c->state.handler = ngx_http_v2_state_preface; > > ngx_queue_init(&h2c->waiting); > ngx_queue_init(&h2c->dependencies); > @@ -333,7 +331,23 @@ ngx_http_v2_init(ngx_event_t *rev) > } > > c->idle = 1; > - ngx_reusable_connection(c, 0); See above. > + > + if (c->buffer) { > + p = c->buffer->pos; > + end = c->buffer->last; > + > + do { > + p = h2c->state.handler(h2c, p, end); > + > + if (p == NULL) { > + return; > + } > + > + } while (p != end); > + > + h2c->total_bytes += p - c->buffer->pos; > + c->buffer->pos = p; > + } > > ngx_http_v2_read_handler(rev); > } For the record: it might be better to integrate this into ngx_http_v2_read_handler(), similarly to how it is done in ngx_event_pipe_read_upstream(). On the other hand, suggested approach looks simple enough and might be better. Note well: this implies an extra recv() call on each cleartext HTTP/2 connection establishment. Probably not very important though. On the other hand, we can consider optimizing out an extra call if there are space in c->buffer. > @@ -847,31 +861,10 @@ ngx_http_v2_lingering_close_handler(ngx_ > > > static u_char * > -ngx_http_v2_state_proxy_protocol(ngx_http_v2_connection_t *h2c, u_char *pos, > - u_char *end) > -{ > - ngx_log_t *log; > - > - log = h2c->connection->log; > - log->action = "reading PROXY protocol"; > - > - pos = ngx_proxy_protocol_read(h2c->connection, pos, end); > - > - log->action = "processing HTTP/2 connection"; > - > - if (pos == NULL) { > - return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR); > - } > - > - return ngx_http_v2_state_preface(h2c, pos, end); > -} > - > - > -static u_char * > ngx_http_v2_state_preface(ngx_http_v2_connection_t *h2c, u_char *pos, > u_char *end) > { > - static const u_char preface[] = "PRI * HTTP/2.0\r\n"; > + static const u_char preface[] = NGX_HTTP_V2_PREFACE_START; > > if ((size_t) (end - pos) < sizeof(preface) - 1) { > return ngx_http_v2_state_save(h2c, pos, end, ngx_http_v2_state_preface); > @@ -892,7 +885,7 @@ static u_char * > ngx_http_v2_state_preface_end(ngx_http_v2_connection_t *h2c, u_char *pos, > u_char *end) > { > - static const u_char preface[] = "\r\nSM\r\n\r\n"; > + static const u_char preface[] = NGX_HTTP_V2_PREFACE_END; > > if ((size_t) (end - pos) < sizeof(preface) - 1) { > return ngx_http_v2_state_save(h2c, pos, end, > @@ -3943,10 +3936,22 @@ static void > ngx_http_v2_run_request(ngx_http_request_t *r) > { > ngx_connection_t *fc; > + ngx_http_v2_srv_conf_t *h2scf; > ngx_http_v2_connection_t *h2c; > > fc = r->connection; > > + h2scf = ngx_http_get_module_srv_conf(r, ngx_http_v2_module); > + > + if (!h2scf->enable && !r->http_connection->addr_conf->http2) { > + ngx_log_error(NGX_LOG_INFO, fc->log, 0, > + "client attempted to request the server name " > + "for which the negotiated protocol is disabled"); > + > + ngx_http_finalize_request(r, NGX_HTTP_MISDIRECTED_REQUEST); > + goto failed; > + } > + > if (ngx_http_v2_construct_request_line(r) != NGX_OK) { > goto failed; > } > diff --git a/src/http/v2/ngx_http_v2.h b/src/http/v2/ngx_http_v2.h > --- a/src/http/v2/ngx_http_v2.h > +++ b/src/http/v2/ngx_http_v2.h > @@ -64,6 +64,16 @@ typedef u_char *(*ngx_http_v2_handler_pt > > > typedef struct { > + ngx_flag_t enable; > + size_t pool_size; > + ngx_uint_t concurrent_streams; > + ngx_uint_t concurrent_pushes; > + size_t preread_size; > + ngx_uint_t streams_index_mask; > +} ngx_http_v2_srv_conf_t; > + > + > +typedef struct { > ngx_str_t name; > ngx_str_t value; > } ngx_http_v2_header_t; > @@ -408,9 +418,17 @@ ngx_int_t ngx_http_v2_table_size(ngx_htt > #define NGX_HTTP_V2_USER_AGENT_INDEX 58 > #define NGX_HTTP_V2_VARY_INDEX 59 > > +#define NGX_HTTP_V2_PREFACE_START "PRI * HTTP/2.0\r\n" > +#define NGX_HTTP_V2_PREFACE_END "\r\nSM\r\n\r\n" > +#define NGX_HTTP_V2_PREFACE NGX_HTTP_V2_PREFACE_START \ > + NGX_HTTP_V2_PREFACE_END > + > > u_char *ngx_http_v2_string_encode(u_char *dst, u_char *src, size_t len, > u_char *tmp, ngx_uint_t lower); > > > +extern ngx_module_t ngx_http_v2_module; > + > + > #endif /* _NGX_HTTP_V2_H_INCLUDED_ */ > diff --git a/src/http/v2/ngx_http_v2_module.c b/src/http/v2/ngx_http_v2_module.c > --- a/src/http/v2/ngx_http_v2_module.c > +++ b/src/http/v2/ngx_http_v2_module.c > @@ -75,6 +75,13 @@ static ngx_conf_post_t ngx_http_v2_chun > > static ngx_command_t ngx_http_v2_commands[] = { > > + { ngx_string("http2"), > + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG, > + ngx_conf_set_flag_slot, > + NGX_HTTP_SRV_CONF_OFFSET, > + offsetof(ngx_http_v2_srv_conf_t, enable), > + NULL }, > + > { ngx_string("http2_recv_buffer_size"), > NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, > ngx_conf_set_size_slot, > @@ -314,6 +321,8 @@ ngx_http_v2_create_srv_conf(ngx_conf_t * > return NULL; > } > > + h2scf->enable = NGX_CONF_UNSET; > + > h2scf->pool_size = NGX_CONF_UNSET_SIZE; > > h2scf->concurrent_streams = NGX_CONF_UNSET_UINT; > @@ -333,6 +342,8 @@ ngx_http_v2_merge_srv_conf(ngx_conf_t *c > ngx_http_v2_srv_conf_t *prev = parent; > ngx_http_v2_srv_conf_t *conf = child; > > + ngx_conf_merge_value(conf->enable, prev->enable, 0); > + > ngx_conf_merge_size_value(conf->pool_size, prev->pool_size, 4096); > > ngx_conf_merge_uint_value(conf->concurrent_streams, > diff --git a/src/http/v2/ngx_http_v2_module.h b/src/http/v2/ngx_http_v2_module.h > --- a/src/http/v2/ngx_http_v2_module.h > +++ b/src/http/v2/ngx_http_v2_module.h > @@ -21,15 +21,6 @@ typedef struct { > > > typedef struct { > - size_t pool_size; > - ngx_uint_t concurrent_streams; > - ngx_uint_t concurrent_pushes; > - size_t preread_size; > - ngx_uint_t streams_index_mask; > -} ngx_http_v2_srv_conf_t; > - > - > -typedef struct { > size_t chunk_size; > > ngx_flag_t push_preload; > @@ -39,7 +30,4 @@ typedef struct { > } ngx_http_v2_loc_conf_t; > > > -extern ngx_module_t ngx_http_v2_module; > - > - > #endif /* _NGX_HTTP_V2_MODULE_H_INCLUDED_ */ Overall looks good. -- Maxim Dounin http://mdounin.ru/ From mdounin at mdounin.ru Sun Jun 4 02:20:29 2023 From: mdounin at mdounin.ru (Maxim Dounin) Date: Sun, 4 Jun 2023 05:20:29 +0300 Subject: [PATCH] HTTP/2: removed server push In-Reply-To: References: Message-ID: Hello! On Thu, Jun 01, 2023 at 05:58:38AM +0400, Sergey Kandaurov wrote: > # HG changeset patch > # User Sergey Kandaurov > # Date 1685584419 -14400 > # Thu Jun 01 05:53:39 2023 +0400 > # Node ID cd90a7bed6ebb098efe1e82b7ffa067e5f0e56c1 > # Parent 79ed88b1bf961a19b1efccd058fae440c3acbbdc > HTTP/2: removed server push. > > Although it has better implementation status than HTTP/3 server push, > it remains of limited use, with adoption numbers seen as negligible. > Per IETF 102 materials, server push was used only in 0.04% of sessions. > It was considered to be "difficult to use effectively" in RFC 9113. > Its use is further limited by badly matching to fetch/cache/connection > models in browsers, see related discussions linked from [1]. > > Server push was disabled in Chrome 106 [2]. > > The http2_push, http2_push_preload, and http2_max_concurrent_pushes > directives are made obsolete. > > [1] https://jakearchibald.com/2017/h2-push-tougher-than-i-thought/ > [2] https://chromestatus.com/feature/6302414934114304 It might make sense to mention ticket #2432. It might also make sense to mention changesets essentially reverted, notably 7201:641306096f5b and 7207:3d2b0b02bd3d. > > diff --git a/src/http/v2/ngx_http_v2.c b/src/http/v2/ngx_http_v2.c > --- a/src/http/v2/ngx_http_v2.c > +++ b/src/http/v2/ngx_http_v2.c > @@ -11,14 +11,6 @@ > #include > > > -typedef struct { > - ngx_str_t name; > - ngx_uint_t offset; > - ngx_uint_t hash; > - ngx_http_header_t *hh; > -} ngx_http_v2_parse_header_t; > - > - > /* errors */ Looking into 7207:3d2b0b02bd3d, where this chunk of code was originally introduced, suggests that NGX_HTTP_HEADERS can be removed from the relevant if in auto/modules. And the same applies to HTTP/3 case as well. > #define NGX_HTTP_V2_NO_ERROR 0x0 > #define NGX_HTTP_V2_PROTOCOL_ERROR 0x1 > @@ -126,7 +118,7 @@ static ngx_int_t ngx_http_v2_parse_int(n > u_char **pos, u_char *end, ngx_uint_t prefix); > > static ngx_http_v2_stream_t *ngx_http_v2_create_stream( > - ngx_http_v2_connection_t *h2c, ngx_uint_t push); > + ngx_http_v2_connection_t *h2c); > static ngx_http_v2_node_t *ngx_http_v2_get_node_by_id( > ngx_http_v2_connection_t *h2c, ngx_uint_t sid, ngx_uint_t alloc); > static ngx_http_v2_node_t *ngx_http_v2_get_closed_node( > @@ -162,14 +154,11 @@ static ngx_int_t ngx_http_v2_parse_schem > ngx_str_t *value); > static ngx_int_t ngx_http_v2_parse_authority(ngx_http_request_t *r, > ngx_str_t *value); > -static ngx_int_t ngx_http_v2_parse_header(ngx_http_request_t *r, > - ngx_http_v2_parse_header_t *header, ngx_str_t *value); > static ngx_int_t ngx_http_v2_construct_request_line(ngx_http_request_t *r); > static ngx_int_t ngx_http_v2_cookie(ngx_http_request_t *r, > ngx_http_v2_header_t *header); > static ngx_int_t ngx_http_v2_construct_cookie_header(ngx_http_request_t *r); > static void ngx_http_v2_run_request(ngx_http_request_t *r); > -static void ngx_http_v2_run_request_handler(ngx_event_t *ev); > static ngx_int_t ngx_http_v2_process_request_body(ngx_http_request_t *r, > u_char *pos, size_t size, ngx_uint_t last, ngx_uint_t flush); > static ngx_int_t ngx_http_v2_filter_request_body(ngx_http_request_t *r); > @@ -210,23 +199,6 @@ static ngx_http_v2_handler_pt ngx_http_v > (sizeof(ngx_http_v2_frame_states) / sizeof(ngx_http_v2_handler_pt)) > > > -static ngx_http_v2_parse_header_t ngx_http_v2_parse_headers[] = { > - { ngx_string("host"), > - offsetof(ngx_http_headers_in_t, host), 0, NULL }, > - > - { ngx_string("accept-encoding"), > - offsetof(ngx_http_headers_in_t, accept_encoding), 0, NULL }, > - > - { ngx_string("accept-language"), > - offsetof(ngx_http_headers_in_t, accept_language), 0, NULL }, > - > - { ngx_string("user-agent"), > - offsetof(ngx_http_headers_in_t, user_agent), 0, NULL }, > - > - { ngx_null_string, 0, 0, NULL } > -}; > - > - > void > ngx_http_v2_init(ngx_event_t *rev) > { > @@ -275,7 +247,6 @@ ngx_http_v2_init(ngx_event_t *rev) > > h2scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v2_module); > > - h2c->concurrent_pushes = h2scf->concurrent_pushes; > h2c->priority_limit = ngx_max(h2scf->concurrent_streams, 100); > > h2c->pool = ngx_create_pool(h2scf->pool_size, h2c->connection->log); > @@ -384,7 +355,7 @@ ngx_http_v2_read_handler(ngx_event_t *re > return; > } > > - if (!h2c->processing && !h2c->pushing) { > + if (!h2c->processing) { > ngx_http_v2_finalize_connection(h2c, NGX_HTTP_V2_NO_ERROR); > return; > } > @@ -427,8 +398,7 @@ ngx_http_v2_read_handler(ngx_event_t *re > break; > } > > - if (n == 0 > - && (h2c->state.incomplete || h2c->processing || h2c->pushing)) > + if (n == 0 && (h2c->state.incomplete || h2c->processing)) > { > ngx_log_error(NGX_LOG_INFO, c->log, 0, > "client prematurely closed connection"); Nitpicking: "{" should be on the same line with "if" (and that's how it was before 7201:641306096f5b). > @@ -652,7 +622,7 @@ ngx_http_v2_handle_connection(ngx_http_v > ngx_connection_t *c; > ngx_http_core_loc_conf_t *clcf; > > - if (h2c->last_out || h2c->processing || h2c->pushing) { > + if (h2c->last_out || h2c->processing) { > return; > } > > @@ -1337,7 +1307,7 @@ ngx_http_v2_state_headers(ngx_http_v2_co > h2c->closed_nodes--; > } > > - stream = ngx_http_v2_create_stream(h2c, 0); > + stream = ngx_http_v2_create_stream(h2c); > if (stream == NULL) { > return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR); > } In 7201:641306096f5b, NGX_HTTP_V2_REFUSED_STREAM handling was added to ngx_http_v2_state_rst_stream(): @@ -1909,6 +1913,11 @@ ngx_http_v2_state_rst_stream(ngx_http_v2 "client canceled stream %ui", h2c->state.sid); break; + case NGX_HTTP_V2_REFUSED_STREAM: + ngx_log_error(NGX_LOG_INFO, fc->log, 0, + "client refused stream %ui", h2c->state.sid); + break; + case NGX_HTTP_V2_INTERNAL_ERROR: ngx_log_error(NGX_LOG_INFO, fc->log, 0, "client terminated stream %ui due to internal error", It does not seem to make any sense now, shouldn't it be removed as well? > @@ -2198,7 +2168,6 @@ ngx_http_v2_state_settings_params(ngx_ht > { > ssize_t window_delta; > ngx_uint_t id, value; > - ngx_http_v2_srv_conf_t *h2scf; > ngx_http_v2_out_frame_t *frame; > > window_delta = 0; > @@ -2260,14 +2229,6 @@ ngx_http_v2_state_settings_params(ngx_ht > NGX_HTTP_V2_PROTOCOL_ERROR); > } > > - h2c->push_disabled = !value; > - break; > - > - case NGX_HTTP_V2_MAX_STREAMS_SETTING: > - h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx, > - ngx_http_v2_module); > - > - h2c->concurrent_pushes = ngx_min(value, h2scf->concurrent_pushes); > break; > > case NGX_HTTP_V2_HEADER_TABLE_SIZE_SETTING: Any specific reasons to keep NGX_HTTP_V2_ENABLE_PUSH_SETTING handling? > @@ -2722,163 +2683,6 @@ ngx_http_v2_parse_int(ngx_http_v2_connec > } > > > -ngx_http_v2_stream_t * > -ngx_http_v2_push_stream(ngx_http_v2_stream_t *parent, ngx_str_t *path) > -{ > - ngx_int_t rc; > - ngx_str_t value; > - ngx_pool_t *pool; > - ngx_uint_t index; > - ngx_table_elt_t **h; > - ngx_connection_t *fc; > - ngx_http_request_t *r; > - ngx_http_v2_node_t *node; > - ngx_http_v2_stream_t *stream; > - ngx_http_v2_srv_conf_t *h2scf; > - ngx_http_v2_connection_t *h2c; > - ngx_http_v2_parse_header_t *header; > - > - h2c = parent->connection; > - > - pool = ngx_create_pool(1024, h2c->connection->log); > - if (pool == NULL) { > - goto rst_stream; > - } > - > - node = ngx_http_v2_get_node_by_id(h2c, h2c->last_push, 1); > - > - if (node == NULL) { > - ngx_destroy_pool(pool); > - goto rst_stream; > - } > - > - stream = ngx_http_v2_create_stream(h2c, 1); > - if (stream == NULL) { > - > - if (node->parent == NULL) { > - h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx, > - ngx_http_v2_module); > - > - index = ngx_http_v2_index(h2scf, h2c->last_push); > - h2c->streams_index[index] = node->index; > - > - ngx_queue_insert_tail(&h2c->closed, &node->reuse); > - h2c->closed_nodes++; > - } > - > - ngx_destroy_pool(pool); > - goto rst_stream; > - } > - > - if (node->parent) { > - ngx_queue_remove(&node->reuse); > - h2c->closed_nodes--; > - } > - > - stream->pool = pool; > - > - r = stream->request; > - fc = r->connection; > - > - stream->in_closed = 1; > - stream->node = node; > - > - node->stream = stream; > - > - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, > - "http2 push stream sid:%ui " > - "depends on %ui excl:0 weight:16", > - h2c->last_push, parent->node->id); > - > - node->weight = NGX_HTTP_V2_DEFAULT_WEIGHT; > - ngx_http_v2_set_dependency(h2c, node, parent->node->id, 0); > - > - r->method_name = ngx_http_core_get_method; > - r->method = NGX_HTTP_GET; > - > - r->schema.data = ngx_pstrdup(pool, &parent->request->schema); > - if (r->schema.data == NULL) { > - goto close; > - } > - > - r->schema.len = parent->request->schema.len; > - > - value.data = ngx_pstrdup(pool, path); > - if (value.data == NULL) { > - goto close; > - } > - > - value.len = path->len; > - > - rc = ngx_http_v2_parse_path(r, &value); > - > - if (rc != NGX_OK) { > - goto error; > - } > - > - for (header = ngx_http_v2_parse_headers; header->name.len; header++) { > - h = (ngx_table_elt_t **) > - ((char *) &parent->request->headers_in + header->offset); > - > - if (*h == NULL) { > - continue; > - } > - > - value.len = (*h)->value.len; > - > - value.data = ngx_pnalloc(pool, value.len + 1); > - if (value.data == NULL) { > - goto close; > - } > - > - ngx_memcpy(value.data, (*h)->value.data, value.len); > - value.data[value.len] = '\0'; > - > - rc = ngx_http_v2_parse_header(r, header, &value); > - > - if (rc != NGX_OK) { > - goto error; > - } > - } > - > - fc->write->handler = ngx_http_v2_run_request_handler; > - ngx_post_event(fc->write, &ngx_posted_events); > - > - return stream; > - > -error: > - > - if (rc == NGX_ABORT) { > - /* header handler has already finalized request */ > - ngx_http_run_posted_requests(fc); > - return NULL; > - } > - > - if (rc == NGX_DECLINED) { > - ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); > - ngx_http_run_posted_requests(fc); > - return NULL; > - } > - > -close: > - > - ngx_http_v2_close_stream(stream, NGX_HTTP_INTERNAL_SERVER_ERROR); > - > - return NULL; > - > -rst_stream: > - > - if (ngx_http_v2_send_rst_stream(h2c, h2c->last_push, > - NGX_HTTP_INTERNAL_SERVER_ERROR) > - != NGX_OK) > - { > - h2c->connection->error = 1; > - } > - > - return NULL; > -} > - > - > static ngx_int_t > ngx_http_v2_send_settings(ngx_http_v2_connection_t *h2c) > { > @@ -3150,7 +2954,7 @@ ngx_http_v2_frame_handler(ngx_http_v2_co > > > static ngx_http_v2_stream_t * > -ngx_http_v2_create_stream(ngx_http_v2_connection_t *h2c, ngx_uint_t push) > +ngx_http_v2_create_stream(ngx_http_v2_connection_t *h2c) > { > ngx_log_t *log; > ngx_event_t *rev, *wev; > @@ -3205,13 +3009,7 @@ ngx_http_v2_create_stream(ngx_http_v2_co > ngx_memcpy(log, h2c->connection->log, sizeof(ngx_log_t)); > > log->data = ctx; > - > - if (push) { > - log->action = "processing pushed request headers"; > - > - } else { > - log->action = "reading client request headers"; > - } > + log->action = "reading client request headers"; > > ngx_memzero(rev, sizeof(ngx_event_t)); > > @@ -3283,12 +3081,7 @@ ngx_http_v2_create_stream(ngx_http_v2_co > stream->send_window = h2c->init_window; > stream->recv_window = h2scf->preread_size; > > - if (push) { > - h2c->pushing++; > - > - } else { > - h2c->processing++; > - } > + h2c->processing++; > > h2c->priority_limit += h2scf->concurrent_streams; > > @@ -3711,45 +3504,40 @@ ngx_http_v2_parse_scheme(ngx_http_reques > static ngx_int_t > ngx_http_v2_parse_authority(ngx_http_request_t *r, ngx_str_t *value) > { > - return ngx_http_v2_parse_header(r, &ngx_http_v2_parse_headers[0], value); > -} > - > - > -static ngx_int_t > -ngx_http_v2_parse_header(ngx_http_request_t *r, > - ngx_http_v2_parse_header_t *header, ngx_str_t *value) > -{ > ngx_table_elt_t *h; > + ngx_http_header_t *hh; > ngx_http_core_main_conf_t *cmcf; > > + static ngx_str_t host = ngx_string("host"); > + > h = ngx_list_push(&r->headers_in.headers); > if (h == NULL) { > return NGX_ERROR; > } > > - h->key.len = header->name.len; > - h->key.data = header->name.data; > - h->lowcase_key = header->name.data; > - > - if (header->hh == NULL) { > - header->hash = ngx_hash_key(header->name.data, header->name.len); > - > - cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); > - > - header->hh = ngx_hash_find(&cmcf->headers_in_hash, header->hash, > - h->lowcase_key, h->key.len); > - if (header->hh == NULL) { > - return NGX_ERROR; > - } > - } > - > - h->hash = header->hash; > + h->key.len = host.len; > + h->key.data = host.data; > + h->lowcase_key = host.data; > + > + h->hash = ngx_hash(ngx_hash(ngx_hash('h', 'o'), 's'), 't'); > For the record: order of h->key/h->lowcase_key/h->hash assignments differs from the one used before 7207:3d2b0b02bd3d, but this is not important, and I agree that the new order is better. > h->value.len = value->len; > h->value.data = value->data; > > - if (header->hh->handler(r, h, header->hh->offset) != NGX_OK) { > - /* header handler has already finalized request */ > + cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); > + > + hh = ngx_hash_find(&cmcf->headers_in_hash, h->hash, > + h->lowcase_key, h->key.len); > + > + if (hh == NULL) { > + return NGX_ERROR; > + } > + > + if (hh->handler(r, h, hh->offset) != NGX_OK) { > + /* > + * request has been finalized already > + * in ngx_http_process_host() > + */ > return NGX_ABORT; > } > > @@ -3992,22 +3780,6 @@ failed: > } > > > -static void > -ngx_http_v2_run_request_handler(ngx_event_t *ev) > -{ > - ngx_connection_t *fc; > - ngx_http_request_t *r; > - > - fc = ev->data; > - r = fc->data; > - > - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0, > - "http2 run request handler"); > - > - ngx_http_v2_run_request(r); > -} > - > - > ngx_int_t > ngx_http_v2_read_request_body(ngx_http_request_t *r) > { > @@ -4611,7 +4383,6 @@ void > ngx_http_v2_close_stream(ngx_http_v2_stream_t *stream, ngx_int_t rc) > { > ngx_pool_t *pool; > - ngx_uint_t push; > ngx_event_t *ev; > ngx_connection_t *fc; > ngx_http_v2_node_t *node; > @@ -4620,10 +4391,9 @@ ngx_http_v2_close_stream(ngx_http_v2_str > h2c = stream->connection; > node = stream->node; > > - ngx_log_debug4(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, > - "http2 close stream %ui, queued %ui, " > - "processing %ui, pushing %ui", > - node->id, stream->queued, h2c->processing, h2c->pushing); > + ngx_log_debug3(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, > + "http2 close stream %ui, queued %ui, processing %ui", > + node->id, stream->queued, h2c->processing); > > fc = stream->request->connection; > > @@ -4658,8 +4428,6 @@ ngx_http_v2_close_stream(ngx_http_v2_str > h2c->state.stream = NULL; > } > > - push = stream->node->id % 2 == 0; > - > node->stream = NULL; > > ngx_queue_insert_tail(&h2c->closed, &node->reuse); > @@ -4709,14 +4477,9 @@ ngx_http_v2_close_stream(ngx_http_v2_str > fc->data = h2c->free_fake_connections; > h2c->free_fake_connections = fc; > > - if (push) { > - h2c->pushing--; > - > - } else { > - h2c->processing--; > - } > - > - if (h2c->processing || h2c->pushing || h2c->blocked) { > + h2c->processing--; > + > + if (h2c->processing || h2c->blocked) { > return; > } > > @@ -4892,7 +4655,7 @@ ngx_http_v2_finalize_connection(ngx_http > } > } > > - if (!h2c->processing && !h2c->pushing) { > + if (!h2c->processing) { > goto done; > } > > @@ -4940,7 +4703,7 @@ ngx_http_v2_finalize_connection(ngx_http > > h2c->blocked = 0; > > - if (h2c->processing || h2c->pushing) { > + if (h2c->processing) { > c->error = 1; > return; > } > diff --git a/src/http/v2/ngx_http_v2.h b/src/http/v2/ngx_http_v2.h > --- a/src/http/v2/ngx_http_v2.h > +++ b/src/http/v2/ngx_http_v2.h > @@ -24,8 +24,6 @@ > #define NGX_HTTP_V2_MAX_FIELD \ > (127 + (1 << (NGX_HTTP_V2_INT_OCTETS - 1) * 7) - 1) > > -#define NGX_HTTP_V2_STREAM_ID_SIZE 4 > - > #define NGX_HTTP_V2_FRAME_HEADER_SIZE 9 > > /* frame types */ > @@ -67,7 +65,6 @@ typedef struct { > ngx_flag_t enable; > size_t pool_size; > ngx_uint_t concurrent_streams; > - ngx_uint_t concurrent_pushes; > size_t preread_size; > ngx_uint_t streams_index_mask; > } ngx_http_v2_srv_conf_t; > @@ -136,9 +133,6 @@ struct ngx_http_v2_connection_s { > ngx_uint_t idle; > ngx_uint_t priority_limit; > > - ngx_uint_t pushing; > - ngx_uint_t concurrent_pushes; > - > size_t send_window; > size_t recv_window; > size_t init_window; > @@ -165,7 +159,6 @@ struct ngx_http_v2_connection_s { > > ngx_uint_t closed_nodes; > ngx_uint_t last_sid; > - ngx_uint_t last_push; > > time_t lingering_time; > > @@ -173,7 +166,6 @@ struct ngx_http_v2_connection_s { > unsigned table_update:1; > unsigned blocked:1; > unsigned goaway:1; > - unsigned push_disabled:1; > }; > > > @@ -303,9 +295,6 @@ void ngx_http_v2_init(ngx_event_t *rev); > ngx_int_t ngx_http_v2_read_request_body(ngx_http_request_t *r); > ngx_int_t ngx_http_v2_read_unbuffered_request_body(ngx_http_request_t *r); > > -ngx_http_v2_stream_t *ngx_http_v2_push_stream(ngx_http_v2_stream_t *parent, > - ngx_str_t *path); > - > void ngx_http_v2_close_stream(ngx_http_v2_stream_t *stream, ngx_int_t rc); > > ngx_int_t ngx_http_v2_send_output_queue(ngx_http_v2_connection_t *h2c); > @@ -407,15 +396,12 @@ ngx_int_t ngx_http_v2_table_size(ngx_htt > #define NGX_HTTP_V2_STATUS_404_INDEX 13 > #define NGX_HTTP_V2_STATUS_500_INDEX 14 > > -#define NGX_HTTP_V2_ACCEPT_ENCODING_INDEX 16 > -#define NGX_HTTP_V2_ACCEPT_LANGUAGE_INDEX 17 > #define NGX_HTTP_V2_CONTENT_LENGTH_INDEX 28 > #define NGX_HTTP_V2_CONTENT_TYPE_INDEX 31 > #define NGX_HTTP_V2_DATE_INDEX 33 > #define NGX_HTTP_V2_LAST_MODIFIED_INDEX 44 > #define NGX_HTTP_V2_LOCATION_INDEX 46 > #define NGX_HTTP_V2_SERVER_INDEX 54 > -#define NGX_HTTP_V2_USER_AGENT_INDEX 58 > #define NGX_HTTP_V2_VARY_INDEX 59 > > #define NGX_HTTP_V2_PREFACE_START "PRI * HTTP/2.0\r\n" > diff --git a/src/http/v2/ngx_http_v2_filter_module.c b/src/http/v2/ngx_http_v2_filter_module.c > --- a/src/http/v2/ngx_http_v2_filter_module.c > +++ b/src/http/v2/ngx_http_v2_filter_module.c > @@ -27,39 +27,8 @@ > #define NGX_HTTP_V2_NO_TRAILERS (ngx_http_v2_out_frame_t *) -1 > > > -typedef struct { > - ngx_str_t name; > - u_char index; > - ngx_uint_t offset; > -} ngx_http_v2_push_header_t; > - > - > -static ngx_http_v2_push_header_t ngx_http_v2_push_headers[] = { > - { ngx_string(":authority"), NGX_HTTP_V2_AUTHORITY_INDEX, > - offsetof(ngx_http_headers_in_t, host) }, > - > - { ngx_string("accept-encoding"), NGX_HTTP_V2_ACCEPT_ENCODING_INDEX, > - offsetof(ngx_http_headers_in_t, accept_encoding) }, > - > - { ngx_string("accept-language"), NGX_HTTP_V2_ACCEPT_LANGUAGE_INDEX, > - offsetof(ngx_http_headers_in_t, accept_language) }, > - > - { ngx_string("user-agent"), NGX_HTTP_V2_USER_AGENT_INDEX, > - offsetof(ngx_http_headers_in_t, user_agent) }, > -}; > - > -#define NGX_HTTP_V2_PUSH_HEADERS \ > - (sizeof(ngx_http_v2_push_headers) / sizeof(ngx_http_v2_push_header_t)) > - > - > -static ngx_int_t ngx_http_v2_push_resources(ngx_http_request_t *r); > -static ngx_int_t ngx_http_v2_push_resource(ngx_http_request_t *r, > - ngx_str_t *path, ngx_str_t *binary); > - > static ngx_http_v2_out_frame_t *ngx_http_v2_create_headers_frame( > ngx_http_request_t *r, u_char *pos, u_char *end, ngx_uint_t fin); > -static ngx_http_v2_out_frame_t *ngx_http_v2_create_push_frame( > - ngx_http_request_t *r, u_char *pos, u_char *end); > static ngx_http_v2_out_frame_t *ngx_http_v2_create_trailers_frame( > ngx_http_request_t *r); > > @@ -82,8 +51,6 @@ static ngx_inline ngx_int_t ngx_http_v2_ > > static ngx_int_t ngx_http_v2_headers_frame_handler( > ngx_http_v2_connection_t *h2c, ngx_http_v2_out_frame_t *frame); > -static ngx_int_t ngx_http_v2_push_frame_handler( > - ngx_http_v2_connection_t *h2c, ngx_http_v2_out_frame_t *frame); > static ngx_int_t ngx_http_v2_data_frame_handler( > ngx_http_v2_connection_t *h2c, ngx_http_v2_out_frame_t *frame); > static ngx_inline void ngx_http_v2_handle_frame( > @@ -244,15 +211,6 @@ ngx_http_v2_header_filter(ngx_http_reque > > h2c = stream->connection; > > - if (!h2c->push_disabled && !h2c->goaway > - && stream->node->id % 2 == 1 > - && r->method != NGX_HTTP_HEAD) > - { > - if (ngx_http_v2_push_resources(r) != NGX_OK) { > - return NGX_ERROR; > - } > - } > - > len = h2c->table_update ? 1 : 0; > > len += status ? 1 : 1 + ngx_http_v2_literal_size("418"); > @@ -653,7 +611,7 @@ ngx_http_v2_header_filter(ngx_http_reque > > ngx_http_v2_queue_blocked_frame(h2c, frame); > > - stream->queued++; > + stream->queued = 1; > > cln = ngx_http_cleanup_add(r, 0); > if (cln == NULL) { > @@ -671,409 +629,6 @@ ngx_http_v2_header_filter(ngx_http_reque > } > > > -static ngx_int_t > -ngx_http_v2_push_resources(ngx_http_request_t *r) > -{ > - u_char *start, *end, *last; > - ngx_int_t rc; > - ngx_str_t path; > - ngx_uint_t i, push; > - ngx_table_elt_t *h; > - ngx_http_v2_loc_conf_t *h2lcf; > - ngx_http_complex_value_t *pushes; > - ngx_str_t binary[NGX_HTTP_V2_PUSH_HEADERS]; > - > - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, > - "http2 push resources"); > - > - ngx_memzero(binary, NGX_HTTP_V2_PUSH_HEADERS * sizeof(ngx_str_t)); > - > - h2lcf = ngx_http_get_module_loc_conf(r, ngx_http_v2_module); > - > - if (h2lcf->pushes) { > - pushes = h2lcf->pushes->elts; > - > - for (i = 0; i < h2lcf->pushes->nelts; i++) { > - > - if (ngx_http_complex_value(r, &pushes[i], &path) != NGX_OK) { > - return NGX_ERROR; > - } > - > - if (path.len == 0) { > - continue; > - } > - > - if (path.len == 3 && ngx_strncmp(path.data, "off", 3) == 0) { > - continue; > - } > - > - rc = ngx_http_v2_push_resource(r, &path, binary); > - > - if (rc == NGX_ERROR) { > - return NGX_ERROR; > - } > - > - if (rc == NGX_ABORT) { > - return NGX_OK; > - } > - > - /* NGX_OK, NGX_DECLINED */ > - } > - } > - > - if (!h2lcf->push_preload) { > - return NGX_OK; > - } > - > - for (h = r->headers_out.link; h; h = h->next) { > - > - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, > - "http2 parse link: \"%V\"", &h->value); > - > - start = h->value.data; > - end = h->value.data + h->value.len; > - > - next_link: > - > - while (start < end && *start == ' ') { start++; } > - > - if (start == end || *start++ != '<') { > - continue; > - } > - > - while (start < end && *start == ' ') { start++; } > - > - for (last = start; last < end && *last != '>'; last++) { > - /* void */ > - } > - > - if (last == start || last == end) { > - continue; > - } > - > - path.len = last - start; > - path.data = start; > - > - start = last + 1; > - > - while (start < end && *start == ' ') { start++; } > - > - if (start == end) { > - continue; > - } > - > - if (*start == ',') { > - start++; > - goto next_link; > - } > - > - if (*start++ != ';') { > - continue; > - } > - > - last = ngx_strlchr(start, end, ','); > - > - if (last == NULL) { > - last = end; > - } > - > - push = 0; > - > - for ( ;; ) { > - > - while (start < last && *start == ' ') { start++; } > - > - if (last - start >= 6 > - && ngx_strncasecmp(start, (u_char *) "nopush", 6) == 0) > - { > - start += 6; > - > - if (start == last || *start == ' ' || *start == ';') { > - push = 0; > - break; > - } > - > - goto next_param; > - } > - > - if (last - start >= 11 > - && ngx_strncasecmp(start, (u_char *) "rel=preload", 11) == 0) > - { > - start += 11; > - > - if (start == last || *start == ' ' || *start == ';') { > - push = 1; > - } > - > - goto next_param; > - } > - > - if (last - start >= 4 > - && ngx_strncasecmp(start, (u_char *) "rel=", 4) == 0) > - { > - start += 4; > - > - while (start < last && *start == ' ') { start++; } > - > - if (start == last || *start++ != '"') { > - goto next_param; > - } > - > - for ( ;; ) { > - > - while (start < last && *start == ' ') { start++; } > - > - if (last - start >= 7 > - && ngx_strncasecmp(start, (u_char *) "preload", 7) == 0) > - { > - start += 7; > - > - if (start < last && (*start == ' ' || *start == '"')) { > - push = 1; > - break; > - } > - } > - > - while (start < last && *start != ' ' && *start != '"') { > - start++; > - } > - > - if (start == last) { > - break; > - } > - > - if (*start == '"') { > - break; > - } > - > - start++; > - } > - } > - > - next_param: > - > - start = ngx_strlchr(start, last, ';'); > - > - if (start == NULL) { > - break; > - } > - > - start++; > - } > - > - if (push) { > - while (path.len && path.data[path.len - 1] == ' ') { > - path.len--; > - } > - } > - > - if (push && path.len > - && !(path.len > 1 && path.data[0] == '/' && path.data[1] == '/')) > - { > - rc = ngx_http_v2_push_resource(r, &path, binary); > - > - if (rc == NGX_ERROR) { > - return NGX_ERROR; > - } > - > - if (rc == NGX_ABORT) { > - return NGX_OK; > - } > - > - /* NGX_OK, NGX_DECLINED */ > - } > - > - if (last < end) { > - start = last + 1; > - goto next_link; > - } > - } > - > - return NGX_OK; > -} > - > - > -static ngx_int_t > -ngx_http_v2_push_resource(ngx_http_request_t *r, ngx_str_t *path, > - ngx_str_t *binary) > -{ > - u_char *start, *pos, *tmp; > - size_t len; > - ngx_str_t *value; > - ngx_uint_t i; > - ngx_table_elt_t **h; > - ngx_connection_t *fc; > - ngx_http_v2_stream_t *stream; > - ngx_http_v2_out_frame_t *frame; > - ngx_http_v2_connection_t *h2c; > - ngx_http_v2_push_header_t *ph; > - > - fc = r->connection; > - > - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0, "http2 push resource"); > - > - stream = r->stream; > - h2c = stream->connection; > - > - if (!ngx_path_separator(path->data[0])) { > - ngx_log_error(NGX_LOG_WARN, fc->log, 0, > - "non-absolute path \"%V\" not pushed", path); > - return NGX_DECLINED; > - } > - > - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, > - "http2 pushing:%ui limit:%ui", > - h2c->pushing, h2c->concurrent_pushes); > - > - if (h2c->pushing >= h2c->concurrent_pushes) { > - return NGX_ABORT; > - } > - > - if (h2c->last_push == 0x7ffffffe) { > - return NGX_ABORT; > - } > - > - if (path->len > NGX_HTTP_V2_MAX_FIELD) { > - return NGX_DECLINED; > - } > - > - if (r->headers_in.host == NULL) { > - return NGX_ABORT; > - } > - > - ph = ngx_http_v2_push_headers; > - > - len = ngx_max(r->schema.len, path->len); > - > - if (binary[0].len) { > - tmp = ngx_palloc(r->pool, len); > - if (tmp == NULL) { > - return NGX_ERROR; > - } > - > - } else { > - for (i = 0; i < NGX_HTTP_V2_PUSH_HEADERS; i++) { > - h = (ngx_table_elt_t **) ((char *) &r->headers_in + ph[i].offset); > - > - if (*h) { > - len = ngx_max(len, (*h)->value.len); > - } > - } > - > - tmp = ngx_palloc(r->pool, len); > - if (tmp == NULL) { > - return NGX_ERROR; > - } > - > - for (i = 0; i < NGX_HTTP_V2_PUSH_HEADERS; i++) { > - h = (ngx_table_elt_t **) ((char *) &r->headers_in + ph[i].offset); > - > - if (*h == NULL) { > - continue; > - } > - > - value = &(*h)->value; > - > - len = 1 + NGX_HTTP_V2_INT_OCTETS + value->len; > - > - pos = ngx_pnalloc(r->pool, len); > - if (pos == NULL) { > - return NGX_ERROR; > - } > - > - binary[i].data = pos; > - > - *pos++ = ngx_http_v2_inc_indexed(ph[i].index); > - pos = ngx_http_v2_write_value(pos, value->data, value->len, tmp); > - > - binary[i].len = pos - binary[i].data; > - } > - } > - > - len = (h2c->table_update ? 1 : 0) > - + 1 > - + 1 + NGX_HTTP_V2_INT_OCTETS + path->len > - + 1 + NGX_HTTP_V2_INT_OCTETS + r->schema.len; > - > - for (i = 0; i < NGX_HTTP_V2_PUSH_HEADERS; i++) { > - len += binary[i].len; > - } > - > - pos = ngx_pnalloc(r->pool, len); > - if (pos == NULL) { > - return NGX_ERROR; > - } > - > - start = pos; > - > - if (h2c->table_update) { > - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0, > - "http2 table size update: 0"); > - *pos++ = (1 << 5) | 0; > - h2c->table_update = 0; > - } > - > - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0, > - "http2 push header: \":method: GET\""); > - > - *pos++ = ngx_http_v2_indexed(NGX_HTTP_V2_METHOD_GET_INDEX); > - > - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, fc->log, 0, > - "http2 push header: \":path: %V\"", path); > - > - *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_PATH_INDEX); > - pos = ngx_http_v2_write_value(pos, path->data, path->len, tmp); > - > - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, fc->log, 0, > - "http2 push header: \":scheme: %V\"", &r->schema); > - > - if (r->schema.len == 5 && ngx_strncmp(r->schema.data, "https", 5) == 0) { > - *pos++ = ngx_http_v2_indexed(NGX_HTTP_V2_SCHEME_HTTPS_INDEX); > - > - } else if (r->schema.len == 4 > - && ngx_strncmp(r->schema.data, "http", 4) == 0) > - { > - *pos++ = ngx_http_v2_indexed(NGX_HTTP_V2_SCHEME_HTTP_INDEX); > - > - } else { > - *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_SCHEME_HTTP_INDEX); > - pos = ngx_http_v2_write_value(pos, r->schema.data, r->schema.len, tmp); > - } > - > - for (i = 0; i < NGX_HTTP_V2_PUSH_HEADERS; i++) { > - h = (ngx_table_elt_t **) ((char *) &r->headers_in + ph[i].offset); > - > - if (*h == NULL) { > - continue; > - } > - > - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, fc->log, 0, > - "http2 push header: \"%V: %V\"", > - &ph[i].name, &(*h)->value); > - > - pos = ngx_cpymem(pos, binary[i].data, binary[i].len); > - } > - > - frame = ngx_http_v2_create_push_frame(r, start, pos); > - if (frame == NULL) { > - return NGX_ERROR; > - } > - > - ngx_http_v2_queue_blocked_frame(h2c, frame); > - > - stream->queued++; > - > - stream = ngx_http_v2_push_stream(stream, path); > - > - if (stream) { > - stream->request->request_length = pos - start; > - return NGX_OK; > - } > - > - return NGX_ERROR; > -} > - > - > static ngx_http_v2_out_frame_t * > ngx_http_v2_create_headers_frame(ngx_http_request_t *r, u_char *pos, > u_char *end, ngx_uint_t fin) > @@ -1180,125 +735,6 @@ ngx_http_v2_create_headers_frame(ngx_htt > > > static ngx_http_v2_out_frame_t * > -ngx_http_v2_create_push_frame(ngx_http_request_t *r, u_char *pos, u_char *end) > -{ > - u_char type, flags; > - size_t rest, frame_size, len; > - ngx_buf_t *b; > - ngx_chain_t *cl, **ll; > - ngx_http_v2_stream_t *stream; > - ngx_http_v2_out_frame_t *frame; > - ngx_http_v2_connection_t *h2c; > - > - stream = r->stream; > - h2c = stream->connection; > - rest = NGX_HTTP_V2_STREAM_ID_SIZE + (end - pos); > - > - frame = ngx_palloc(r->pool, sizeof(ngx_http_v2_out_frame_t)); > - if (frame == NULL) { > - return NULL; > - } > - > - frame->handler = ngx_http_v2_push_frame_handler; > - frame->stream = stream; > - frame->length = rest; > - frame->blocked = 1; > - frame->fin = 0; > - > - ll = &frame->first; > - > - type = NGX_HTTP_V2_PUSH_PROMISE_FRAME; > - flags = NGX_HTTP_V2_NO_FLAG; > - frame_size = h2c->frame_size; > - > - for ( ;; ) { > - if (rest <= frame_size) { > - frame_size = rest; > - flags |= NGX_HTTP_V2_END_HEADERS_FLAG; > - } > - > - b = ngx_create_temp_buf(r->pool, > - NGX_HTTP_V2_FRAME_HEADER_SIZE > - + ((type == NGX_HTTP_V2_PUSH_PROMISE_FRAME) > - ? NGX_HTTP_V2_STREAM_ID_SIZE : 0)); > - if (b == NULL) { > - return NULL; > - } > - > - b->last = ngx_http_v2_write_len_and_type(b->last, frame_size, type); > - *b->last++ = flags; > - b->last = ngx_http_v2_write_sid(b->last, stream->node->id); > - > - b->tag = (ngx_buf_tag_t) &ngx_http_v2_module; > - > - if (type == NGX_HTTP_V2_PUSH_PROMISE_FRAME) { > - h2c->last_push += 2; > - > - b->last = ngx_http_v2_write_sid(b->last, h2c->last_push); > - len = frame_size - NGX_HTTP_V2_STREAM_ID_SIZE; > - > - } else { > - len = frame_size; > - } > - > - cl = ngx_alloc_chain_link(r->pool); > - if (cl == NULL) { > - return NULL; > - } > - > - cl->buf = b; > - > - *ll = cl; > - ll = &cl->next; > - > - b = ngx_calloc_buf(r->pool); > - if (b == NULL) { > - return NULL; > - } > - > - b->pos = pos; > - > - pos += len; > - > - b->last = pos; > - b->start = b->pos; > - b->end = b->last; > - b->temporary = 1; > - > - cl = ngx_alloc_chain_link(r->pool); > - if (cl == NULL) { > - return NULL; > - } > - > - cl->buf = b; > - > - *ll = cl; > - ll = &cl->next; > - > - rest -= frame_size; > - > - if (rest) { > - frame->length += NGX_HTTP_V2_FRAME_HEADER_SIZE; > - > - type = NGX_HTTP_V2_CONTINUATION_FRAME; > - continue; > - } > - > - cl->next = NULL; > - frame->last = cl; > - > - ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, > - "http2:%ui create PUSH_PROMISE frame %p: " > - "sid:%ui len:%uz", > - stream->node->id, frame, h2c->last_push, > - frame->length); > - > - return frame; > - } > -} > - > - > -static ngx_http_v2_out_frame_t * > ngx_http_v2_create_trailers_frame(ngx_http_request_t *r) > { > u_char *pos, *start, *tmp; > @@ -1902,62 +1338,6 @@ ngx_http_v2_headers_frame_handler(ngx_ht > > > static ngx_int_t > -ngx_http_v2_push_frame_handler(ngx_http_v2_connection_t *h2c, > - ngx_http_v2_out_frame_t *frame) > -{ > - ngx_chain_t *cl, *ln; > - ngx_http_v2_stream_t *stream; > - > - stream = frame->stream; > - cl = frame->first; > - > - for ( ;; ) { > - if (cl->buf->pos != cl->buf->last) { > - frame->first = cl; > - > - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, > - "http2:%ui PUSH_PROMISE frame %p was sent partially", > - stream->node->id, frame); > - > - return NGX_AGAIN; > - } > - > - ln = cl->next; > - > - if (cl->buf->tag == (ngx_buf_tag_t) &ngx_http_v2_module) { > - cl->next = stream->free_frame_headers; > - stream->free_frame_headers = cl; > - > - } else { > - cl->next = stream->free_bufs; > - stream->free_bufs = cl; > - } > - > - if (cl == frame->last) { > - break; > - } > - > - cl = ln; > - } > - > - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, > - "http2:%ui PUSH_PROMISE frame %p was sent", > - stream->node->id, frame); > - > - stream->request->header_size += NGX_HTTP_V2_FRAME_HEADER_SIZE > - + frame->length; > - > - h2c->payload_bytes += frame->length; > - > - ngx_http_v2_handle_frame(stream, frame); > - > - ngx_http_v2_handle_stream(h2c, stream); > - > - return NGX_OK; > -} > - > - > -static ngx_int_t > ngx_http_v2_data_frame_handler(ngx_http_v2_connection_t *h2c, > ngx_http_v2_out_frame_t *frame) > { > diff --git a/src/http/v2/ngx_http_v2_module.c b/src/http/v2/ngx_http_v2_module.c > --- a/src/http/v2/ngx_http_v2_module.c > +++ b/src/http/v2/ngx_http_v2_module.c > @@ -27,8 +27,6 @@ static void *ngx_http_v2_create_loc_conf > static char *ngx_http_v2_merge_loc_conf(ngx_conf_t *cf, void *parent, > void *child); > > -static char *ngx_http_v2_push(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); > - > static char *ngx_http_v2_recv_buffer_size(ngx_conf_t *cf, void *post, > void *data); > static char *ngx_http_v2_pool_size(ngx_conf_t *cf, void *post, void *data); > @@ -38,6 +36,8 @@ static char *ngx_http_v2_streams_index_m > static char *ngx_http_v2_chunk_size(ngx_conf_t *cf, void *post, void *data); > static char *ngx_http_v2_obsolete(ngx_conf_t *cf, ngx_command_t *cmd, > void *conf); > +static char *ngx_http_v2_obsolete_push(ngx_conf_t *cf, ngx_command_t *cmd, > + void *conf); > > > static ngx_conf_deprecated_t ngx_http_v2_recv_timeout_deprecated = { > @@ -105,9 +105,9 @@ static ngx_command_t ngx_http_v2_comman > > { ngx_string("http2_max_concurrent_pushes"), > NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, > - ngx_conf_set_num_slot, > - NGX_HTTP_SRV_CONF_OFFSET, > - offsetof(ngx_http_v2_srv_conf_t, concurrent_pushes), > + ngx_http_v2_obsolete_push, > + 0, > + 0, > NULL }, > > { ngx_string("http2_max_requests"), > @@ -168,15 +168,15 @@ static ngx_command_t ngx_http_v2_comman > > { ngx_string("http2_push_preload"), > NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, > - ngx_conf_set_flag_slot, > - NGX_HTTP_LOC_CONF_OFFSET, > - offsetof(ngx_http_v2_loc_conf_t, push_preload), > + ngx_http_v2_obsolete_push, > + 0, > + 0, > NULL }, > > { ngx_string("http2_push"), > NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, > - ngx_http_v2_push, > - NGX_HTTP_LOC_CONF_OFFSET, > + ngx_http_v2_obsolete_push, > + 0, > 0, > NULL }, > Using ngx_http_v2_obsolete() might be better, see below. > @@ -326,7 +326,6 @@ ngx_http_v2_create_srv_conf(ngx_conf_t * > h2scf->pool_size = NGX_CONF_UNSET_SIZE; > > h2scf->concurrent_streams = NGX_CONF_UNSET_UINT; > - h2scf->concurrent_pushes = NGX_CONF_UNSET_UINT; > > h2scf->preread_size = NGX_CONF_UNSET_SIZE; > > @@ -348,8 +347,6 @@ ngx_http_v2_merge_srv_conf(ngx_conf_t *c > > ngx_conf_merge_uint_value(conf->concurrent_streams, > prev->concurrent_streams, 128); > - ngx_conf_merge_uint_value(conf->concurrent_pushes, > - prev->concurrent_pushes, 10); > > ngx_conf_merge_size_value(conf->preread_size, prev->preread_size, 65536); > > @@ -370,17 +367,8 @@ ngx_http_v2_create_loc_conf(ngx_conf_t * > return NULL; > } > > - /* > - * set by ngx_pcalloc(): > - * > - * h2lcf->pushes = NULL; > - */ > - > h2lcf->chunk_size = NGX_CONF_UNSET_SIZE; > > - h2lcf->push_preload = NGX_CONF_UNSET; > - h2lcf->push = NGX_CONF_UNSET; > - > return h2lcf; > } > > @@ -393,72 +381,6 @@ ngx_http_v2_merge_loc_conf(ngx_conf_t *c > > ngx_conf_merge_size_value(conf->chunk_size, prev->chunk_size, 8 * 1024); > > - ngx_conf_merge_value(conf->push, prev->push, 1); > - > - if (conf->push && conf->pushes == NULL) { > - conf->pushes = prev->pushes; > - } > - > - ngx_conf_merge_value(conf->push_preload, prev->push_preload, 0); > - > - return NGX_CONF_OK; > -} > - > - > -static char * > -ngx_http_v2_push(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) > -{ > - ngx_http_v2_loc_conf_t *h2lcf = conf; > - > - ngx_str_t *value; > - ngx_http_complex_value_t *cv; > - ngx_http_compile_complex_value_t ccv; > - > - value = cf->args->elts; > - > - if (ngx_strcmp(value[1].data, "off") == 0) { > - > - if (h2lcf->pushes) { > - return "\"off\" parameter cannot be used with URI"; > - } > - > - if (h2lcf->push == 0) { > - return "is duplicate"; > - } > - > - h2lcf->push = 0; > - return NGX_CONF_OK; > - } > - > - if (h2lcf->push == 0) { > - return "URI cannot be used with \"off\" parameter"; > - } > - > - h2lcf->push = 1; > - > - if (h2lcf->pushes == NULL) { > - h2lcf->pushes = ngx_array_create(cf->pool, 1, > - sizeof(ngx_http_complex_value_t)); > - if (h2lcf->pushes == NULL) { > - return NGX_CONF_ERROR; > - } > - } > - > - cv = ngx_array_push(h2lcf->pushes); > - if (cv == NULL) { > - return NGX_CONF_ERROR; > - } > - > - ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); > - > - ccv.cf = cf; > - ccv.value = &value[1]; > - ccv.complex_value = cv; > - > - if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { > - return NGX_CONF_ERROR; > - } > - > return NGX_CONF_OK; > } > > @@ -569,3 +491,14 @@ ngx_http_v2_obsolete(ngx_conf_t *cf, ngx > > return NGX_CONF_OK; > } > + > + > +static char * > +ngx_http_v2_obsolete_push(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) > +{ > + ngx_conf_log_error(NGX_LOG_WARN, cf, 0, > + "HTTP/2 server push was removed, " > + "the \"%V\" directive is obsolete", &cmd->name); I would rather use something like: ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "the \"%V\" directive is obsolete, ignored", &cmd->name); And it might make sense to update the ngx_http_v2_obsolete() function to do this if no cmd->post is provided. diff --git a/src/http/v2/ngx_http_v2_module.c b/src/http/v2/ngx_http_v2_module.c --- a/src/http/v2/ngx_http_v2_module.c +++ b/src/http/v2/ngx_http_v2_module.c @@ -36,8 +36,6 @@ static char *ngx_http_v2_streams_index_m static char *ngx_http_v2_chunk_size(ngx_conf_t *cf, void *post, void *data); static char *ngx_http_v2_obsolete(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); -static char *ngx_http_v2_obsolete_push(ngx_conf_t *cf, ngx_command_t *cmd, - void *conf); static ngx_conf_deprecated_t ngx_http_v2_recv_timeout_deprecated = { @@ -105,7 +103,7 @@ static ngx_command_t ngx_http_v2_comman { ngx_string("http2_max_concurrent_pushes"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, - ngx_http_v2_obsolete_push, + ngx_http_v2_obsolete, 0, 0, NULL }, @@ -168,14 +166,14 @@ static ngx_command_t ngx_http_v2_comman { ngx_string("http2_push_preload"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, - ngx_http_v2_obsolete_push, + ngx_http_v2_obsolete, 0, 0, NULL }, { ngx_string("http2_push"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, - ngx_http_v2_obsolete_push, + ngx_http_v2_obsolete, 0, 0, NULL }, @@ -484,21 +482,17 @@ ngx_http_v2_obsolete(ngx_conf_t *cf, ngx { ngx_conf_deprecated_t *d = cmd->post; - ngx_conf_log_error(NGX_LOG_WARN, cf, 0, - "the \"%s\" directive is obsolete, " - "use the \"%s\" directive instead", - d->old_name, d->new_name); + if (d) { + ngx_conf_log_error(NGX_LOG_WARN, cf, 0, + "the \"%s\" directive is obsolete, " + "use the \"%s\" directive instead", + d->old_name, d->new_name); + + } else { + ngx_conf_log_error(NGX_LOG_WARN, cf, 0, + "the \"%V\" directive is obsolete, ignored", + &cmd->name); + } return NGX_CONF_OK; } - - -static char * -ngx_http_v2_obsolete_push(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_conf_log_error(NGX_LOG_WARN, cf, 0, - "HTTP/2 server push was removed, " - "the \"%V\" directive is obsolete", &cmd->name); - - return NGX_CONF_OK; -} > + > + return NGX_CONF_OK; > +} > diff --git a/src/http/v2/ngx_http_v2_module.h b/src/http/v2/ngx_http_v2_module.h > --- a/src/http/v2/ngx_http_v2_module.h > +++ b/src/http/v2/ngx_http_v2_module.h > @@ -22,11 +22,6 @@ typedef struct { > > typedef struct { > size_t chunk_size; > - > - ngx_flag_t push_preload; > - > - ngx_flag_t push; > - ngx_array_t *pushes; > } ngx_http_v2_loc_conf_t; > > Otherwise looks good. -- Maxim Dounin http://mdounin.ru/ From mdounin at mdounin.ru Sun Jun 4 21:58:42 2023 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 5 Jun 2023 00:58:42 +0300 Subject: [PATCH 1 of 2] Removed obsolete SPDY documentation In-Reply-To: References: Message-ID: Hello! On Thu, Jun 01, 2023 at 06:16:42PM +0400, Sergey Kandaurov wrote: > # HG changeset patch > # User Sergey Kandaurov > # Date 1685628905 -14400 > # Thu Jun 01 18:15:05 2023 +0400 > # Node ID b891dba3aadb77b0a4621a981edbb1c6a8d3c5be > # Parent 203f32f5373458548931a706e728fdf94daa6a77 > Removed obsolete SPDY documentation. > > diff --git a/xml/en/docs/http/ngx_http_core_module.xml b/xml/en/docs/http/ngx_http_core_module.xml > --- a/xml/en/docs/http/ngx_http_core_module.xml > +++ b/xml/en/docs/http/ngx_http_core_module.xml > @@ -10,7 +10,7 @@ > link="/en/docs/http/ngx_http_core_module.html" > lang="en" > - rev="104"> > + rev="105"> > >
> > @@ -1272,8 +1272,7 @@ The “wait-read-ignore” cycle is repeated, but no longer than specified by the > [default_server] > [ssl] > [http2 | > - quic | > - spdy] > + quic] > [proxy_protocol] > [setfib=number] > [fastopen=number] > @@ -1291,8 +1290,7 @@ The “wait-read-ignore” cycle is repeated, but no longer than specified by the > [default_server] > [ssl] > [http2 | > - quic | > - spdy] > + quic] > [proxy_protocol] > [setfib=number] > [fastopen=number] > @@ -1310,8 +1308,7 @@ The “wait-read-ignore” cycle is repeated, but no longer than specified by the > [default_server] > [ssl] > [http2 | > - quic | > - spdy] > + quic] > [proxy_protocol] > [backlog=number] > [rcvbuf=size] > @@ -1395,14 +1392,6 @@ The quic parameter (1 > > > > -The spdy parameter (1.3.15-1.9.4) allows accepting > -SPDY connections on this port. > -Normally, for this to work the ssl parameter should be > -specified as well, but nginx can also be configured to accept SPDY > -connections without SSL. > - > - > - > The proxy_protocol parameter (1.5.12) > allows specifying that all connections accepted on this port should use the > PROXY > diff --git a/xml/en/docs/http/ngx_http_spdy_module.xml b/xml/en/docs/http/ngx_http_spdy_module.xml > --- a/xml/en/docs/http/ngx_http_spdy_module.xml > +++ b/xml/en/docs/http/ngx_http_spdy_module.xml > @@ -9,155 +9,14 @@ > link="/en/docs/http/ngx_http_spdy_module.html" > lang="en" > - rev="10"> > + rev="11"> > >
> > > -The ngx_http_spdy_module module provides experimental > -support for SPDY. > -Currently, > -draft > -3.1 of SPDY protocol is implemented. > - > -Before version 1.5.10, > -draft > -2 of SPDY protocol was implemented. > - > - > - > - > -This module is not built by default, it should be enabled with > -the --with-http_spdy_module > -configuration parameter. > - > - > - > - > This module was superseded by the > ngx_http_v2_module module > in 1.9.5. > - > - > - > -
> - > - > -
> - > - > -The module is experimental, caveat emptor applies. > - > - > - > -Current implementation of SPDY protocol does not support “server push”. > - > - > - > -In versions prior to 1.5.9, responses in SPDY connections could not be > -rate limited. > - > - > - > -Buffering of a client request body cannot be disabled > -regardless of > -, > -, > -, and > - > -directive values. > - > - > -
> - > - > -
> - > - > - > -server { > - listen 443 ssl spdy; > - > - ssl_certificate server.crt; > - ssl_certificate_key server.key; > - ... > -} > - > - > -Note that in order to accept both > -HTTPS and SPDY connections > -simultaneously on the same port, > -OpenSSL library used should support > -“Next Protocol Negotiation” TLS extension, available since OpenSSL > -version 1.0.1. > - > - > - > -
> - > - > -
> - > - > -size > -8k > -http > -server > -location > -1.5.9 > - > - > -Sets the maximum size of chunks > -into which the response body is > - > -sliced. > -A too low value results in higher overhead. > -A too high value impairs prioritization due to > - > -HOL blocking. > - > - > - > - > - > - > -level > -0 > -http > -server > - > - > -Sets the header compression level of a response in a range from > -1 (fastest, less compression) to 9 (slowest, best compression). > -The special value 0 turns off the header compression. > - > - > - > - > -
> - > - > -
> - > - > -The ngx_http_spdy_module module > -supports the following embedded variables: > - > - > -$spdy > - > -SPDY protocol version for SPDY connections, > -or an empty string otherwise; > - > - > -$spdy_request_priority > - > - > -request priority for SPDY connections, > -or an empty string otherwise. > - > - > - > > >
> diff --git a/xml/en/docs/http/ngx_http_v2_module.xml b/xml/en/docs/http/ngx_http_v2_module.xml > --- a/xml/en/docs/http/ngx_http_v2_module.xml > +++ b/xml/en/docs/http/ngx_http_v2_module.xml > @@ -15,9 +15,8 @@ > > > The ngx_http_v2_module module (1.9.5) provides > -support for HTTP/2 > -and supersedes the > -ngx_http_spdy_module module. > +support for > +HTTP/2. > > > > diff --git a/xml/en/docs/index.xml b/xml/en/docs/index.xml > --- a/xml/en/docs/index.xml > +++ b/xml/en/docs/index.xml > @@ -8,7 +8,7 @@ >
link="/en/docs/" > lang="en" > - rev="48" > + rev="49" > toc="no"> > > > @@ -434,11 +434,6 @@ ngx_http_slice_module > > > > - > -ngx_http_spdy_module > - > - > - > > ngx_http_split_clients_module > > diff --git a/xml/ru/docs/http/ngx_http_core_module.xml b/xml/ru/docs/http/ngx_http_core_module.xml > --- a/xml/ru/docs/http/ngx_http_core_module.xml > +++ b/xml/ru/docs/http/ngx_http_core_module.xml > @@ -10,7 +10,7 @@ > link="/ru/docs/http/ngx_http_core_module.html" > lang="ru" > - rev="104"> > + rev="105"> > >
> > @@ -1266,8 +1266,7 @@ location /flv/ { > [default_server] > [ssl] > [http2 | > - quic | > - spdy] > + quic] > [proxy_protocol] > [setfib=число] > [fastopen=число] > @@ -1285,8 +1284,7 @@ location /flv/ { > [default_server] > [ssl] > [http2 | > - quic | > - spdy] > + quic] > [proxy_protocol] > [setfib=число] > [fastopen=число] > @@ -1304,8 +1302,7 @@ location /flv/ { > [default_server] > [ssl] > [http2 | > - quic | > - spdy] > + quic] > [proxy_protocol] > [backlog=число] > [rcvbuf=размер] > @@ -1387,14 +1384,6 @@ HTTP/2-соединений без SSL. > > > > -Параметр spdy (1.3.15-1.9.4) позволяет принимать на этом порту > -SPDY-соединения. > -Обычно, чтобы это работало, следует также указать параметр > -ssl, однако nginx можно также настроить и на приём > -SPDY-соединений без SSL. > - > - > - > Параметр proxy_protocol (1.5.12) > указывает на то, что все соединения, принимаемые на данном порту, > должны использовать > diff --git a/xml/ru/docs/http/ngx_http_spdy_module.xml b/xml/ru/docs/http/ngx_http_spdy_module.xml > --- a/xml/ru/docs/http/ngx_http_spdy_module.xml > +++ b/xml/ru/docs/http/ngx_http_spdy_module.xml > @@ -9,156 +9,14 @@ > link="/ru/docs/http/ngx_http_spdy_module.html" > lang="ru" > - rev="10"> > + rev="11"> > >
> > > -Модуль ngx_http_spdy_module обеспечивает экспериментальную > -поддержку SPDY. > -В настоящий момент реализован > -draft > -3.1 протокола SPDY. > - > -До версии 1.5.10 был реализован > -draft > -2 протокола SPDY. > - > - > - > - > -По умолчанию этот модуль не собирается, его сборку необходимо > -разрешить с помощью конфигурационного параметра > ---with-http_spdy_module. > - > - > - > - > Этот модуль был заменён модулем > ngx_http_v2_module > в версии 1.9.5. > - > - > - > -
> - > - > -
> - > - > -Модуль экспериментальный, поэтому возможно всё. > - > - > - > -Текущая реализация протокола SPDY не поддерживает server push. > - > - > - > -До версии 1.5.9 скорость передачи ответа клиенту в SPDY-соединении не могла быть > -ограничена. > - > - > - > -Буферизация тела запроса клиента не может быть выключена > -независимо от значения директив > -, > -, > - и > -. > - > - > -
> - > - > -
> - > - > - > -server { > - listen 443 ssl spdy; > - > - ssl_certificate server.crt; > - ssl_certificate_key server.key; > - ... > -} > - > - > -Для того чтобы одновременно принимать > -HTTPS и > -SPDY соединения на том же порту, > -используемая библиотека OpenSSL > -должна поддерживать расширение Next Protocol Negotiation протокола TLS, > -доступное с версии OpenSSL 1.0.1. > - > - > - > -
> - > - > -
> - > - > -размер > -8k > -http > -server > -location > -1.5.9 > - > - > -Задаёт максимальный размер частей, > -на которые будет > - > -разделяться тело ответа. > -Слишком маленькое значение может > -привести к росту накладных расходов. > -Слишком большое значение может > -негативно сказаться на приоритизации из-за > - > -блокировки очереди. > - > - > - > - > - > - > -степень > -0 > -http > -server > - > - > -Устанавливает степень сжатия заголовков ответа > -в диапазоне от 1 (быстрее, но хуже сжатие) до 9 (медленнее, лучшее сжатие). > -Специальное значение 0 отключает сжатие заголовков. > - > - > - > - > -
> - > - > -
> - > - > -Модуль ngx_http_spdy_module > -поддерживает следующие встроенные переменные: > - > - > -$spdy > - > -версия протокола SPDY для SPDY-соединений, > -либо пустая строка; > - > - > -$spdy_request_priority > - > - > -приоритет запроса для SPDY-соединений, > -либо пустая строка. > - > - > - > > >
> diff --git a/xml/ru/docs/http/ngx_http_v2_module.xml b/xml/ru/docs/http/ngx_http_v2_module.xml > --- a/xml/ru/docs/http/ngx_http_v2_module.xml > +++ b/xml/ru/docs/http/ngx_http_v2_module.xml > @@ -15,9 +15,8 @@ > > > Модуль ngx_http_v2_module (1.9.5) обеспечивает > -поддержку HTTP/2 > -и заменяет > -модуль ngx_http_spdy_module. > +поддержку > +HTTP/2. > > > > diff --git a/xml/ru/docs/index.xml b/xml/ru/docs/index.xml > --- a/xml/ru/docs/index.xml > +++ b/xml/ru/docs/index.xml > @@ -8,7 +8,7 @@ >
link="/ru/docs/" > lang="ru" > - rev="48" > + rev="49" > toc="no"> > > > @@ -439,11 +439,6 @@ ngx_http_slice_module > > > > - > -ngx_http_spdy_module > - > - > - > > ngx_http_split_clients_module > Looks good. -- Maxim Dounin http://mdounin.ru/ From mdounin at mdounin.ru Sun Jun 4 22:02:05 2023 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 5 Jun 2023 01:02:05 +0300 Subject: [PATCH 2 of 2] Mention HTTP/3 on the index page In-Reply-To: <08e1ceba17535e7f42a8.1685629003@enoparse.local> References: <08e1ceba17535e7f42a8.1685629003@enoparse.local> Message-ID: Hello! On Thu, Jun 01, 2023 at 06:16:43PM +0400, Sergey Kandaurov wrote: > # HG changeset patch > # User Sergey Kandaurov > # Date 1685628906 -14400 > # Thu Jun 01 18:15:06 2023 +0400 > # Node ID 08e1ceba17535e7f42a8ece311686f977b593a78 > # Parent b891dba3aadb77b0a4621a981edbb1c6a8d3c5be > Mention HTTP/3 on the index page. > > diff --git a/xml/en/index.xml b/xml/en/index.xml > --- a/xml/en/index.xml > +++ b/xml/en/index.xml > @@ -8,7 +8,7 @@ >
link="/en/" > lang="en" > - rev="155"> > + rev="156"> > > >
> @@ -100,7 +100,11 @@ TLS SNI support; > > > Support for HTTP/2 > -with weighted and dependency-based prioritization. > +with weighted and dependency-based prioritization; > + > + > + > +Support for HTTP/3. > > > > diff --git a/xml/ru/index.xml b/xml/ru/index.xml > --- a/xml/ru/index.xml > +++ b/xml/ru/index.xml > @@ -8,7 +8,7 @@ >
link="/ru/" > lang="ru" > - rev="155"> > + rev="156"> > > >
> @@ -101,7 +101,11 @@ chunked ответы, > > > Поддержка HTTP/2 > -с приоритизацией на основе весов и зависимостей. > +с приоритизацией на основе весов и зависимостей; > + > + > + > +Поддержка HTTP/3. > > > Looks good. -- Maxim Dounin http://mdounin.ru/ From arut at nginx.com Mon Jun 5 14:19:51 2023 From: arut at nginx.com (Roman Arutyunyan) Date: Mon, 5 Jun 2023 18:19:51 +0400 Subject: [PATCH 2 of 3] HTTP/2: "http2" directive In-Reply-To: References: <735f9e501922e4b0a1b2.1675781431@arut-laptop> <20230209120234.rttyjviwir4sneed@N00W24XTQX> <20230209123359.i6fosl5r6tdhpvhv@N00W24XTQX> <71CADCEB-5BD1-4F67-AE85-581943918D5B@nginx.com> <20230516123938.rgrmdpern3i5hq5n@N00W24XTQX> Message-ID: <20230605141951.wx5np5jwxhjsxybc@N00W24XTQX> Hi, On Sat, Jun 03, 2023 at 12:37:03AM +0300, Maxim Dounin wrote: > Hello! > > On Tue, May 16, 2023 at 04:39:38PM +0400, Roman Arutyunyan wrote: > > > On Thu, Feb 09, 2023 at 07:56:55PM +0400, Sergey Kandaurov wrote: > > > > > > > On 9 Feb 2023, at 16:33, Roman Arutyunyan wrote: > > > > > > > > Hi, > > > > > > > > On Thu, Feb 09, 2023 at 04:02:34PM +0400, Roman Arutyunyan wrote: > > > > > > > > [..] > > > > > > > >> diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c > > > >> --- a/src/http/ngx_http_request.c > > > >> +++ b/src/http/ngx_http_request.c > > > >> @@ -318,12 +318,6 @@ ngx_http_init_connection(ngx_connection_ > > > >> rev->handler = ngx_http_wait_request_handler; > > > >> c->write->handler = ngx_http_empty_handler; > > > >> > > > >> -#if (NGX_HTTP_V2) > > > >> - if (hc->addr_conf->http2) { > > > >> - rev->handler = ngx_http_v2_init; > > > >> - } > > > >> -#endif > > > >> - > > > >> #if (NGX_HTTP_V3) > > > >> if (hc->addr_conf->quic) { > > > >> ngx_http_v3_init_stream(c); > > > >> @@ -383,6 +377,9 @@ ngx_http_wait_request_handler(ngx_event_ > > > >> ngx_buf_t *b; > > > >> ngx_connection_t *c; > > > >> ngx_http_connection_t *hc; > > > >> +#if (NGX_HTTP_V2) > > > >> + ngx_http_v2_srv_conf_t *h2scf; > > > >> +#endif > > > >> ngx_http_core_srv_conf_t *cscf; > > > >> > > > >> c = rev->data; > > > >> @@ -429,6 +426,8 @@ ngx_http_wait_request_handler(ngx_event_ > > > >> b->end = b->last + size; > > > >> } > > > >> > > > >> + size = b->end - b->last; > > > >> + > > > >> n = c->recv(c, b->last, size); > > > >> > > > >> if (n == NGX_AGAIN) { > > > >> @@ -443,12 +442,16 @@ ngx_http_wait_request_handler(ngx_event_ > > > >> return; > > > >> } > > > >> > > > >> - /* > > > >> - * We are trying to not hold c->buffer's memory for an idle connection. > > > >> - */ > > > >> - > > > >> - if (ngx_pfree(c->pool, b->start) == NGX_OK) { > > > >> - b->start = NULL; > > > >> + if (b->pos == b->last) { > > > >> + > > > >> + /* > > > >> + * We are trying to not hold c->buffer's memory for an > > > >> + * idle connection. > > > >> + */ > > > >> + > > > >> + if (ngx_pfree(c->pool, b->start) == NGX_OK) { > > > >> + b->start = NULL; > > > >> + } > > > >> } > > > >> > > > >> return; > > > >> @@ -489,10 +492,34 @@ ngx_http_wait_request_handler(ngx_event_ > > > >> } > > > >> } > > > >> > > > >> + ngx_reusable_connection(c, 0); > > > >> + > > > >> +#if (NGX_HTTP_V2) > > > >> + > > > >> + h2scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v2_module); > > > >> + > > > >> + if (!c->ssl && (h2scf->enable || hc->addr_conf->http2)) { > > > > > > > > And one more fix for compilation with HTTP/2, but without SSL: > > > > > > > > diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c > > > > --- a/src/http/ngx_http_request.c > > > > +++ b/src/http/ngx_http_request.c > > > > @@ -498,8 +498,12 @@ ngx_http_wait_request_handler(ngx_event_ > > > > > > > > h2scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v2_module); > > > > > > > > - if (!c->ssl && (h2scf->enable || hc->addr_conf->http2)) { > > > > - > > > > + if ((h2scf->enable || hc->addr_conf->http2) > > > > +#if (NGX_HTTP_SSL) > > > > + && !c->ssl > > > > +#endif > > > > + ) > > > > + { > > > > size = ngx_min(sizeof(NGX_HTTP_V2_PREFACE) - 1, > > > > (size_t) (b->last - b->pos)); > > > > > > > > > > I think this test needs to be replaced with !hc->ssl. > > > Otherwise, it would allow to establish (and keep) h2c on ssl-enabled > > > sockets, which we likely do not want to allow. > > > > After a series of discussions we decided to go with !hc->ssl. As a result, > > any non-SSL connection on an SSL port will trigger the HTTP/1 error page. > > Previous attempt to trigger the HTTP/2 error in case client request is > > recognized as HTTP/2, is discarded since the situation is unlikely. > > > > [..] > > > > -- > > Roman Arutyunyan > > > # HG changeset patch > > # User Roman Arutyunyan > > # Date 1684240208 -14400 > > # Tue May 16 16:30:08 2023 +0400 > > # Branch quic > > # Node ID 4dcd2b42c23973815a6b8a7f54bbd1460c314c93 > > # Parent d8272b84031bea1940ef8a5b8e2f79ec6a2dcfc1 > > HTTP/2: "http2" directive. > > > > The directive enables HTTP/2 in the current server. The previous way to > > enable HTTP/2 via "listen ... http2" is now deprecated. The new approach > > allows to share HTTP/2 and HTTP/0.9-1.1 on the same port. > > > > For SSL connections, HTTP/2 is now selected by ALPN callback based on whether > > the protocol is enabled in the virtual server chosen by SNI. This however only > > works since OpenSSL 1.0.2h, where ALPN callback is invoked after SNI callback. > > For older versions of OpenSSL, HTTP/2 is enabled based on the default virtual > > server configuration. > > > > For plain TCP connections, HTTP/2 is now auto-detected by HTTP/2 preface, if > > HTTP/2 is enabled in the default virtual server. If preface is not matched, > > HTTP/0.9-1.1 is assumed. > > > > diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c > > --- a/src/http/modules/ngx_http_ssl_module.c > > +++ b/src/http/modules/ngx_http_ssl_module.c > > @@ -435,6 +435,9 @@ ngx_http_ssl_alpn_select(ngx_ssl_conn_t > > #if (NGX_HTTP_V2 || NGX_HTTP_V3) > > ngx_http_connection_t *hc; > > #endif > > +#if (NGX_HTTP_V2) > > + ngx_http_v2_srv_conf_t *h2scf; > > +#endif > > #if (NGX_HTTP_V3) > > ngx_http_v3_srv_conf_t *h3scf; > > #endif > > @@ -456,12 +459,6 @@ ngx_http_ssl_alpn_select(ngx_ssl_conn_t > > hc = c->data; > > #endif > > > > -#if (NGX_HTTP_V2) > > - if (hc->addr_conf->http2) { > > - srv = (unsigned char *) NGX_HTTP_V2_ALPN_PROTO NGX_HTTP_ALPN_PROTOS; > > - srvlen = sizeof(NGX_HTTP_V2_ALPN_PROTO NGX_HTTP_ALPN_PROTOS) - 1; > > - } else > > -#endif > > #if (NGX_HTTP_V3) > > if (hc->addr_conf->quic) { > > > > @@ -488,8 +485,19 @@ ngx_http_ssl_alpn_select(ngx_ssl_conn_t > > } else > > #endif > > { > > - srv = (unsigned char *) NGX_HTTP_ALPN_PROTOS; > > - srvlen = sizeof(NGX_HTTP_ALPN_PROTOS) - 1; > > +#if (NGX_HTTP_V2) > > + h2scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v2_module); > > + > > + if (h2scf->enable || hc->addr_conf->http2) { > > + srv = (unsigned char *) NGX_HTTP_V2_ALPN_PROTO NGX_HTTP_ALPN_PROTOS; > > + srvlen = sizeof(NGX_HTTP_V2_ALPN_PROTO NGX_HTTP_ALPN_PROTOS) - 1; > > + > > + } else > > +#endif > > + { > > + srv = (unsigned char *) NGX_HTTP_ALPN_PROTOS; > > + srvlen = sizeof(NGX_HTTP_ALPN_PROTOS) - 1; > > + } > > } > > > > if (SSL_select_next_proto((unsigned char **) out, outlen, srv, srvlen, > > diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c > > --- a/src/http/ngx_http_core_module.c > > +++ b/src/http/ngx_http_core_module.c > > @@ -4176,6 +4176,11 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx > > > > if (ngx_strcmp(value[n].data, "http2") == 0) { > > #if (NGX_HTTP_V2) > > + ngx_conf_log_error(NGX_LOG_WARN, cf, 0, > > + "the \"listen ... http2\" directive " > > + "is deprecated, use " > > + "the \"http2\" directive instead"); > > + > > lsopt.http2 = 1; > > continue; > > #else > > diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c > > --- a/src/http/ngx_http_request.c > > +++ b/src/http/ngx_http_request.c > > @@ -318,12 +318,6 @@ ngx_http_init_connection(ngx_connection_ > > rev->handler = ngx_http_wait_request_handler; > > c->write->handler = ngx_http_empty_handler; > > > > -#if (NGX_HTTP_V2) > > - if (hc->addr_conf->http2) { > > - rev->handler = ngx_http_v2_init; > > - } > > -#endif > > - > > #if (NGX_HTTP_V3) > > if (hc->addr_conf->quic) { > > ngx_http_v3_init_stream(c); > > @@ -383,6 +377,9 @@ ngx_http_wait_request_handler(ngx_event_ > > ngx_buf_t *b; > > ngx_connection_t *c; > > ngx_http_connection_t *hc; > > +#if (NGX_HTTP_V2) > > + ngx_http_v2_srv_conf_t *h2scf; > > +#endif > > ngx_http_core_srv_conf_t *cscf; > > > > c = rev->data; > > @@ -429,6 +426,8 @@ ngx_http_wait_request_handler(ngx_event_ > > b->end = b->last + size; > > } > > > > + size = b->end - b->last; > > + > > n = c->recv(c, b->last, size); > > > > if (n == NGX_AGAIN) { > > @@ -443,12 +442,16 @@ ngx_http_wait_request_handler(ngx_event_ > > return; > > } > > > > - /* > > - * We are trying to not hold c->buffer's memory for an idle connection. > > - */ > > - > > - if (ngx_pfree(c->pool, b->start) == NGX_OK) { > > - b->start = NULL; > > + if (b->pos == b->last) { > > + > > + /* > > + * We are trying to not hold c->buffer's memory for an > > + * idle connection. > > + */ > > + > > + if (ngx_pfree(c->pool, b->start) == NGX_OK) { > > + b->start = NULL; > > + } > > } > > > > return; > > @@ -489,10 +492,34 @@ ngx_http_wait_request_handler(ngx_event_ > > } > > } > > > > + ngx_reusable_connection(c, 0); > > I don't think it should be moved. > > Non-reusable connections are basically ones with a request > created, so nginx won't try to terminate running requests. This > does not apply to a connection waiting for an HTTP/2 preface. > > It might need to be called in (or just before) ngx_http_v2_init() > though, since HTTP/2 code assumes that the connection is not > reusable by default. OK > > + > > +#if (NGX_HTTP_V2) > > + > > + h2scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v2_module); > > + > > + if (!hc->ssl && (h2scf->enable || hc->addr_conf->http2)) { > > For the record: we might consider introducing a way to explicitly > control "establishment of HTTP/2 connections over cleartext TCP" > (quote from RFC 9113, section 3.3. "Starting HTTP/2 with Prior > Knowledge"), something like "http2_cleartext on|off;". Might not > worth the effort though. Why do you think we need this directive? > > + > > + size = ngx_min(sizeof(NGX_HTTP_V2_PREFACE) - 1, > > + (size_t) (b->last - b->pos)); > > + > > + if (ngx_memcmp(b->pos, NGX_HTTP_V2_PREFACE, size) == 0) { > > + > > + if (size == sizeof(NGX_HTTP_V2_PREFACE) - 1) { > > + ngx_http_v2_init(rev); > > + return; > > + } > > + > > + c->log->action = "waiting for request"; > > Any reasons to change the log action here? > > Note that for proxy_protocol handling above, c->log->action is set > to "reading PROXY protocol", and therefore needs to be reset to > "waiting for request" when PROXY protocol header is fully > processed. This is not the case for HTTP/2 preface though, as it > does not use a special log action. > > Further, in this particular point HTTP/2 preface reading is not > complete, so changing the log action would be wrong if there was > a special log action set. You're right, removed this one. > > + ngx_post_event(rev, &ngx_posted_events); > > + return; > > For the record: as far as I understand, there is no real need to > post an event here, and just adding a timer and calling > ngx_handle_read_event() (much like in case of EAGAIN after recv()) > would be slightly more optimal. I don't object keeping it this > way though, since it's not a hot path, have some chance to > actually read the rest of the preface in the posted event, and > proxy_protocol handling already uses the same approach. > > > + } > > + } > > + > > +#endif > > + > > c->log->action = "reading client request line"; > > > > - ngx_reusable_connection(c, 0); > > - > > c->data = ngx_http_create_request(c); > > if (c->data == NULL) { > > ngx_http_close_connection(c); > > @@ -808,13 +835,16 @@ ngx_http_ssl_handshake_handler(ngx_conne > > #if (NGX_HTTP_V2 \ > > && defined TLSEXT_TYPE_application_layer_protocol_negotiation) > > { > > - unsigned int len; > > - const unsigned char *data; > > - ngx_http_connection_t *hc; > > + unsigned int len; > > + const unsigned char *data; > > + ngx_http_connection_t *hc; > > + ngx_http_v2_srv_conf_t *h2scf; > > > > hc = c->data; > > > > - if (hc->addr_conf->http2) { > > + h2scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v2_module); > > + > > + if (h2scf->enable || hc->addr_conf->http2) { > > > > SSL_get0_alpn_selected(c->ssl->connection, &data, &len); > > > > diff --git a/src/http/v2/ngx_http_v2.c b/src/http/v2/ngx_http_v2.c > > --- a/src/http/v2/ngx_http_v2.c > > +++ b/src/http/v2/ngx_http_v2.c > > @@ -63,8 +63,6 @@ static void ngx_http_v2_handle_connectio > > static void ngx_http_v2_lingering_close(ngx_connection_t *c); > > static void ngx_http_v2_lingering_close_handler(ngx_event_t *rev); > > > > -static u_char *ngx_http_v2_state_proxy_protocol(ngx_http_v2_connection_t *h2c, > > - u_char *pos, u_char *end); > > static u_char *ngx_http_v2_state_preface(ngx_http_v2_connection_t *h2c, > > u_char *pos, u_char *end); > > static u_char *ngx_http_v2_state_preface_end(ngx_http_v2_connection_t *h2c, > > @@ -232,6 +230,7 @@ static ngx_http_v2_parse_header_t ngx_h > > void > > ngx_http_v2_init(ngx_event_t *rev) > > { > > + u_char *p, *end; > > ngx_connection_t *c; > > ngx_pool_cleanup_t *cln; > > ngx_http_connection_t *hc; > > @@ -314,8 +313,7 @@ ngx_http_v2_init(ngx_event_t *rev) > > return; > > } > > > > - h2c->state.handler = hc->proxy_protocol ? ngx_http_v2_state_proxy_protocol > > - : ngx_http_v2_state_preface; > > + h2c->state.handler = ngx_http_v2_state_preface; > > > > ngx_queue_init(&h2c->waiting); > > ngx_queue_init(&h2c->dependencies); > > @@ -333,7 +331,23 @@ ngx_http_v2_init(ngx_event_t *rev) > > } > > > > c->idle = 1; > > - ngx_reusable_connection(c, 0); > > See above. Brought this back along with the above mentioned calls. > > + > > + if (c->buffer) { > > + p = c->buffer->pos; > > + end = c->buffer->last; > > + > > + do { > > + p = h2c->state.handler(h2c, p, end); > > + > > + if (p == NULL) { > > + return; > > + } > > + > > + } while (p != end); > > + > > + h2c->total_bytes += p - c->buffer->pos; > > + c->buffer->pos = p; > > + } > > > > ngx_http_v2_read_handler(rev); > > } > > For the record: it might be better to integrate this into > ngx_http_v2_read_handler(), similarly to how it is done in > ngx_event_pipe_read_upstream(). On the other hand, suggested > approach looks simple enough and might be better. Yes, this would make ngx_http_v2_read_handler() too complex. > Note well: this implies an extra recv() call on each cleartext > HTTP/2 connection establishment. Probably not very important > though. On the other hand, we can consider optimizing out an > extra call if there are space in c->buffer. Why not check rev->ready at the beginning of the loop in ngx_http_v2_read_handler() ? while (rev->ready) { ... } Currently it's checked at the end. > > @@ -847,31 +861,10 @@ ngx_http_v2_lingering_close_handler(ngx_ > > > > > > static u_char * > > -ngx_http_v2_state_proxy_protocol(ngx_http_v2_connection_t *h2c, u_char *pos, > > - u_char *end) > > -{ > > - ngx_log_t *log; > > - > > - log = h2c->connection->log; > > - log->action = "reading PROXY protocol"; > > - > > - pos = ngx_proxy_protocol_read(h2c->connection, pos, end); > > - > > - log->action = "processing HTTP/2 connection"; > > - > > - if (pos == NULL) { > > - return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR); > > - } > > - > > - return ngx_http_v2_state_preface(h2c, pos, end); > > -} > > - > > - > > -static u_char * > > ngx_http_v2_state_preface(ngx_http_v2_connection_t *h2c, u_char *pos, > > u_char *end) > > { > > - static const u_char preface[] = "PRI * HTTP/2.0\r\n"; > > + static const u_char preface[] = NGX_HTTP_V2_PREFACE_START; > > > > if ((size_t) (end - pos) < sizeof(preface) - 1) { > > return ngx_http_v2_state_save(h2c, pos, end, ngx_http_v2_state_preface); > > @@ -892,7 +885,7 @@ static u_char * > > ngx_http_v2_state_preface_end(ngx_http_v2_connection_t *h2c, u_char *pos, > > u_char *end) > > { > > - static const u_char preface[] = "\r\nSM\r\n\r\n"; > > + static const u_char preface[] = NGX_HTTP_V2_PREFACE_END; > > > > if ((size_t) (end - pos) < sizeof(preface) - 1) { > > return ngx_http_v2_state_save(h2c, pos, end, > > @@ -3943,10 +3936,22 @@ static void > > ngx_http_v2_run_request(ngx_http_request_t *r) > > { > > ngx_connection_t *fc; > > + ngx_http_v2_srv_conf_t *h2scf; > > ngx_http_v2_connection_t *h2c; > > > > fc = r->connection; > > > > + h2scf = ngx_http_get_module_srv_conf(r, ngx_http_v2_module); > > + > > + if (!h2scf->enable && !r->http_connection->addr_conf->http2) { > > + ngx_log_error(NGX_LOG_INFO, fc->log, 0, > > + "client attempted to request the server name " > > + "for which the negotiated protocol is disabled"); > > + > > + ngx_http_finalize_request(r, NGX_HTTP_MISDIRECTED_REQUEST); > > + goto failed; > > + } > > + > > if (ngx_http_v2_construct_request_line(r) != NGX_OK) { > > goto failed; > > } > > diff --git a/src/http/v2/ngx_http_v2.h b/src/http/v2/ngx_http_v2.h > > --- a/src/http/v2/ngx_http_v2.h > > +++ b/src/http/v2/ngx_http_v2.h > > @@ -64,6 +64,16 @@ typedef u_char *(*ngx_http_v2_handler_pt > > > > > > typedef struct { > > + ngx_flag_t enable; > > + size_t pool_size; > > + ngx_uint_t concurrent_streams; > > + ngx_uint_t concurrent_pushes; > > + size_t preread_size; > > + ngx_uint_t streams_index_mask; > > +} ngx_http_v2_srv_conf_t; > > + > > + > > +typedef struct { > > ngx_str_t name; > > ngx_str_t value; > > } ngx_http_v2_header_t; > > @@ -408,9 +418,17 @@ ngx_int_t ngx_http_v2_table_size(ngx_htt > > #define NGX_HTTP_V2_USER_AGENT_INDEX 58 > > #define NGX_HTTP_V2_VARY_INDEX 59 > > > > +#define NGX_HTTP_V2_PREFACE_START "PRI * HTTP/2.0\r\n" > > +#define NGX_HTTP_V2_PREFACE_END "\r\nSM\r\n\r\n" > > +#define NGX_HTTP_V2_PREFACE NGX_HTTP_V2_PREFACE_START \ > > + NGX_HTTP_V2_PREFACE_END > > + > > > > u_char *ngx_http_v2_string_encode(u_char *dst, u_char *src, size_t len, > > u_char *tmp, ngx_uint_t lower); > > > > > > +extern ngx_module_t ngx_http_v2_module; > > + > > + > > #endif /* _NGX_HTTP_V2_H_INCLUDED_ */ > > diff --git a/src/http/v2/ngx_http_v2_module.c b/src/http/v2/ngx_http_v2_module.c > > --- a/src/http/v2/ngx_http_v2_module.c > > +++ b/src/http/v2/ngx_http_v2_module.c > > @@ -75,6 +75,13 @@ static ngx_conf_post_t ngx_http_v2_chun > > > > static ngx_command_t ngx_http_v2_commands[] = { > > > > + { ngx_string("http2"), > > + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG, > > + ngx_conf_set_flag_slot, > > + NGX_HTTP_SRV_CONF_OFFSET, > > + offsetof(ngx_http_v2_srv_conf_t, enable), > > + NULL }, > > + > > { ngx_string("http2_recv_buffer_size"), > > NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, > > ngx_conf_set_size_slot, > > @@ -314,6 +321,8 @@ ngx_http_v2_create_srv_conf(ngx_conf_t * > > return NULL; > > } > > > > + h2scf->enable = NGX_CONF_UNSET; > > + > > h2scf->pool_size = NGX_CONF_UNSET_SIZE; > > > > h2scf->concurrent_streams = NGX_CONF_UNSET_UINT; > > @@ -333,6 +342,8 @@ ngx_http_v2_merge_srv_conf(ngx_conf_t *c > > ngx_http_v2_srv_conf_t *prev = parent; > > ngx_http_v2_srv_conf_t *conf = child; > > > > + ngx_conf_merge_value(conf->enable, prev->enable, 0); > > + > > ngx_conf_merge_size_value(conf->pool_size, prev->pool_size, 4096); > > > > ngx_conf_merge_uint_value(conf->concurrent_streams, > > diff --git a/src/http/v2/ngx_http_v2_module.h b/src/http/v2/ngx_http_v2_module.h > > --- a/src/http/v2/ngx_http_v2_module.h > > +++ b/src/http/v2/ngx_http_v2_module.h > > @@ -21,15 +21,6 @@ typedef struct { > > > > > > typedef struct { > > - size_t pool_size; > > - ngx_uint_t concurrent_streams; > > - ngx_uint_t concurrent_pushes; > > - size_t preread_size; > > - ngx_uint_t streams_index_mask; > > -} ngx_http_v2_srv_conf_t; > > - > > - > > -typedef struct { > > size_t chunk_size; > > > > ngx_flag_t push_preload; > > @@ -39,7 +30,4 @@ typedef struct { > > } ngx_http_v2_loc_conf_t; > > > > > > -extern ngx_module_t ngx_http_v2_module; > > - > > - > > #endif /* _NGX_HTTP_V2_MODULE_H_INCLUDED_ */ > > Overall looks good. > > -- > Maxim Dounin > http://mdounin.ru/ > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > https://mailman.nginx.org/mailman/listinfo/nginx-devel -- Roman Arutyunyan -------------- next part -------------- # HG changeset patch # User Roman Arutyunyan # Date 1684240208 -14400 # Tue May 16 16:30:08 2023 +0400 # Node ID 6d3648910d8ea0bf8891670c7b9ea5539a3d39f9 # Parent 564c8f447ea4d76d80251bbf07df412942a2261f HTTP/2: "http2" directive. The directive enables HTTP/2 in the current server. The previous way to enable HTTP/2 via "listen ... http2" is now deprecated. The new approach allows to share HTTP/2 and HTTP/0.9-1.1 on the same port. For SSL connections, HTTP/2 is now selected by ALPN callback based on whether the protocol is enabled in the virtual server chosen by SNI. This however only works since OpenSSL 1.0.2h, where ALPN callback is invoked after SNI callback. For older versions of OpenSSL, HTTP/2 is enabled based on the default virtual server configuration. For plain TCP connections, HTTP/2 is now auto-detected by HTTP/2 preface, if HTTP/2 is enabled in the default virtual server. If preface is not matched, HTTP/0.9-1.1 is assumed. diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c --- a/src/http/modules/ngx_http_ssl_module.c +++ b/src/http/modules/ngx_http_ssl_module.c @@ -421,6 +421,9 @@ ngx_http_ssl_alpn_select(ngx_ssl_conn_t #if (NGX_HTTP_V2 || NGX_HTTP_V3) ngx_http_connection_t *hc; #endif +#if (NGX_HTTP_V2) + ngx_http_v2_srv_conf_t *h2scf; +#endif #if (NGX_HTTP_V3) ngx_http_v3_srv_conf_t *h3scf; #endif @@ -442,12 +445,6 @@ ngx_http_ssl_alpn_select(ngx_ssl_conn_t hc = c->data; #endif -#if (NGX_HTTP_V2) - if (hc->addr_conf->http2) { - srv = (unsigned char *) NGX_HTTP_V2_ALPN_PROTO NGX_HTTP_ALPN_PROTOS; - srvlen = sizeof(NGX_HTTP_V2_ALPN_PROTO NGX_HTTP_ALPN_PROTOS) - 1; - } else -#endif #if (NGX_HTTP_V3) if (hc->addr_conf->quic) { @@ -474,8 +471,19 @@ ngx_http_ssl_alpn_select(ngx_ssl_conn_t } else #endif { - srv = (unsigned char *) NGX_HTTP_ALPN_PROTOS; - srvlen = sizeof(NGX_HTTP_ALPN_PROTOS) - 1; +#if (NGX_HTTP_V2) + h2scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v2_module); + + if (h2scf->enable || hc->addr_conf->http2) { + srv = (unsigned char *) NGX_HTTP_V2_ALPN_PROTO NGX_HTTP_ALPN_PROTOS; + srvlen = sizeof(NGX_HTTP_V2_ALPN_PROTO NGX_HTTP_ALPN_PROTOS) - 1; + + } else +#endif + { + srv = (unsigned char *) NGX_HTTP_ALPN_PROTOS; + srvlen = sizeof(NGX_HTTP_ALPN_PROTOS) - 1; + } } if (SSL_select_next_proto((unsigned char **) out, outlen, srv, srvlen, diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -4176,6 +4176,11 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx if (ngx_strcmp(value[n].data, "http2") == 0) { #if (NGX_HTTP_V2) + ngx_conf_log_error(NGX_LOG_WARN, cf, 0, + "the \"listen ... http2\" directive " + "is deprecated, use " + "the \"http2\" directive instead"); + lsopt.http2 = 1; continue; #else diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -318,12 +318,6 @@ ngx_http_init_connection(ngx_connection_ rev->handler = ngx_http_wait_request_handler; c->write->handler = ngx_http_empty_handler; -#if (NGX_HTTP_V2) - if (hc->addr_conf->http2) { - rev->handler = ngx_http_v2_init; - } -#endif - #if (NGX_HTTP_V3) if (hc->addr_conf->quic) { ngx_http_v3_init_stream(c); @@ -377,6 +371,9 @@ ngx_http_wait_request_handler(ngx_event_ ngx_buf_t *b; ngx_connection_t *c; ngx_http_connection_t *hc; +#if (NGX_HTTP_V2) + ngx_http_v2_srv_conf_t *h2scf; +#endif ngx_http_core_srv_conf_t *cscf; c = rev->data; @@ -423,6 +420,8 @@ ngx_http_wait_request_handler(ngx_event_ b->end = b->last + size; } + size = b->end - b->last; + n = c->recv(c, b->last, size); if (n == NGX_AGAIN) { @@ -437,12 +436,16 @@ ngx_http_wait_request_handler(ngx_event_ return; } - /* - * We are trying to not hold c->buffer's memory for an idle connection. - */ - - if (ngx_pfree(c->pool, b->start) == NGX_OK) { - b->start = NULL; + if (b->pos == b->last) { + + /* + * We are trying to not hold c->buffer's memory for an + * idle connection. + */ + + if (ngx_pfree(c->pool, b->start) == NGX_OK) { + b->start = NULL; + } } return; @@ -483,6 +486,29 @@ ngx_http_wait_request_handler(ngx_event_ } } +#if (NGX_HTTP_V2) + + h2scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v2_module); + + if (!hc->ssl && (h2scf->enable || hc->addr_conf->http2)) { + + size = ngx_min(sizeof(NGX_HTTP_V2_PREFACE) - 1, + (size_t) (b->last - b->pos)); + + if (ngx_memcmp(b->pos, NGX_HTTP_V2_PREFACE, size) == 0) { + + if (size == sizeof(NGX_HTTP_V2_PREFACE) - 1) { + ngx_http_v2_init(rev); + return; + } + + ngx_post_event(rev, &ngx_posted_events); + return; + } + } + +#endif + c->log->action = "reading client request line"; ngx_reusable_connection(c, 0); @@ -802,13 +828,16 @@ ngx_http_ssl_handshake_handler(ngx_conne #if (NGX_HTTP_V2 \ && defined TLSEXT_TYPE_application_layer_protocol_negotiation) { - unsigned int len; - const unsigned char *data; - ngx_http_connection_t *hc; + unsigned int len; + const unsigned char *data; + ngx_http_connection_t *hc; + ngx_http_v2_srv_conf_t *h2scf; hc = c->data; - if (hc->addr_conf->http2) { + h2scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v2_module); + + if (h2scf->enable || hc->addr_conf->http2) { SSL_get0_alpn_selected(c->ssl->connection, &data, &len); diff --git a/src/http/v2/ngx_http_v2.c b/src/http/v2/ngx_http_v2.c --- a/src/http/v2/ngx_http_v2.c +++ b/src/http/v2/ngx_http_v2.c @@ -63,8 +63,6 @@ static void ngx_http_v2_handle_connectio static void ngx_http_v2_lingering_close(ngx_connection_t *c); static void ngx_http_v2_lingering_close_handler(ngx_event_t *rev); -static u_char *ngx_http_v2_state_proxy_protocol(ngx_http_v2_connection_t *h2c, - u_char *pos, u_char *end); static u_char *ngx_http_v2_state_preface(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end); static u_char *ngx_http_v2_state_preface_end(ngx_http_v2_connection_t *h2c, @@ -232,6 +230,7 @@ static ngx_http_v2_parse_header_t ngx_h void ngx_http_v2_init(ngx_event_t *rev) { + u_char *p, *end; ngx_connection_t *c; ngx_pool_cleanup_t *cln; ngx_http_connection_t *hc; @@ -314,8 +313,7 @@ ngx_http_v2_init(ngx_event_t *rev) return; } - h2c->state.handler = hc->proxy_protocol ? ngx_http_v2_state_proxy_protocol - : ngx_http_v2_state_preface; + h2c->state.handler = ngx_http_v2_state_preface; ngx_queue_init(&h2c->waiting); ngx_queue_init(&h2c->dependencies); @@ -335,6 +333,23 @@ ngx_http_v2_init(ngx_event_t *rev) c->idle = 1; ngx_reusable_connection(c, 0); + if (c->buffer) { + p = c->buffer->pos; + end = c->buffer->last; + + do { + p = h2c->state.handler(h2c, p, end); + + if (p == NULL) { + return; + } + + } while (p != end); + + h2c->total_bytes += p - c->buffer->pos; + c->buffer->pos = p; + } + ngx_http_v2_read_handler(rev); } @@ -847,31 +862,10 @@ ngx_http_v2_lingering_close_handler(ngx_ static u_char * -ngx_http_v2_state_proxy_protocol(ngx_http_v2_connection_t *h2c, u_char *pos, - u_char *end) -{ - ngx_log_t *log; - - log = h2c->connection->log; - log->action = "reading PROXY protocol"; - - pos = ngx_proxy_protocol_read(h2c->connection, pos, end); - - log->action = "processing HTTP/2 connection"; - - if (pos == NULL) { - return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR); - } - - return ngx_http_v2_state_preface(h2c, pos, end); -} - - -static u_char * ngx_http_v2_state_preface(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end) { - static const u_char preface[] = "PRI * HTTP/2.0\r\n"; + static const u_char preface[] = NGX_HTTP_V2_PREFACE_START; if ((size_t) (end - pos) < sizeof(preface) - 1) { return ngx_http_v2_state_save(h2c, pos, end, ngx_http_v2_state_preface); @@ -892,7 +886,7 @@ static u_char * ngx_http_v2_state_preface_end(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end) { - static const u_char preface[] = "\r\nSM\r\n\r\n"; + static const u_char preface[] = NGX_HTTP_V2_PREFACE_END; if ((size_t) (end - pos) < sizeof(preface) - 1) { return ngx_http_v2_state_save(h2c, pos, end, @@ -3943,10 +3937,22 @@ static void ngx_http_v2_run_request(ngx_http_request_t *r) { ngx_connection_t *fc; + ngx_http_v2_srv_conf_t *h2scf; ngx_http_v2_connection_t *h2c; fc = r->connection; + h2scf = ngx_http_get_module_srv_conf(r, ngx_http_v2_module); + + if (!h2scf->enable && !r->http_connection->addr_conf->http2) { + ngx_log_error(NGX_LOG_INFO, fc->log, 0, + "client attempted to request the server name " + "for which the negotiated protocol is disabled"); + + ngx_http_finalize_request(r, NGX_HTTP_MISDIRECTED_REQUEST); + goto failed; + } + if (ngx_http_v2_construct_request_line(r) != NGX_OK) { goto failed; } diff --git a/src/http/v2/ngx_http_v2.h b/src/http/v2/ngx_http_v2.h --- a/src/http/v2/ngx_http_v2.h +++ b/src/http/v2/ngx_http_v2.h @@ -64,6 +64,16 @@ typedef u_char *(*ngx_http_v2_handler_pt typedef struct { + ngx_flag_t enable; + size_t pool_size; + ngx_uint_t concurrent_streams; + ngx_uint_t concurrent_pushes; + size_t preread_size; + ngx_uint_t streams_index_mask; +} ngx_http_v2_srv_conf_t; + + +typedef struct { ngx_str_t name; ngx_str_t value; } ngx_http_v2_header_t; @@ -408,9 +418,17 @@ ngx_int_t ngx_http_v2_table_size(ngx_htt #define NGX_HTTP_V2_USER_AGENT_INDEX 58 #define NGX_HTTP_V2_VARY_INDEX 59 +#define NGX_HTTP_V2_PREFACE_START "PRI * HTTP/2.0\r\n" +#define NGX_HTTP_V2_PREFACE_END "\r\nSM\r\n\r\n" +#define NGX_HTTP_V2_PREFACE NGX_HTTP_V2_PREFACE_START \ + NGX_HTTP_V2_PREFACE_END + u_char *ngx_http_v2_string_encode(u_char *dst, u_char *src, size_t len, u_char *tmp, ngx_uint_t lower); +extern ngx_module_t ngx_http_v2_module; + + #endif /* _NGX_HTTP_V2_H_INCLUDED_ */ diff --git a/src/http/v2/ngx_http_v2_module.c b/src/http/v2/ngx_http_v2_module.c --- a/src/http/v2/ngx_http_v2_module.c +++ b/src/http/v2/ngx_http_v2_module.c @@ -75,6 +75,13 @@ static ngx_conf_post_t ngx_http_v2_chun static ngx_command_t ngx_http_v2_commands[] = { + { ngx_string("http2"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_HTTP_SRV_CONF_OFFSET, + offsetof(ngx_http_v2_srv_conf_t, enable), + NULL }, + { ngx_string("http2_recv_buffer_size"), NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, ngx_conf_set_size_slot, @@ -314,6 +321,8 @@ ngx_http_v2_create_srv_conf(ngx_conf_t * return NULL; } + h2scf->enable = NGX_CONF_UNSET; + h2scf->pool_size = NGX_CONF_UNSET_SIZE; h2scf->concurrent_streams = NGX_CONF_UNSET_UINT; @@ -333,6 +342,8 @@ ngx_http_v2_merge_srv_conf(ngx_conf_t *c ngx_http_v2_srv_conf_t *prev = parent; ngx_http_v2_srv_conf_t *conf = child; + ngx_conf_merge_value(conf->enable, prev->enable, 0); + ngx_conf_merge_size_value(conf->pool_size, prev->pool_size, 4096); ngx_conf_merge_uint_value(conf->concurrent_streams, diff --git a/src/http/v2/ngx_http_v2_module.h b/src/http/v2/ngx_http_v2_module.h --- a/src/http/v2/ngx_http_v2_module.h +++ b/src/http/v2/ngx_http_v2_module.h @@ -21,15 +21,6 @@ typedef struct { typedef struct { - size_t pool_size; - ngx_uint_t concurrent_streams; - ngx_uint_t concurrent_pushes; - size_t preread_size; - ngx_uint_t streams_index_mask; -} ngx_http_v2_srv_conf_t; - - -typedef struct { size_t chunk_size; ngx_flag_t push_preload; @@ -39,7 +30,4 @@ typedef struct { } ngx_http_v2_loc_conf_t; -extern ngx_module_t ngx_http_v2_module; - - #endif /* _NGX_HTTP_V2_MODULE_H_INCLUDED_ */ From pluknet at nginx.com Mon Jun 5 15:06:26 2023 From: pluknet at nginx.com (Sergey Kandaurov) Date: Mon, 5 Jun 2023 19:06:26 +0400 Subject: [PATCH] SSL: removed the "ssl" directive In-Reply-To: <564c8f447ea4d76d8025.1685690902@arut-laptop> References: <564c8f447ea4d76d8025.1685690902@arut-laptop> Message-ID: > On 2 Jun 2023, at 11:28, Roman Arutyunyan wrote: > > # HG changeset patch > # User Roman Arutyunyan > # Date 1685447035 -14400 > # Tue May 30 15:43:55 2023 +0400 > # Node ID 564c8f447ea4d76d80251bbf07df412942a2261f > # Parent b4a57278bf24dd28d39afea0eb09732c05bf1606 > SSL: removed the "ssl" directive. > > It has been deprecated since 46c0c7ef4913 (1.15.0); s/;/./ The rest looks fine. > [..] -- Sergey Kandaurov From xeioex at nginx.com Tue Jun 6 01:31:35 2023 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 06 Jun 2023 01:31:35 +0000 Subject: [njs] Tests: fixed js tests for Fetch API for nginx-1.22 and below. Message-ID: details: https://hg.nginx.org/njs/rev/db36e0384d97 branches: changeset: 2146:db36e0384d97 user: Dmitry Volyntsev date: Mon Feb 06 09:36:13 2023 -0800 description: Tests: fixed js tests for Fetch API for nginx-1.22 and below. The fix is to move a test with multiple headers returned by $http_a variable under an nginx version check. diffstat: nginx/t/js_fetch_objects.t | 30 +++++++++++++++++++++++++----- 1 files changed, 25 insertions(+), 5 deletions(-) diffs (67 lines): diff -r d73bfec720b9 -r db36e0384d97 nginx/t/js_fetch_objects.t --- a/nginx/t/js_fetch_objects.t Thu Jun 01 09:39:27 2023 -0700 +++ b/nginx/t/js_fetch_objects.t Mon Feb 06 09:36:13 2023 -0800 @@ -61,6 +61,10 @@ http { js_content test.fetch; } + location /fetch_multi_header { + js_content test.fetch_multi_header; + } + location /method { return 200 $request_method; } @@ -450,13 +454,20 @@ my $p0 = port(8080); var body = await r.text(); return `\${r.url}: \${r.status} \${body}`; }, 'http://127.0.0.1:$p0/body: 201 foo'], - ['request body', async () => { + ]; + + run(r, tests); + } + + async function fetch_multi_header(r) { + const tests = [ + ['request multi header', async () => { var h = new Headers({a: 'X'}); h.append('a', 'Z'); var req = new Request("http://127.0.0.1:$p0/header", {headers: h}); - var r = await ngx.fetch(req); - var body = await r.text(); + var r = await ngx.fetch(req); + var body = await r.text(); return `\${r.url}: \${r.status} \${body}`; }, 'http://127.0.0.1:$p0/header: 200 X, Z'], ]; @@ -464,10 +475,11 @@ my $p0 = port(8080); run(r, tests); } - export default {njs: test_njs, body, headers, request, response, fetch}; + export default {njs: test_njs, body, headers, request, response, fetch, + fetch_multi_header}; EOF -$t->try_run('no njs')->plan(4); +$t->try_run('no njs')->plan(5); ############################################################################### @@ -478,6 +490,14 @@ like(http_get('/request'), qr/200 OK/s, like(http_get('/response'), qr/200 OK/s, 'response tests'); like(http_get('/fetch'), qr/200 OK/s, 'fetch tests'); +TODO: { +local $TODO = 'not yet' unless $t->has_version('1.23.0'); + +like(http_get('/fetch_multi_header'), qr/200 OK/s, + 'fetch multi header tests'); + +} + ############################################################################### sub has_version { From xeioex at nginx.com Tue Jun 6 01:31:37 2023 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 06 Jun 2023 01:31:37 +0000 Subject: [njs] Tests: removed excessive tab characters from js_fetch_objects.t. Message-ID: details: https://hg.nginx.org/njs/rev/5952d7709956 branches: changeset: 2147:5952d7709956 user: Dmitry Volyntsev date: Mon Feb 06 09:36:14 2023 -0800 description: Tests: removed excessive tab characters from js_fetch_objects.t. diffstat: nginx/t/js_fetch_objects.t | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diffs (23 lines): diff -r db36e0384d97 -r 5952d7709956 nginx/t/js_fetch_objects.t --- a/nginx/t/js_fetch_objects.t Mon Feb 06 09:36:13 2023 -0800 +++ b/nginx/t/js_fetch_objects.t Mon Feb 06 09:36:14 2023 -0800 @@ -443,15 +443,15 @@ my $p0 = port(8080); ['method', async () => { var req = new Request("http://127.0.0.1:$p0/method", {method: 'PUT'}); - var r = await ngx.fetch(req); - var body = await r.text(); + var r = await ngx.fetch(req); + var body = await r.text(); return `\${r.url}: \${r.status} \${body} \${r.headers.get('a')}`; }, 'http://127.0.0.1:$p0/method: 200 PUT null'], ['request body', async () => { var req = new Request("http://127.0.0.1:$p0/body", {body: 'foo'}); - var r = await ngx.fetch(req); - var body = await r.text(); + var r = await ngx.fetch(req); + var body = await r.text(); return `\${r.url}: \${r.status} \${body}`; }, 'http://127.0.0.1:$p0/body: 201 foo'], ]; From xeioex at nginx.com Tue Jun 6 01:31:39 2023 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 06 Jun 2023 01:31:39 +0000 Subject: [njs] HTTP: deduplicated special header handlers for nginx <= 1.22. Message-ID: details: https://hg.nginx.org/njs/rev/a5affeb25558 branches: changeset: 2148:a5affeb25558 user: Dmitry Volyntsev date: Mon Jun 05 18:21:06 2023 -0700 description: HTTP: deduplicated special header handlers for nginx <= 1.22. diffstat: nginx/ngx_http_js_module.c | 373 ++++++++++++++++---------------------------- 1 files changed, 140 insertions(+), 233 deletions(-) diffs (441 lines): diff -r 5952d7709956 -r a5affeb25558 nginx/ngx_http_js_module.c --- a/nginx/ngx_http_js_module.c Mon Feb 06 09:36:14 2023 -0800 +++ b/nginx/ngx_http_js_module.c Mon Jun 05 18:21:06 2023 -0700 @@ -116,15 +116,15 @@ static njs_int_t ngx_http_js_header_arra static njs_int_t ngx_http_js_header_generic(njs_vm_t *vm, ngx_http_request_t *r, ngx_list_t *headers, njs_str_t *name, njs_value_t *setval, njs_value_t *retval); -static njs_int_t ngx_http_js_content_length(njs_vm_t *vm, ngx_http_request_t *r, - ngx_list_t *headers, njs_str_t *name, njs_value_t *setval, - njs_value_t *retval); -static njs_int_t ngx_http_js_content_encoding(njs_vm_t *vm, +static njs_int_t ngx_http_js_content_encoding122(njs_vm_t *vm, ngx_http_request_t *r, ngx_list_t *headers, njs_str_t *name, njs_value_t *setval, njs_value_t *retval); -static njs_int_t ngx_http_js_content_type(njs_vm_t *vm, ngx_http_request_t *r, - ngx_list_t *headers, njs_str_t *name, njs_value_t *setval, - njs_value_t *retval); +static njs_int_t ngx_http_js_content_length122(njs_vm_t *vm, + ngx_http_request_t *r, ngx_list_t *headers, njs_str_t *name, + njs_value_t *setval, njs_value_t *retval); +static njs_int_t ngx_http_js_content_type122(njs_vm_t *vm, + ngx_http_request_t *r, ngx_list_t *headers, njs_str_t *name, + njs_value_t *setval, njs_value_t *retval); #endif static njs_int_t ngx_http_js_ext_keys_header_out(njs_vm_t *vm, njs_value_t *value, njs_value_t *keys); @@ -203,6 +203,13 @@ static njs_int_t ngx_http_js_header_in(n unsigned flags, njs_str_t *name, njs_value_t *retval); static njs_int_t ngx_http_js_header_out(njs_vm_t *vm, ngx_http_request_t *r, unsigned flags, njs_str_t *name, njs_value_t *setval, njs_value_t *retval); +static njs_int_t ngx_http_js_header_out_special(njs_vm_t *vm, + ngx_http_request_t *r, njs_str_t *v, njs_value_t *setval, + njs_value_t *retval, ngx_table_elt_t **hh); +static njs_int_t ngx_http_js_header_generic(njs_vm_t *vm, + ngx_http_request_t *r, ngx_list_t *headers, ngx_table_elt_t **ph, + unsigned flags, njs_str_t *name, njs_value_t *retval); +#endif static njs_int_t ngx_http_js_content_encoding(njs_vm_t *vm, ngx_http_request_t *r, unsigned flags, njs_str_t *name, njs_value_t *setval, njs_value_t *retval); @@ -212,13 +219,6 @@ static njs_int_t ngx_http_js_content_len static njs_int_t ngx_http_js_content_type(njs_vm_t *vm, ngx_http_request_t *r, unsigned flags, njs_str_t *name, njs_value_t *setval, njs_value_t *retval); -static njs_int_t ngx_http_js_header_out_special(njs_vm_t *vm, - ngx_http_request_t *r, njs_str_t *v, njs_value_t *setval, - njs_value_t *retval, ngx_table_elt_t **hh); -static njs_int_t ngx_http_js_header_generic(njs_vm_t *vm, - ngx_http_request_t *r, ngx_list_t *headers, ngx_table_elt_t **ph, - unsigned flags, njs_str_t *name, njs_value_t *retval); -#endif static njs_host_event_t ngx_http_js_set_timer(njs_external_ptr_t external, uint64_t delay, njs_vm_event_t vm_event); @@ -1476,9 +1476,9 @@ ngx_http_js_ext_header_out(njs_vm_t *vm, static ngx_http_js_header_t headers_out[] = { #if defined(nginx_version) && (nginx_version < 1023000) { njs_str("Age"), ngx_http_js_header_single }, - { njs_str("Content-Type"), ngx_http_js_content_type }, - { njs_str("Content-Length"), ngx_http_js_content_length }, - { njs_str("Content-Encoding"), ngx_http_js_content_encoding }, + { njs_str("Content-Type"), ngx_http_js_content_type122 }, + { njs_str("Content-Length"), ngx_http_js_content_length122 }, + { njs_str("Content-Encoding"), ngx_http_js_content_encoding122 }, { njs_str("Etag"), ngx_http_js_header_single }, { njs_str("Expires"), ngx_http_js_header_single }, { njs_str("Last-Modified"), ngx_http_js_header_single }, @@ -1884,119 +1884,26 @@ ngx_http_js_header_generic(njs_vm_t *vm, static njs_int_t -ngx_http_js_content_encoding(njs_vm_t *vm, ngx_http_request_t *r, +ngx_http_js_content_encoding122(njs_vm_t *vm, ngx_http_request_t *r, ngx_list_t *headers, njs_str_t *v, njs_value_t *setval, njs_value_t *retval) { - njs_int_t rc; - ngx_table_elt_t *h; - - rc = ngx_http_js_header_out_special(vm, r, v, setval, retval, &h); - if (rc == NJS_ERROR) { - return NJS_ERROR; - } - - if (setval != NULL || retval == NULL) { - r->headers_out.content_encoding = h; - } - - return NJS_OK; + return ngx_http_js_content_encoding(vm, r, 0, v, setval, retval); } static njs_int_t -ngx_http_js_content_length(njs_vm_t *vm, ngx_http_request_t *r, +ngx_http_js_content_length122(njs_vm_t *vm, ngx_http_request_t *r, ngx_list_t *headers, njs_str_t *v, njs_value_t *setval, njs_value_t *retval) { - u_char *p, *start; - njs_int_t rc; - ngx_int_t n; - ngx_table_elt_t *h; - u_char content_len[NGX_OFF_T_LEN]; - - if (retval != NULL && setval == NULL) { - if (r->headers_out.content_length == NULL - && r->headers_out.content_length_n >= 0) - { - p = ngx_sprintf(content_len, "%O", r->headers_out.content_length_n); - - start = njs_vm_value_string_alloc(vm, retval, p - content_len); - if (start == NULL) { - return NJS_ERROR; - } - - ngx_memcpy(start, content_len, p - content_len); - - return NJS_OK; - } - } - - rc = ngx_http_js_header_out_special(vm, r, v, setval, retval, &h); - if (rc == NJS_ERROR) { - return NJS_ERROR; - } - - if (setval != NULL || retval == NULL) { - if (h != NULL) { - n = ngx_atoi(h->value.data, h->value.len); - if (n == NGX_ERROR) { - h->hash = 0; - njs_vm_error(vm, "failed converting argument " - "to positive integer"); - return NJS_ERROR; - } - - r->headers_out.content_length = h; - r->headers_out.content_length_n = n; - - } else { - ngx_http_clear_content_length(r); - } - } - - return NJS_OK; + return ngx_http_js_content_length(vm, r, 0, v, setval, retval); } static njs_int_t -ngx_http_js_content_type(njs_vm_t *vm, ngx_http_request_t *r, +ngx_http_js_content_type122(njs_vm_t *vm, ngx_http_request_t *r, ngx_list_t *headers, njs_str_t *v, njs_value_t *setval, njs_value_t *retval) { - int64_t length; - njs_int_t rc; - njs_str_t s; - ngx_str_t *hdr; - njs_opaque_value_t lvalue; - - if (retval != NULL && setval == NULL) { - hdr = &r->headers_out.content_type; - - if (hdr->len == 0) { - njs_value_undefined_set(retval); - return NJS_OK; - } - - return njs_vm_value_string_set(vm, retval, hdr->data, hdr->len); - } - - if (setval != NULL && njs_value_is_array(setval)) { - rc = njs_vm_array_length(vm, setval, &length); - if (rc != NJS_OK) { - return NJS_ERROR; - } - - setval = njs_vm_array_prop(vm, setval, length - 1, &lvalue); - } - - if (ngx_js_string(vm, setval, &s) != NGX_OK) { - return NJS_ERROR; - } - - r->headers_out.content_type.len = s.length; - r->headers_out.content_type_len = r->headers_out.content_type.len; - r->headers_out.content_type.data = s.start; - r->headers_out.content_type_lowcase = NULL; - - return NJS_OK; + return ngx_http_js_content_type(vm, r, 0, v, setval, retval); } #endif @@ -3659,123 +3566,6 @@ ngx_http_js_header_out(njs_vm_t *vm, ngx static njs_int_t -ngx_http_js_content_encoding(njs_vm_t *vm, ngx_http_request_t *r, - unsigned flags, njs_str_t *v, njs_value_t *setval, njs_value_t *retval) -{ - njs_int_t rc; - ngx_table_elt_t *h; - - rc = ngx_http_js_header_out_special(vm, r, v, setval, retval, &h); - if (rc == NJS_ERROR) { - return NJS_ERROR; - } - - if (setval != NULL || retval == NULL) { - r->headers_out.content_encoding = h; - } - - return NJS_OK; -} - - -static njs_int_t -ngx_http_js_content_length(njs_vm_t *vm, ngx_http_request_t *r, - unsigned flags, njs_str_t *v, njs_value_t *setval, njs_value_t *retval) -{ - u_char *p, *start; - njs_int_t rc; - ngx_int_t n; - ngx_table_elt_t *h; - u_char content_len[NGX_OFF_T_LEN]; - - if (retval != NULL && setval == NULL) { - if (r->headers_out.content_length == NULL - && r->headers_out.content_length_n >= 0) - { - p = ngx_sprintf(content_len, "%O", r->headers_out.content_length_n); - - start = njs_vm_value_string_alloc(vm, retval, p - content_len); - if (start == NULL) { - return NJS_ERROR; - } - - ngx_memcpy(start, content_len, p - content_len); - - return NJS_OK; - } - } - - rc = ngx_http_js_header_out_special(vm, r, v, setval, retval, &h); - if (rc == NJS_ERROR) { - return NJS_ERROR; - } - - if (setval != NULL || retval == NULL) { - if (h != NULL) { - n = ngx_atoi(h->value.data, h->value.len); - if (n == NGX_ERROR) { - h->hash = 0; - njs_vm_error(vm, "failed converting argument " - "to positive integer"); - return NJS_ERROR; - } - - r->headers_out.content_length = h; - r->headers_out.content_length_n = n; - - } else { - ngx_http_clear_content_length(r); - } - } - - return NJS_OK; -} - - -static njs_int_t -ngx_http_js_content_type(njs_vm_t *vm, ngx_http_request_t *r, - unsigned flags, njs_str_t *v, njs_value_t *setval, njs_value_t *retval) -{ - int64_t length; - njs_int_t rc; - njs_str_t s; - ngx_str_t *hdr; - njs_opaque_value_t lvalue; - - if (retval != NULL && setval == NULL) { - hdr = &r->headers_out.content_type; - - if (hdr->len == 0) { - njs_value_undefined_set(retval); - return NJS_OK; - } - - return njs_vm_value_string_set(vm, retval, hdr->data, hdr->len); - } - - if (setval != NULL && njs_value_is_array(setval)) { - rc = njs_vm_array_length(vm, setval, &length); - if (rc != NJS_OK) { - return NJS_ERROR; - } - - setval = njs_vm_array_prop(vm, setval, length - 1, &lvalue); - } - - if (ngx_js_string(vm, setval, &s) != NGX_OK) { - return NJS_ERROR; - } - - r->headers_out.content_type.len = s.length; - r->headers_out.content_type_len = r->headers_out.content_type.len; - r->headers_out.content_type.data = s.start; - r->headers_out.content_type_lowcase = NULL; - - return NJS_OK; -} - - -static njs_int_t ngx_http_js_header_out_special(njs_vm_t *vm, ngx_http_request_t *r, njs_str_t *v, njs_value_t *setval, njs_value_t *retval, ngx_table_elt_t **hh) @@ -3998,6 +3788,123 @@ ngx_http_js_header_generic(njs_vm_t *vm, #endif +static njs_int_t +ngx_http_js_content_encoding(njs_vm_t *vm, ngx_http_request_t *r, + unsigned flags, njs_str_t *v, njs_value_t *setval, njs_value_t *retval) +{ + njs_int_t rc; + ngx_table_elt_t *h; + + rc = ngx_http_js_header_out_special(vm, r, v, setval, retval, &h); + if (rc == NJS_ERROR) { + return NJS_ERROR; + } + + if (setval != NULL || retval == NULL) { + r->headers_out.content_encoding = h; + } + + return NJS_OK; +} + + +static njs_int_t +ngx_http_js_content_length(njs_vm_t *vm, ngx_http_request_t *r, + unsigned flags, njs_str_t *v, njs_value_t *setval, njs_value_t *retval) +{ + u_char *p, *start; + njs_int_t rc; + ngx_int_t n; + ngx_table_elt_t *h; + u_char content_len[NGX_OFF_T_LEN]; + + if (retval != NULL && setval == NULL) { + if (r->headers_out.content_length == NULL + && r->headers_out.content_length_n >= 0) + { + p = ngx_sprintf(content_len, "%O", r->headers_out.content_length_n); + + start = njs_vm_value_string_alloc(vm, retval, p - content_len); + if (start == NULL) { + return NJS_ERROR; + } + + ngx_memcpy(start, content_len, p - content_len); + + return NJS_OK; + } + } + + rc = ngx_http_js_header_out_special(vm, r, v, setval, retval, &h); + if (rc == NJS_ERROR) { + return NJS_ERROR; + } + + if (setval != NULL || retval == NULL) { + if (h != NULL) { + n = ngx_atoi(h->value.data, h->value.len); + if (n == NGX_ERROR) { + h->hash = 0; + njs_vm_error(vm, "failed converting argument " + "to positive integer"); + return NJS_ERROR; + } + + r->headers_out.content_length = h; + r->headers_out.content_length_n = n; + + } else { + ngx_http_clear_content_length(r); + } + } + + return NJS_OK; +} + + +static njs_int_t +ngx_http_js_content_type(njs_vm_t *vm, ngx_http_request_t *r, + unsigned flags, njs_str_t *v, njs_value_t *setval, njs_value_t *retval) +{ + int64_t length; + njs_int_t rc; + njs_str_t s; + ngx_str_t *hdr; + njs_opaque_value_t lvalue; + + if (retval != NULL && setval == NULL) { + hdr = &r->headers_out.content_type; + + if (hdr->len == 0) { + njs_value_undefined_set(retval); + return NJS_OK; + } + + return njs_vm_value_string_set(vm, retval, hdr->data, hdr->len); + } + + if (setval != NULL && njs_value_is_array(setval)) { + rc = njs_vm_array_length(vm, setval, &length); + if (rc != NJS_OK) { + return NJS_ERROR; + } + + setval = njs_vm_array_prop(vm, setval, length - 1, &lvalue); + } + + if (ngx_js_string(vm, setval, &s) != NGX_OK) { + return NJS_ERROR; + } + + r->headers_out.content_type.len = s.length; + r->headers_out.content_type_len = r->headers_out.content_type.len; + r->headers_out.content_type.data = s.start; + r->headers_out.content_type_lowcase = NULL; + + return NJS_OK; +} + + static njs_host_event_t ngx_http_js_set_timer(njs_external_ptr_t external, uint64_t delay, njs_vm_event_t vm_event) From xeioex at nginx.com Tue Jun 6 01:31:41 2023 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 06 Jun 2023 01:31:41 +0000 Subject: [njs] HTTP: fixed setting of Location header. Message-ID: details: https://hg.nginx.org/njs/rev/f357972b28e3 branches: changeset: 2149:f357972b28e3 user: Dmitry Volyntsev date: Mon Jun 05 18:21:06 2023 -0700 description: HTTP: fixed setting of Location header. Previously, r.headersOut['Location'] setter did not update r->headers_out.location. As a result a client might get two Location headers. This fixes #648 issue on Github. diffstat: nginx/ngx_http_js_module.c | 38 ++++++++++++++++++++++++++++++++++- nginx/t/js_headers.t | 48 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 82 insertions(+), 4 deletions(-) diffs (166 lines): diff -r a5affeb25558 -r f357972b28e3 nginx/ngx_http_js_module.c --- a/nginx/ngx_http_js_module.c Mon Jun 05 18:21:06 2023 -0700 +++ b/nginx/ngx_http_js_module.c Mon Jun 05 18:21:06 2023 -0700 @@ -125,6 +125,9 @@ static njs_int_t ngx_http_js_content_len static njs_int_t ngx_http_js_content_type122(njs_vm_t *vm, ngx_http_request_t *r, ngx_list_t *headers, njs_str_t *name, njs_value_t *setval, njs_value_t *retval); +static njs_int_t ngx_http_js_location122(njs_vm_t *vm, ngx_http_request_t *r, + ngx_list_t *headers, njs_str_t *name, njs_value_t *setval, + njs_value_t *retval); #endif static njs_int_t ngx_http_js_ext_keys_header_out(njs_vm_t *vm, njs_value_t *value, njs_value_t *keys); @@ -219,6 +222,9 @@ static njs_int_t ngx_http_js_content_len static njs_int_t ngx_http_js_content_type(njs_vm_t *vm, ngx_http_request_t *r, unsigned flags, njs_str_t *name, njs_value_t *setval, njs_value_t *retval); +static njs_int_t ngx_http_js_location(njs_vm_t *vm, ngx_http_request_t *r, + unsigned flags, njs_str_t *name, njs_value_t *setval, + njs_value_t *retval); static njs_host_event_t ngx_http_js_set_timer(njs_external_ptr_t external, uint64_t delay, njs_vm_event_t vm_event); @@ -1482,7 +1488,7 @@ ngx_http_js_ext_header_out(njs_vm_t *vm, { njs_str("Etag"), ngx_http_js_header_single }, { njs_str("Expires"), ngx_http_js_header_single }, { njs_str("Last-Modified"), ngx_http_js_header_single }, - { njs_str("Location"), ngx_http_js_header_single }, + { njs_str("Location"), ngx_http_js_location122 }, { njs_str("Set-Cookie"), ngx_http_js_header_array }, { njs_str("Retry-After"), ngx_http_js_header_single }, { njs_str(""), ngx_http_js_header_generic }, @@ -1494,7 +1500,7 @@ ngx_http_js_ext_header_out(njs_vm_t *vm, { njs_str("Etag"), NJS_HEADER_SINGLE, ngx_http_js_header_out }, { njs_str("Expires"), NJS_HEADER_SINGLE, ngx_http_js_header_out }, { njs_str("Last-Modified"), NJS_HEADER_SINGLE, ngx_http_js_header_out }, - { njs_str("Location"), NJS_HEADER_SINGLE, ngx_http_js_header_out }, + { njs_str("Location"), 0, ngx_http_js_location }, { njs_str("Set-Cookie"), NJS_HEADER_ARRAY, ngx_http_js_header_out }, { njs_str("Retry-After"), NJS_HEADER_SINGLE, ngx_http_js_header_out }, { njs_str(""), 0, ngx_http_js_header_out }, @@ -1905,6 +1911,14 @@ ngx_http_js_content_type122(njs_vm_t *vm { return ngx_http_js_content_type(vm, r, 0, v, setval, retval); } + + +static njs_int_t +ngx_http_js_location122(njs_vm_t *vm, ngx_http_request_t *r, + ngx_list_t *headers, njs_str_t *v, njs_value_t *setval, njs_value_t *retval) +{ + return ngx_http_js_location(vm, r, 0, v, setval, retval); +} #endif @@ -3905,6 +3919,26 @@ ngx_http_js_content_type(njs_vm_t *vm, n } +static njs_int_t +ngx_http_js_location(njs_vm_t *vm, ngx_http_request_t *r, unsigned flags, + njs_str_t *v, njs_value_t *setval, njs_value_t *retval) +{ + njs_int_t rc; + ngx_table_elt_t *h; + + rc = ngx_http_js_header_out_special(vm, r, v, setval, retval, &h); + if (rc == NJS_ERROR) { + return NJS_ERROR; + } + + if (setval != NULL || retval == NULL) { + r->headers_out.location = h; + } + + return NJS_OK; +} + + static njs_host_event_t ngx_http_js_set_timer(njs_external_ptr_t external, uint64_t delay, njs_vm_event_t vm_event) diff -r a5affeb25558 -r f357972b28e3 nginx/t/js_headers.t --- a/nginx/t/js_headers.t Mon Jun 05 18:21:06 2023 -0700 +++ b/nginx/t/js_headers.t Mon Jun 05 18:21:06 2023 -0700 @@ -84,6 +84,18 @@ http { js_content test.content_encoding_arr; } + location /location { + js_content test.location; + } + + location /location_sr { + js_content test.location_sr; + } + + location /_redirect { + return 307 $request_uri; + } + location /headers_list { js_content test.headers_list; } @@ -233,6 +245,29 @@ EOF r.return(200); } + function location(r) { + if (njs.version_number >= 0x000705) { + var lc = r.headersOut['Location']; + if (lc !== undefined) { + r.return(500, `Location "\${lc}" is not empty`); + return; + } + } + + delete r.headersOut['Location']; + r.headersOut['Location'] = ''; + r.headersOut['Location'] = 'test'; + delete r.headersOut['Location']; + r.headersOut['Location'] = 'loc'; + r.return(200); + } + + async function location_sr(r) { + let resp = await r.subrequest('/_redirect'); + r.headersOut['Location'] = resp.headersOut['Location']; + r.return(resp.status, 'loc'); + } + function content_encoding_arr(r) { r.headersOut['Content-Encoding'] = 'test'; r.headersOut['Content-Encoding'] = []; @@ -402,12 +437,12 @@ EOF hdr_in, raw_hdr_in, hdr_sorted_keys, foo_in, ifoo_in, hdr_out, raw_hdr_out, hdr_out_array, hdr_out_single, hdr_out_set_cookie, ihdr_out, hdr_out_special_set, - copy_subrequest_hdrs, subrequest}; + copy_subrequest_hdrs, subrequest, location, location_sr}; EOF -$t->try_run('no njs')->plan(42); +$t->try_run('no njs')->plan(44); ############################################################################### @@ -546,6 +581,15 @@ like(http_get('/copy_subrequest_hdrs'), } +TODO: { +local $TODO = 'not yet' unless has_version('0.8.0'); + +like(http_get('/location'), qr/Location: loc/, 'set location'); +unlike(http_get('/location_sr'), qr/Location: \/location_sr/, + 'location redirect'); + +} + ############################################################################### sub has_version { From xeioex at nginx.com Tue Jun 6 01:31:43 2023 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 06 Jun 2023 01:31:43 +0000 Subject: [njs] Types: fixed typos. Message-ID: details: https://hg.nginx.org/njs/rev/92678163754a branches: changeset: 2150:92678163754a user: Dmitry Volyntsev date: Mon Jun 05 18:21:07 2023 -0700 description: Types: fixed typos. diffstat: ts/ngx_core.d.ts | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diffs (21 lines): diff -r f357972b28e3 -r 92678163754a ts/ngx_core.d.ts --- a/ts/ngx_core.d.ts Mon Jun 05 18:21:06 2023 -0700 +++ b/ts/ngx_core.d.ts Mon Jun 05 18:21:07 2023 -0700 @@ -102,7 +102,7 @@ declare class Request { * Request constructors. * * @param init is an optional initialization object. - * @returns returns Headers object. + * @returns returns Request object. * @since 0.7.10 */ constructor(input: NjsStringLike | Request, options?: NgxRequestOptions); @@ -162,7 +162,7 @@ declare class Response { * Response constructors. * * @param init is an optional initialization object. - * @returns returns Headers object. + * @returns returns Response object. * @since 0.7.10 */ constructor(body?: NjsStringLike, options?: NgxResponseOptions); From pluknet at nginx.com Tue Jun 6 16:29:07 2023 From: pluknet at nginx.com (Sergey Kandaurov) Date: Tue, 6 Jun 2023 20:29:07 +0400 Subject: [PATCH] HTTP/2: removed server push In-Reply-To: References: Message-ID: <7816CF05-E4E3-412E-900A-358031E1016A@nginx.com> > On 4 Jun 2023, at 06:20, Maxim Dounin wrote: > > Hello! > > On Thu, Jun 01, 2023 at 05:58:38AM +0400, Sergey Kandaurov wrote: > >> # HG changeset patch >> # User Sergey Kandaurov >> # Date 1685584419 -14400 >> # Thu Jun 01 05:53:39 2023 +0400 >> # Node ID cd90a7bed6ebb098efe1e82b7ffa067e5f0e56c1 >> # Parent 79ed88b1bf961a19b1efccd058fae440c3acbbdc >> HTTP/2: removed server push. >> >> Although it has better implementation status than HTTP/3 server push, >> it remains of limited use, with adoption numbers seen as negligible. >> Per IETF 102 materials, server push was used only in 0.04% of sessions. >> It was considered to be "difficult to use effectively" in RFC 9113. >> Its use is further limited by badly matching to fetch/cache/connection >> models in browsers, see related discussions linked from [1]. >> >> Server push was disabled in Chrome 106 [2]. >> >> The http2_push, http2_push_preload, and http2_max_concurrent_pushes >> directives are made obsolete. >> >> [1] https://jakearchibald.com/2017/h2-push-tougher-than-i-thought/ >> [2] https://chromestatus.com/feature/6302414934114304 > > It might make sense to mention ticket #2432. > > It might also make sense to mention changesets essentially > reverted, notably 7201:641306096f5b and 7207:3d2b0b02bd3d. Applied, thanks. > >> >> diff --git a/src/http/v2/ngx_http_v2.c b/src/http/v2/ngx_http_v2.c >> --- a/src/http/v2/ngx_http_v2.c >> +++ b/src/http/v2/ngx_http_v2.c >> @@ -11,14 +11,6 @@ >> #include >> >> >> -typedef struct { >> - ngx_str_t name; >> - ngx_uint_t offset; >> - ngx_uint_t hash; >> - ngx_http_header_t *hh; >> -} ngx_http_v2_parse_header_t; >> - >> - >> /* errors */ > > Looking into 7207:3d2b0b02bd3d, where this chunk of code was > originally introduced, suggests that NGX_HTTP_HEADERS can be > removed from the relevant if in auto/modules. > > And the same applies to HTTP/3 case as well. Removed in both places. > >> #define NGX_HTTP_V2_NO_ERROR 0x0 >> #define NGX_HTTP_V2_PROTOCOL_ERROR 0x1 >> @@ -126,7 +118,7 @@ static ngx_int_t ngx_http_v2_parse_int(n >> u_char **pos, u_char *end, ngx_uint_t prefix); >> >> static ngx_http_v2_stream_t *ngx_http_v2_create_stream( >> - ngx_http_v2_connection_t *h2c, ngx_uint_t push); >> + ngx_http_v2_connection_t *h2c); >> static ngx_http_v2_node_t *ngx_http_v2_get_node_by_id( >> ngx_http_v2_connection_t *h2c, ngx_uint_t sid, ngx_uint_t alloc); >> static ngx_http_v2_node_t *ngx_http_v2_get_closed_node( >> @@ -162,14 +154,11 @@ static ngx_int_t ngx_http_v2_parse_schem >> ngx_str_t *value); >> static ngx_int_t ngx_http_v2_parse_authority(ngx_http_request_t *r, >> ngx_str_t *value); >> -static ngx_int_t ngx_http_v2_parse_header(ngx_http_request_t *r, >> - ngx_http_v2_parse_header_t *header, ngx_str_t *value); >> static ngx_int_t ngx_http_v2_construct_request_line(ngx_http_request_t *r); >> static ngx_int_t ngx_http_v2_cookie(ngx_http_request_t *r, >> ngx_http_v2_header_t *header); >> static ngx_int_t ngx_http_v2_construct_cookie_header(ngx_http_request_t *r); >> static void ngx_http_v2_run_request(ngx_http_request_t *r); >> -static void ngx_http_v2_run_request_handler(ngx_event_t *ev); >> static ngx_int_t ngx_http_v2_process_request_body(ngx_http_request_t *r, >> u_char *pos, size_t size, ngx_uint_t last, ngx_uint_t flush); >> static ngx_int_t ngx_http_v2_filter_request_body(ngx_http_request_t *r); >> @@ -210,23 +199,6 @@ static ngx_http_v2_handler_pt ngx_http_v >> (sizeof(ngx_http_v2_frame_states) / sizeof(ngx_http_v2_handler_pt)) >> >> >> -static ngx_http_v2_parse_header_t ngx_http_v2_parse_headers[] = { >> - { ngx_string("host"), >> - offsetof(ngx_http_headers_in_t, host), 0, NULL }, >> - >> - { ngx_string("accept-encoding"), >> - offsetof(ngx_http_headers_in_t, accept_encoding), 0, NULL }, >> - >> - { ngx_string("accept-language"), >> - offsetof(ngx_http_headers_in_t, accept_language), 0, NULL }, >> - >> - { ngx_string("user-agent"), >> - offsetof(ngx_http_headers_in_t, user_agent), 0, NULL }, >> - >> - { ngx_null_string, 0, 0, NULL } >> -}; >> - >> - >> void >> ngx_http_v2_init(ngx_event_t *rev) >> { >> @@ -275,7 +247,6 @@ ngx_http_v2_init(ngx_event_t *rev) >> >> h2scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v2_module); >> >> - h2c->concurrent_pushes = h2scf->concurrent_pushes; >> h2c->priority_limit = ngx_max(h2scf->concurrent_streams, 100); >> >> h2c->pool = ngx_create_pool(h2scf->pool_size, h2c->connection->log); >> @@ -384,7 +355,7 @@ ngx_http_v2_read_handler(ngx_event_t *re >> return; >> } >> >> - if (!h2c->processing && !h2c->pushing) { >> + if (!h2c->processing) { >> ngx_http_v2_finalize_connection(h2c, NGX_HTTP_V2_NO_ERROR); >> return; >> } >> @@ -427,8 +398,7 @@ ngx_http_v2_read_handler(ngx_event_t *re >> break; >> } >> >> - if (n == 0 >> - && (h2c->state.incomplete || h2c->processing || h2c->pushing)) >> + if (n == 0 && (h2c->state.incomplete || h2c->processing)) >> { >> ngx_log_error(NGX_LOG_INFO, c->log, 0, >> "client prematurely closed connection"); > > Nitpicking: "{" should be on the same line with "if" (and that's > how it was before 7201:641306096f5b). Indeed, that was an unfinished change, fixed. > >> @@ -652,7 +622,7 @@ ngx_http_v2_handle_connection(ngx_http_v >> ngx_connection_t *c; >> ngx_http_core_loc_conf_t *clcf; >> >> - if (h2c->last_out || h2c->processing || h2c->pushing) { >> + if (h2c->last_out || h2c->processing) { >> return; >> } >> >> @@ -1337,7 +1307,7 @@ ngx_http_v2_state_headers(ngx_http_v2_co >> h2c->closed_nodes--; >> } >> >> - stream = ngx_http_v2_create_stream(h2c, 0); >> + stream = ngx_http_v2_create_stream(h2c); >> if (stream == NULL) { >> return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR); >> } > > In 7201:641306096f5b, NGX_HTTP_V2_REFUSED_STREAM handling was > added to ngx_http_v2_state_rst_stream(): > > @@ -1909,6 +1913,11 @@ ngx_http_v2_state_rst_stream(ngx_http_v2 > "client canceled stream %ui", h2c->state.sid); > break; > > + case NGX_HTTP_V2_REFUSED_STREAM: > + ngx_log_error(NGX_LOG_INFO, fc->log, 0, > + "client refused stream %ui", h2c->state.sid); > + break; > + > case NGX_HTTP_V2_INTERNAL_ERROR: > ngx_log_error(NGX_LOG_INFO, fc->log, 0, > "client terminated stream %ui due to internal error", > > It does not seem to make any sense now, shouldn't it be removed as > well? Well, it served little to no sense before. This case is used to make distinguished logging for REFUSED_STREAM, which is not closely related to server push being removed. RFC 9113, 8.7 gives the following explanation: : The REFUSED_STREAM error code can be included in a RST_STREAM : frame to indicate that the stream is being closed prior to any : processing having occurred. Any request that was sent on the reset : stream can be safely retried. That's why I refrained from removing this chunk as something related. Though, in 8.4.2, REFUSED_STREAM is specified to cancel pushed responses, and no other use-cases applicable seems to be related to client's usage. So indeed it looks to be fine to be removed as well, applied. > >> @@ -2198,7 +2168,6 @@ ngx_http_v2_state_settings_params(ngx_ht >> { >> ssize_t window_delta; >> ngx_uint_t id, value; >> - ngx_http_v2_srv_conf_t *h2scf; >> ngx_http_v2_out_frame_t *frame; >> >> window_delta = 0; >> @@ -2260,14 +2229,6 @@ ngx_http_v2_state_settings_params(ngx_ht >> NGX_HTTP_V2_PROTOCOL_ERROR); >> } >> >> - h2c->push_disabled = !value; >> - break; >> - >> - case NGX_HTTP_V2_MAX_STREAMS_SETTING: >> - h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx, >> - ngx_http_v2_module); >> - >> - h2c->concurrent_pushes = ngx_min(value, h2scf->concurrent_pushes); >> break; >> >> case NGX_HTTP_V2_HEADER_TABLE_SIZE_SETTING: > > Any specific reasons to keep NGX_HTTP_V2_ENABLE_PUSH_SETTING > handling? Note that here remains a degenerate handling, used to reject invalid values for SETTINGS_ENABLE_PUSH. IMHO, it makes sense to keep it, since "Any value other than 0 or 1 MUST be treated as a connection error". > >> @@ -2722,163 +2683,6 @@ ngx_http_v2_parse_int(ngx_http_v2_connec >> } >> >> >> -ngx_http_v2_stream_t * >> -ngx_http_v2_push_stream(ngx_http_v2_stream_t *parent, ngx_str_t *path) >> -{ >> - ngx_int_t rc; >> - ngx_str_t value; >> - ngx_pool_t *pool; >> - ngx_uint_t index; >> - ngx_table_elt_t **h; >> - ngx_connection_t *fc; >> - ngx_http_request_t *r; >> - ngx_http_v2_node_t *node; >> - ngx_http_v2_stream_t *stream; >> - ngx_http_v2_srv_conf_t *h2scf; >> - ngx_http_v2_connection_t *h2c; >> - ngx_http_v2_parse_header_t *header; >> - >> - h2c = parent->connection; >> - >> - pool = ngx_create_pool(1024, h2c->connection->log); >> - if (pool == NULL) { >> - goto rst_stream; >> - } >> - >> - node = ngx_http_v2_get_node_by_id(h2c, h2c->last_push, 1); >> - >> - if (node == NULL) { >> - ngx_destroy_pool(pool); >> - goto rst_stream; >> - } >> - >> - stream = ngx_http_v2_create_stream(h2c, 1); >> - if (stream == NULL) { >> - >> - if (node->parent == NULL) { >> - h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx, >> - ngx_http_v2_module); >> - >> - index = ngx_http_v2_index(h2scf, h2c->last_push); >> - h2c->streams_index[index] = node->index; >> - >> - ngx_queue_insert_tail(&h2c->closed, &node->reuse); >> - h2c->closed_nodes++; >> - } >> - >> - ngx_destroy_pool(pool); >> - goto rst_stream; >> - } >> - >> - if (node->parent) { >> - ngx_queue_remove(&node->reuse); >> - h2c->closed_nodes--; >> - } >> - >> - stream->pool = pool; >> - >> - r = stream->request; >> - fc = r->connection; >> - >> - stream->in_closed = 1; >> - stream->node = node; >> - >> - node->stream = stream; >> - >> - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, >> - "http2 push stream sid:%ui " >> - "depends on %ui excl:0 weight:16", >> - h2c->last_push, parent->node->id); >> - >> - node->weight = NGX_HTTP_V2_DEFAULT_WEIGHT; >> - ngx_http_v2_set_dependency(h2c, node, parent->node->id, 0); >> - >> - r->method_name = ngx_http_core_get_method; >> - r->method = NGX_HTTP_GET; >> - >> - r->schema.data = ngx_pstrdup(pool, &parent->request->schema); >> - if (r->schema.data == NULL) { >> - goto close; >> - } >> - >> - r->schema.len = parent->request->schema.len; >> - >> - value.data = ngx_pstrdup(pool, path); >> - if (value.data == NULL) { >> - goto close; >> - } >> - >> - value.len = path->len; >> - >> - rc = ngx_http_v2_parse_path(r, &value); >> - >> - if (rc != NGX_OK) { >> - goto error; >> - } >> - >> - for (header = ngx_http_v2_parse_headers; header->name.len; header++) { >> - h = (ngx_table_elt_t **) >> - ((char *) &parent->request->headers_in + header->offset); >> - >> - if (*h == NULL) { >> - continue; >> - } >> - >> - value.len = (*h)->value.len; >> - >> - value.data = ngx_pnalloc(pool, value.len + 1); >> - if (value.data == NULL) { >> - goto close; >> - } >> - >> - ngx_memcpy(value.data, (*h)->value.data, value.len); >> - value.data[value.len] = '\0'; >> - >> - rc = ngx_http_v2_parse_header(r, header, &value); >> - >> - if (rc != NGX_OK) { >> - goto error; >> - } >> - } >> - >> - fc->write->handler = ngx_http_v2_run_request_handler; >> - ngx_post_event(fc->write, &ngx_posted_events); >> - >> - return stream; >> - >> -error: >> - >> - if (rc == NGX_ABORT) { >> - /* header handler has already finalized request */ >> - ngx_http_run_posted_requests(fc); >> - return NULL; >> - } >> - >> - if (rc == NGX_DECLINED) { >> - ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); >> - ngx_http_run_posted_requests(fc); >> - return NULL; >> - } >> - >> -close: >> - >> - ngx_http_v2_close_stream(stream, NGX_HTTP_INTERNAL_SERVER_ERROR); >> - >> - return NULL; >> - >> -rst_stream: >> - >> - if (ngx_http_v2_send_rst_stream(h2c, h2c->last_push, >> - NGX_HTTP_INTERNAL_SERVER_ERROR) >> - != NGX_OK) >> - { >> - h2c->connection->error = 1; >> - } >> - >> - return NULL; >> -} >> - >> - >> static ngx_int_t >> ngx_http_v2_send_settings(ngx_http_v2_connection_t *h2c) >> { >> @@ -3150,7 +2954,7 @@ ngx_http_v2_frame_handler(ngx_http_v2_co >> >> >> static ngx_http_v2_stream_t * >> -ngx_http_v2_create_stream(ngx_http_v2_connection_t *h2c, ngx_uint_t push) >> +ngx_http_v2_create_stream(ngx_http_v2_connection_t *h2c) >> { >> ngx_log_t *log; >> ngx_event_t *rev, *wev; >> @@ -3205,13 +3009,7 @@ ngx_http_v2_create_stream(ngx_http_v2_co >> ngx_memcpy(log, h2c->connection->log, sizeof(ngx_log_t)); >> >> log->data = ctx; >> - >> - if (push) { >> - log->action = "processing pushed request headers"; >> - >> - } else { >> - log->action = "reading client request headers"; >> - } >> + log->action = "reading client request headers"; >> >> ngx_memzero(rev, sizeof(ngx_event_t)); >> >> @@ -3283,12 +3081,7 @@ ngx_http_v2_create_stream(ngx_http_v2_co >> stream->send_window = h2c->init_window; >> stream->recv_window = h2scf->preread_size; >> >> - if (push) { >> - h2c->pushing++; >> - >> - } else { >> - h2c->processing++; >> - } >> + h2c->processing++; >> >> h2c->priority_limit += h2scf->concurrent_streams; >> >> @@ -3711,45 +3504,40 @@ ngx_http_v2_parse_scheme(ngx_http_reques >> static ngx_int_t >> ngx_http_v2_parse_authority(ngx_http_request_t *r, ngx_str_t *value) >> { >> - return ngx_http_v2_parse_header(r, &ngx_http_v2_parse_headers[0], value); >> -} >> - >> - >> -static ngx_int_t >> -ngx_http_v2_parse_header(ngx_http_request_t *r, >> - ngx_http_v2_parse_header_t *header, ngx_str_t *value) >> -{ >> ngx_table_elt_t *h; >> + ngx_http_header_t *hh; >> ngx_http_core_main_conf_t *cmcf; >> >> + static ngx_str_t host = ngx_string("host"); >> + >> h = ngx_list_push(&r->headers_in.headers); >> if (h == NULL) { >> return NGX_ERROR; >> } >> >> - h->key.len = header->name.len; >> - h->key.data = header->name.data; >> - h->lowcase_key = header->name.data; >> - >> - if (header->hh == NULL) { >> - header->hash = ngx_hash_key(header->name.data, header->name.len); >> - >> - cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); >> - >> - header->hh = ngx_hash_find(&cmcf->headers_in_hash, header->hash, >> - h->lowcase_key, h->key.len); >> - if (header->hh == NULL) { >> - return NGX_ERROR; >> - } >> - } >> - >> - h->hash = header->hash; >> + h->key.len = host.len; >> + h->key.data = host.data; >> + h->lowcase_key = host.data; >> + >> + h->hash = ngx_hash(ngx_hash(ngx_hash('h', 'o'), 's'), 't'); >> > > For the record: order of h->key/h->lowcase_key/h->hash assignments > differs from the one used before 7207:3d2b0b02bd3d, but this is > not important, and I agree that the new order is better. Yep, it uses to preserve the order, not revert to pre-3d2b0b02bd3d. Well, it can be rearranged to be consistent with the current order of assignments in ngx_http_v2_construct_cookie_header(): diff --git a/src/http/v2/ngx_http_v2.c b/src/http/v2/ngx_http_v2.c --- a/src/http/v2/ngx_http_v2.c +++ b/src/http/v2/ngx_http_v2.c @@ -3509,15 +3509,16 @@ ngx_http_v2_parse_authority(ngx_http_req return NGX_ERROR; } + h->hash = ngx_hash(ngx_hash(ngx_hash('h', 'o'), 's'), 't'); + h->key.len = host.len; h->key.data = host.data; - h->lowcase_key = host.data; - - h->hash = ngx_hash(ngx_hash(ngx_hash('h', 'o'), 's'), 't'); h->value.len = value->len; h->value.data = value->data; + h->lowcase_key = host.data; + cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); hh = ngx_hash_find(&cmcf->headers_in_hash, h->hash, (just in case, not applied) > >> h->value.len = value->len; >> h->value.data = value->data; >> >> - if (header->hh->handler(r, h, header->hh->offset) != NGX_OK) { >> - /* header handler has already finalized request */ >> + cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); >> + >> + hh = ngx_hash_find(&cmcf->headers_in_hash, h->hash, >> + h->lowcase_key, h->key.len); >> + >> + if (hh == NULL) { >> + return NGX_ERROR; >> + } >> + >> + if (hh->handler(r, h, hh->offset) != NGX_OK) { >> + /* >> + * request has been finalized already >> + * in ngx_http_process_host() >> + */ >> return NGX_ABORT; >> } >> [..] >> diff --git a/src/http/v2/ngx_http_v2_module.c b/src/http/v2/ngx_http_v2_module.c >> --- a/src/http/v2/ngx_http_v2_module.c >> +++ b/src/http/v2/ngx_http_v2_module.c >> @@ -27,8 +27,6 @@ static void *ngx_http_v2_create_loc_conf >> static char *ngx_http_v2_merge_loc_conf(ngx_conf_t *cf, void *parent, >> void *child); >> >> -static char *ngx_http_v2_push(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); >> - >> static char *ngx_http_v2_recv_buffer_size(ngx_conf_t *cf, void *post, >> void *data); >> static char *ngx_http_v2_pool_size(ngx_conf_t *cf, void *post, void *data); >> @@ -38,6 +36,8 @@ static char *ngx_http_v2_streams_index_m >> static char *ngx_http_v2_chunk_size(ngx_conf_t *cf, void *post, void *data); >> static char *ngx_http_v2_obsolete(ngx_conf_t *cf, ngx_command_t *cmd, >> void *conf); >> +static char *ngx_http_v2_obsolete_push(ngx_conf_t *cf, ngx_command_t *cmd, >> + void *conf); >> >> >> static ngx_conf_deprecated_t ngx_http_v2_recv_timeout_deprecated = { >> @@ -105,9 +105,9 @@ static ngx_command_t ngx_http_v2_comman >> >> { ngx_string("http2_max_concurrent_pushes"), >> NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, >> - ngx_conf_set_num_slot, >> - NGX_HTTP_SRV_CONF_OFFSET, >> - offsetof(ngx_http_v2_srv_conf_t, concurrent_pushes), >> + ngx_http_v2_obsolete_push, >> + 0, >> + 0, >> NULL }, >> >> { ngx_string("http2_max_requests"), >> @@ -168,15 +168,15 @@ static ngx_command_t ngx_http_v2_comman >> >> { ngx_string("http2_push_preload"), >> NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, >> - ngx_conf_set_flag_slot, >> - NGX_HTTP_LOC_CONF_OFFSET, >> - offsetof(ngx_http_v2_loc_conf_t, push_preload), >> + ngx_http_v2_obsolete_push, >> + 0, >> + 0, >> NULL }, >> >> { ngx_string("http2_push"), >> NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, >> - ngx_http_v2_push, >> - NGX_HTTP_LOC_CONF_OFFSET, >> + ngx_http_v2_obsolete_push, >> + 0, >> 0, >> NULL }, >> > > Using ngx_http_v2_obsolete() might be better, see below. Agree, it doesn't look nice to deserve a separate function. > >> @@ -326,7 +326,6 @@ ngx_http_v2_create_srv_conf(ngx_conf_t * >> h2scf->pool_size = NGX_CONF_UNSET_SIZE; >> >> h2scf->concurrent_streams = NGX_CONF_UNSET_UINT; >> - h2scf->concurrent_pushes = NGX_CONF_UNSET_UINT; >> >> h2scf->preread_size = NGX_CONF_UNSET_SIZE; >> >> @@ -348,8 +347,6 @@ ngx_http_v2_merge_srv_conf(ngx_conf_t *c >> >> ngx_conf_merge_uint_value(conf->concurrent_streams, >> prev->concurrent_streams, 128); >> - ngx_conf_merge_uint_value(conf->concurrent_pushes, >> - prev->concurrent_pushes, 10); >> >> ngx_conf_merge_size_value(conf->preread_size, prev->preread_size, 65536); >> >> @@ -370,17 +367,8 @@ ngx_http_v2_create_loc_conf(ngx_conf_t * >> return NULL; >> } >> >> - /* >> - * set by ngx_pcalloc(): >> - * >> - * h2lcf->pushes = NULL; >> - */ >> - >> h2lcf->chunk_size = NGX_CONF_UNSET_SIZE; >> >> - h2lcf->push_preload = NGX_CONF_UNSET; >> - h2lcf->push = NGX_CONF_UNSET; >> - >> return h2lcf; >> } >> >> @@ -393,72 +381,6 @@ ngx_http_v2_merge_loc_conf(ngx_conf_t *c >> >> ngx_conf_merge_size_value(conf->chunk_size, prev->chunk_size, 8 * 1024); >> >> - ngx_conf_merge_value(conf->push, prev->push, 1); >> - >> - if (conf->push && conf->pushes == NULL) { >> - conf->pushes = prev->pushes; >> - } >> - >> - ngx_conf_merge_value(conf->push_preload, prev->push_preload, 0); >> - >> - return NGX_CONF_OK; >> -} >> - >> - >> -static char * >> -ngx_http_v2_push(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) >> -{ >> - ngx_http_v2_loc_conf_t *h2lcf = conf; >> - >> - ngx_str_t *value; >> - ngx_http_complex_value_t *cv; >> - ngx_http_compile_complex_value_t ccv; >> - >> - value = cf->args->elts; >> - >> - if (ngx_strcmp(value[1].data, "off") == 0) { >> - >> - if (h2lcf->pushes) { >> - return "\"off\" parameter cannot be used with URI"; >> - } >> - >> - if (h2lcf->push == 0) { >> - return "is duplicate"; >> - } >> - >> - h2lcf->push = 0; >> - return NGX_CONF_OK; >> - } >> - >> - if (h2lcf->push == 0) { >> - return "URI cannot be used with \"off\" parameter"; >> - } >> - >> - h2lcf->push = 1; >> - >> - if (h2lcf->pushes == NULL) { >> - h2lcf->pushes = ngx_array_create(cf->pool, 1, >> - sizeof(ngx_http_complex_value_t)); >> - if (h2lcf->pushes == NULL) { >> - return NGX_CONF_ERROR; >> - } >> - } >> - >> - cv = ngx_array_push(h2lcf->pushes); >> - if (cv == NULL) { >> - return NGX_CONF_ERROR; >> - } >> - >> - ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); >> - >> - ccv.cf = cf; >> - ccv.value = &value[1]; >> - ccv.complex_value = cv; >> - >> - if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { >> - return NGX_CONF_ERROR; >> - } >> - >> return NGX_CONF_OK; >> } >> >> @@ -569,3 +491,14 @@ ngx_http_v2_obsolete(ngx_conf_t *cf, ngx >> >> return NGX_CONF_OK; >> } >> + >> + >> +static char * >> +ngx_http_v2_obsolete_push(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) >> +{ >> + ngx_conf_log_error(NGX_LOG_WARN, cf, 0, >> + "HTTP/2 server push was removed, " >> + "the \"%V\" directive is obsolete", &cmd->name); > > I would rather use something like: > > ngx_conf_log_error(NGX_LOG_WARN, cf, 0, > "the \"%V\" directive is obsolete, ignored", > &cmd->name); Agree, shorter is better. > > And it might make sense to update the ngx_http_v2_obsolete() > function to do this if no cmd->post is provided. > > diff --git a/src/http/v2/ngx_http_v2_module.c b/src/http/v2/ngx_http_v2_module.c > --- a/src/http/v2/ngx_http_v2_module.c > +++ b/src/http/v2/ngx_http_v2_module.c > @@ -36,8 +36,6 @@ static char *ngx_http_v2_streams_index_m > static char *ngx_http_v2_chunk_size(ngx_conf_t *cf, void *post, void *data); > static char *ngx_http_v2_obsolete(ngx_conf_t *cf, ngx_command_t *cmd, > void *conf); > -static char *ngx_http_v2_obsolete_push(ngx_conf_t *cf, ngx_command_t *cmd, > - void *conf); > > > static ngx_conf_deprecated_t ngx_http_v2_recv_timeout_deprecated = { > @@ -105,7 +103,7 @@ static ngx_command_t ngx_http_v2_comman > > { ngx_string("http2_max_concurrent_pushes"), > NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, > - ngx_http_v2_obsolete_push, > + ngx_http_v2_obsolete, > 0, > 0, > NULL }, > @@ -168,14 +166,14 @@ static ngx_command_t ngx_http_v2_comman > > { ngx_string("http2_push_preload"), > NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, > - ngx_http_v2_obsolete_push, > + ngx_http_v2_obsolete, > 0, > 0, > NULL }, > > { ngx_string("http2_push"), > NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, > - ngx_http_v2_obsolete_push, > + ngx_http_v2_obsolete, > 0, > 0, > NULL }, > @@ -484,21 +482,17 @@ ngx_http_v2_obsolete(ngx_conf_t *cf, ngx > { > ngx_conf_deprecated_t *d = cmd->post; > > - ngx_conf_log_error(NGX_LOG_WARN, cf, 0, > - "the \"%s\" directive is obsolete, " > - "use the \"%s\" directive instead", > - d->old_name, d->new_name); > + if (d) { > + ngx_conf_log_error(NGX_LOG_WARN, cf, 0, > + "the \"%s\" directive is obsolete, " > + "use the \"%s\" directive instead", > + d->old_name, d->new_name); > + > + } else { > + ngx_conf_log_error(NGX_LOG_WARN, cf, 0, > + "the \"%V\" directive is obsolete, ignored", > + &cmd->name); > + } > > return NGX_CONF_OK; > } > - > - > -static char * > -ngx_http_v2_obsolete_push(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) > -{ > - ngx_conf_log_error(NGX_LOG_WARN, cf, 0, > - "HTTP/2 server push was removed, " > - "the \"%V\" directive is obsolete", &cmd->name); > - > - return NGX_CONF_OK; > -} > Applied, thanks. Updated patch attached. > >> + >> + return NGX_CONF_OK; >> +} >> diff --git a/src/http/v2/ngx_http_v2_module.h b/src/http/v2/ngx_http_v2_module.h >> --- a/src/http/v2/ngx_http_v2_module.h >> +++ b/src/http/v2/ngx_http_v2_module.h >> @@ -22,11 +22,6 @@ typedef struct { >> >> typedef struct { >> size_t chunk_size; >> - >> - ngx_flag_t push_preload; >> - >> - ngx_flag_t push; >> - ngx_array_t *pushes; >> } ngx_http_v2_loc_conf_t; >> >> > > Otherwise looks good. > -------------- next part -------------- A non-text attachment was scrubbed... Name: v2_push Type: application/octet-stream Size: 43824 bytes Desc: not available URL: -------------- next part -------------- -- Sergey Kandaurov From arut at nginx.com Wed Jun 7 05:44:21 2023 From: arut at nginx.com (=?iso-8859-1?q?Roman_Arutyunyan?=) Date: Wed, 07 Jun 2023 09:44:21 +0400 Subject: [PATCH] QUIC: use AEAD cipher to encrypt address validation tokens Message-ID: <931f7f2b2aab96ca6783.1686116661@arut-laptop> # HG changeset patch # User Roman Arutyunyan # Date 1686116578 -14400 # Wed Jun 07 09:42:58 2023 +0400 # Node ID 931f7f2b2aab96ca6783d42a6dc4d1150b0d45ee # Parent b4a57278bf24dd28d39afea0eb09732c05bf1606 QUIC: use AEAD cipher to encrypt address validation tokens. Previously used AES256-CBC is now substituted with AES256-GCM. Although there seem to be no tangible consequences of token integrity loss. diff --git a/src/event/quic/ngx_event_quic_tokens.c b/src/event/quic/ngx_event_quic_tokens.c --- a/src/event/quic/ngx_event_quic_tokens.c +++ b/src/event/quic/ngx_event_quic_tokens.c @@ -69,11 +69,10 @@ ngx_quic_new_token(ngx_log_t *log, struc len = p - in; - cipher = EVP_aes_256_cbc(); - iv_len = NGX_QUIC_AES_256_CBC_IV_LEN; + cipher = EVP_aes_256_gcm(); + iv_len = NGX_QUIC_AES_256_GCM_IV_LEN; - if ((size_t) (iv_len + len + NGX_QUIC_AES_256_CBC_BLOCK_SIZE) > token->len) - { + if ((size_t) (iv_len + len + NGX_QUIC_AES_256_GCM_TAG_LEN) > token->len) { ngx_log_error(NGX_LOG_ALERT, log, 0, "quic token buffer is too small"); return NGX_ERROR; } @@ -108,6 +107,17 @@ ngx_quic_new_token(ngx_log_t *log, struc token->len += len; + if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, + NGX_QUIC_AES_256_GCM_TAG_LEN, + token->data + token->len) + == 0) + { + EVP_CIPHER_CTX_free(ctx); + return NGX_ERROR; + } + + token->len += NGX_QUIC_AES_256_GCM_TAG_LEN; + EVP_CIPHER_CTX_free(ctx); #ifdef NGX_QUIC_DEBUG_PACKETS @@ -184,17 +194,19 @@ ngx_quic_validate_token(ngx_connection_t /* Retry token or NEW_TOKEN in a previous connection */ - cipher = EVP_aes_256_cbc(); + cipher = EVP_aes_256_gcm(); iv = pkt->token.data; - iv_len = NGX_QUIC_AES_256_CBC_IV_LEN; + iv_len = NGX_QUIC_AES_256_GCM_IV_LEN; /* sanity checks */ - if (pkt->token.len < (size_t) iv_len + NGX_QUIC_AES_256_CBC_BLOCK_SIZE) { + if (pkt->token.len < (size_t) iv_len + NGX_QUIC_AES_256_GCM_TAG_LEN) { goto garbage; } - if (pkt->token.len > (size_t) iv_len + NGX_QUIC_MAX_TOKEN_SIZE) { + if (pkt->token.len > (size_t) iv_len + NGX_QUIC_MAX_TOKEN_SIZE + + NGX_QUIC_AES_256_GCM_TAG_LEN) + { goto garbage; } @@ -209,15 +221,23 @@ ngx_quic_validate_token(ngx_connection_t } p = pkt->token.data + iv_len; - len = pkt->token.len - iv_len; + len = pkt->token.len - iv_len - NGX_QUIC_AES_256_GCM_TAG_LEN; - if (EVP_DecryptUpdate(ctx, tdec, &len, p, len) != 1) { + if (EVP_DecryptUpdate(ctx, tdec, &tlen, p, len) != 1) { EVP_CIPHER_CTX_free(ctx); goto garbage; } - total = len; + total = tlen; - if (EVP_DecryptFinal_ex(ctx, tdec + len, &tlen) <= 0) { + if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, + NGX_QUIC_AES_256_GCM_TAG_LEN, p + len) + == 0) + { + EVP_CIPHER_CTX_free(ctx); + goto garbage; + } + + if (EVP_DecryptFinal_ex(ctx, tdec + tlen, &tlen) <= 0) { EVP_CIPHER_CTX_free(ctx); goto garbage; } diff --git a/src/event/quic/ngx_event_quic_tokens.h b/src/event/quic/ngx_event_quic_tokens.h --- a/src/event/quic/ngx_event_quic_tokens.h +++ b/src/event/quic/ngx_event_quic_tokens.h @@ -15,13 +15,12 @@ #define NGX_QUIC_MAX_TOKEN_SIZE 64 /* SHA-1(addr)=20 + sizeof(time_t) + retry(1) + odcid.len(1) + odcid */ -/* RFC 3602, 2.1 and 2.4 for AES-CBC block size and IV length */ -#define NGX_QUIC_AES_256_CBC_IV_LEN 16 -#define NGX_QUIC_AES_256_CBC_BLOCK_SIZE 16 +#define NGX_QUIC_AES_256_GCM_IV_LEN 12 +#define NGX_QUIC_AES_256_GCM_TAG_LEN 16 -#define NGX_QUIC_TOKEN_BUF_SIZE (NGX_QUIC_AES_256_CBC_IV_LEN \ +#define NGX_QUIC_TOKEN_BUF_SIZE (NGX_QUIC_AES_256_GCM_IV_LEN \ + NGX_QUIC_MAX_TOKEN_SIZE \ - + NGX_QUIC_AES_256_CBC_BLOCK_SIZE) + + NGX_QUIC_AES_256_GCM_TAG_LEN) ngx_int_t ngx_quic_new_sr_token(ngx_connection_t *c, ngx_str_t *cid, From mdounin at mdounin.ru Wed Jun 7 15:50:57 2023 From: mdounin at mdounin.ru (Maxim Dounin) Date: Wed, 7 Jun 2023 18:50:57 +0300 Subject: [PATCH 2 of 3] HTTP/2: "http2" directive In-Reply-To: <20230605141951.wx5np5jwxhjsxybc@N00W24XTQX> References: <735f9e501922e4b0a1b2.1675781431@arut-laptop> <20230209120234.rttyjviwir4sneed@N00W24XTQX> <20230209123359.i6fosl5r6tdhpvhv@N00W24XTQX> <71CADCEB-5BD1-4F67-AE85-581943918D5B@nginx.com> <20230516123938.rgrmdpern3i5hq5n@N00W24XTQX> <20230605141951.wx5np5jwxhjsxybc@N00W24XTQX> Message-ID: Hello! On Mon, Jun 05, 2023 at 06:19:51PM +0400, Roman Arutyunyan wrote: > On Sat, Jun 03, 2023 at 12:37:03AM +0300, Maxim Dounin wrote: > > Hello! > > > > On Tue, May 16, 2023 at 04:39:38PM +0400, Roman Arutyunyan wrote: > > > > > On Thu, Feb 09, 2023 at 07:56:55PM +0400, Sergey Kandaurov wrote: > > > > > > > > > On 9 Feb 2023, at 16:33, Roman Arutyunyan wrote: > > > > > > > > > > Hi, > > > > > > > > > > On Thu, Feb 09, 2023 at 04:02:34PM +0400, Roman Arutyunyan wrote: > > > > > > > > > > [..] > > > > > > > > > >> diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c > > > > >> --- a/src/http/ngx_http_request.c > > > > >> +++ b/src/http/ngx_http_request.c > > > > >> @@ -318,12 +318,6 @@ ngx_http_init_connection(ngx_connection_ > > > > >> rev->handler = ngx_http_wait_request_handler; > > > > >> c->write->handler = ngx_http_empty_handler; > > > > >> > > > > >> -#if (NGX_HTTP_V2) > > > > >> - if (hc->addr_conf->http2) { > > > > >> - rev->handler = ngx_http_v2_init; > > > > >> - } > > > > >> -#endif > > > > >> - > > > > >> #if (NGX_HTTP_V3) > > > > >> if (hc->addr_conf->quic) { > > > > >> ngx_http_v3_init_stream(c); > > > > >> @@ -383,6 +377,9 @@ ngx_http_wait_request_handler(ngx_event_ > > > > >> ngx_buf_t *b; > > > > >> ngx_connection_t *c; > > > > >> ngx_http_connection_t *hc; > > > > >> +#if (NGX_HTTP_V2) > > > > >> + ngx_http_v2_srv_conf_t *h2scf; > > > > >> +#endif > > > > >> ngx_http_core_srv_conf_t *cscf; > > > > >> > > > > >> c = rev->data; > > > > >> @@ -429,6 +426,8 @@ ngx_http_wait_request_handler(ngx_event_ > > > > >> b->end = b->last + size; > > > > >> } > > > > >> > > > > >> + size = b->end - b->last; > > > > >> + > > > > >> n = c->recv(c, b->last, size); > > > > >> > > > > >> if (n == NGX_AGAIN) { > > > > >> @@ -443,12 +442,16 @@ ngx_http_wait_request_handler(ngx_event_ > > > > >> return; > > > > >> } > > > > >> > > > > >> - /* > > > > >> - * We are trying to not hold c->buffer's memory for an idle connection. > > > > >> - */ > > > > >> - > > > > >> - if (ngx_pfree(c->pool, b->start) == NGX_OK) { > > > > >> - b->start = NULL; > > > > >> + if (b->pos == b->last) { > > > > >> + > > > > >> + /* > > > > >> + * We are trying to not hold c->buffer's memory for an > > > > >> + * idle connection. > > > > >> + */ > > > > >> + > > > > >> + if (ngx_pfree(c->pool, b->start) == NGX_OK) { > > > > >> + b->start = NULL; > > > > >> + } > > > > >> } > > > > >> > > > > >> return; > > > > >> @@ -489,10 +492,34 @@ ngx_http_wait_request_handler(ngx_event_ > > > > >> } > > > > >> } > > > > >> > > > > >> + ngx_reusable_connection(c, 0); > > > > >> + > > > > >> +#if (NGX_HTTP_V2) > > > > >> + > > > > >> + h2scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v2_module); > > > > >> + > > > > >> + if (!c->ssl && (h2scf->enable || hc->addr_conf->http2)) { > > > > > > > > > > And one more fix for compilation with HTTP/2, but without SSL: > > > > > > > > > > diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c > > > > > --- a/src/http/ngx_http_request.c > > > > > +++ b/src/http/ngx_http_request.c > > > > > @@ -498,8 +498,12 @@ ngx_http_wait_request_handler(ngx_event_ > > > > > > > > > > h2scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v2_module); > > > > > > > > > > - if (!c->ssl && (h2scf->enable || hc->addr_conf->http2)) { > > > > > - > > > > > + if ((h2scf->enable || hc->addr_conf->http2) > > > > > +#if (NGX_HTTP_SSL) > > > > > + && !c->ssl > > > > > +#endif > > > > > + ) > > > > > + { > > > > > size = ngx_min(sizeof(NGX_HTTP_V2_PREFACE) - 1, > > > > > (size_t) (b->last - b->pos)); > > > > > > > > > > > > > I think this test needs to be replaced with !hc->ssl. > > > > Otherwise, it would allow to establish (and keep) h2c on ssl-enabled > > > > sockets, which we likely do not want to allow. > > > > > > After a series of discussions we decided to go with !hc->ssl. As a result, > > > any non-SSL connection on an SSL port will trigger the HTTP/1 error page. > > > Previous attempt to trigger the HTTP/2 error in case client request is > > > recognized as HTTP/2, is discarded since the situation is unlikely. > > > > > > [..] > > > > > > -- > > > Roman Arutyunyan > > > > > # HG changeset patch > > > # User Roman Arutyunyan > > > # Date 1684240208 -14400 > > > # Tue May 16 16:30:08 2023 +0400 > > > # Branch quic > > > # Node ID 4dcd2b42c23973815a6b8a7f54bbd1460c314c93 > > > # Parent d8272b84031bea1940ef8a5b8e2f79ec6a2dcfc1 > > > HTTP/2: "http2" directive. > > > > > > The directive enables HTTP/2 in the current server. The previous way to > > > enable HTTP/2 via "listen ... http2" is now deprecated. The new approach > > > allows to share HTTP/2 and HTTP/0.9-1.1 on the same port. > > > > > > For SSL connections, HTTP/2 is now selected by ALPN callback based on whether > > > the protocol is enabled in the virtual server chosen by SNI. This however only > > > works since OpenSSL 1.0.2h, where ALPN callback is invoked after SNI callback. > > > For older versions of OpenSSL, HTTP/2 is enabled based on the default virtual > > > server configuration. > > > > > > For plain TCP connections, HTTP/2 is now auto-detected by HTTP/2 preface, if > > > HTTP/2 is enabled in the default virtual server. If preface is not matched, > > > HTTP/0.9-1.1 is assumed. > > > > > > diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c > > > --- a/src/http/modules/ngx_http_ssl_module.c > > > +++ b/src/http/modules/ngx_http_ssl_module.c > > > @@ -435,6 +435,9 @@ ngx_http_ssl_alpn_select(ngx_ssl_conn_t > > > #if (NGX_HTTP_V2 || NGX_HTTP_V3) > > > ngx_http_connection_t *hc; > > > #endif > > > +#if (NGX_HTTP_V2) > > > + ngx_http_v2_srv_conf_t *h2scf; > > > +#endif > > > #if (NGX_HTTP_V3) > > > ngx_http_v3_srv_conf_t *h3scf; > > > #endif > > > @@ -456,12 +459,6 @@ ngx_http_ssl_alpn_select(ngx_ssl_conn_t > > > hc = c->data; > > > #endif > > > > > > -#if (NGX_HTTP_V2) > > > - if (hc->addr_conf->http2) { > > > - srv = (unsigned char *) NGX_HTTP_V2_ALPN_PROTO NGX_HTTP_ALPN_PROTOS; > > > - srvlen = sizeof(NGX_HTTP_V2_ALPN_PROTO NGX_HTTP_ALPN_PROTOS) - 1; > > > - } else > > > -#endif > > > #if (NGX_HTTP_V3) > > > if (hc->addr_conf->quic) { > > > > > > @@ -488,8 +485,19 @@ ngx_http_ssl_alpn_select(ngx_ssl_conn_t > > > } else > > > #endif > > > { > > > - srv = (unsigned char *) NGX_HTTP_ALPN_PROTOS; > > > - srvlen = sizeof(NGX_HTTP_ALPN_PROTOS) - 1; > > > +#if (NGX_HTTP_V2) > > > + h2scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v2_module); > > > + > > > + if (h2scf->enable || hc->addr_conf->http2) { > > > + srv = (unsigned char *) NGX_HTTP_V2_ALPN_PROTO NGX_HTTP_ALPN_PROTOS; > > > + srvlen = sizeof(NGX_HTTP_V2_ALPN_PROTO NGX_HTTP_ALPN_PROTOS) - 1; > > > + > > > + } else > > > +#endif > > > + { > > > + srv = (unsigned char *) NGX_HTTP_ALPN_PROTOS; > > > + srvlen = sizeof(NGX_HTTP_ALPN_PROTOS) - 1; > > > + } > > > } > > > > > > if (SSL_select_next_proto((unsigned char **) out, outlen, srv, srvlen, > > > diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c > > > --- a/src/http/ngx_http_core_module.c > > > +++ b/src/http/ngx_http_core_module.c > > > @@ -4176,6 +4176,11 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx > > > > > > if (ngx_strcmp(value[n].data, "http2") == 0) { > > > #if (NGX_HTTP_V2) > > > + ngx_conf_log_error(NGX_LOG_WARN, cf, 0, > > > + "the \"listen ... http2\" directive " > > > + "is deprecated, use " > > > + "the \"http2\" directive instead"); > > > + > > > lsopt.http2 = 1; > > > continue; > > > #else > > > diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c > > > --- a/src/http/ngx_http_request.c > > > +++ b/src/http/ngx_http_request.c > > > @@ -318,12 +318,6 @@ ngx_http_init_connection(ngx_connection_ > > > rev->handler = ngx_http_wait_request_handler; > > > c->write->handler = ngx_http_empty_handler; > > > > > > -#if (NGX_HTTP_V2) > > > - if (hc->addr_conf->http2) { > > > - rev->handler = ngx_http_v2_init; > > > - } > > > -#endif > > > - > > > #if (NGX_HTTP_V3) > > > if (hc->addr_conf->quic) { > > > ngx_http_v3_init_stream(c); > > > @@ -383,6 +377,9 @@ ngx_http_wait_request_handler(ngx_event_ > > > ngx_buf_t *b; > > > ngx_connection_t *c; > > > ngx_http_connection_t *hc; > > > +#if (NGX_HTTP_V2) > > > + ngx_http_v2_srv_conf_t *h2scf; > > > +#endif > > > ngx_http_core_srv_conf_t *cscf; > > > > > > c = rev->data; > > > @@ -429,6 +426,8 @@ ngx_http_wait_request_handler(ngx_event_ > > > b->end = b->last + size; > > > } > > > > > > + size = b->end - b->last; > > > + > > > n = c->recv(c, b->last, size); > > > > > > if (n == NGX_AGAIN) { > > > @@ -443,12 +442,16 @@ ngx_http_wait_request_handler(ngx_event_ > > > return; > > > } > > > > > > - /* > > > - * We are trying to not hold c->buffer's memory for an idle connection. > > > - */ > > > - > > > - if (ngx_pfree(c->pool, b->start) == NGX_OK) { > > > - b->start = NULL; > > > + if (b->pos == b->last) { > > > + > > > + /* > > > + * We are trying to not hold c->buffer's memory for an > > > + * idle connection. > > > + */ > > > + > > > + if (ngx_pfree(c->pool, b->start) == NGX_OK) { > > > + b->start = NULL; > > > + } > > > } > > > > > > return; > > > @@ -489,10 +492,34 @@ ngx_http_wait_request_handler(ngx_event_ > > > } > > > } > > > > > > + ngx_reusable_connection(c, 0); > > > > I don't think it should be moved. > > > > Non-reusable connections are basically ones with a request > > created, so nginx won't try to terminate running requests. This > > does not apply to a connection waiting for an HTTP/2 preface. > > > > It might need to be called in (or just before) ngx_http_v2_init() > > though, since HTTP/2 code assumes that the connection is not > > reusable by default. > > OK > > > > + > > > +#if (NGX_HTTP_V2) > > > + > > > + h2scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v2_module); > > > + > > > + if (!hc->ssl && (h2scf->enable || hc->addr_conf->http2)) { > > > > For the record: we might consider introducing a way to explicitly > > control "establishment of HTTP/2 connections over cleartext TCP" > > (quote from RFC 9113, section 3.3. "Starting HTTP/2 with Prior > > Knowledge"), something like "http2_cleartext on|off;". Might not > > worth the effort though. > > Why do you think we need this directive? HTTP/2 over cleartext TCP implies different code paths, which are better avoided unless needed. And it is only needed in very specific cases, since browsers do not support HTTP/2 over cleartext TCP. Further, it implies different resource usage ratio between client and server, and enabling it might make some attacks more feasible. That is, there are no specific reasons to say “we certainly need it”, but there are generic concerns that it would be safer to not enable HTTP/2 over cleartext TCP in most setups using HTTP/2. While it would be possible to only enable HTTP/2 in specific server blocks with only SSL listening sockets, having a distinct directive would be easier to configure. > > > + > > > + size = ngx_min(sizeof(NGX_HTTP_V2_PREFACE) - 1, > > > + (size_t) (b->last - b->pos)); > > > + > > > + if (ngx_memcmp(b->pos, NGX_HTTP_V2_PREFACE, size) == 0) { > > > + > > > + if (size == sizeof(NGX_HTTP_V2_PREFACE) - 1) { > > > + ngx_http_v2_init(rev); > > > + return; > > > + } > > > + > > > + c->log->action = "waiting for request"; > > > > Any reasons to change the log action here? > > > > Note that for proxy_protocol handling above, c->log->action is set > > to "reading PROXY protocol", and therefore needs to be reset to > > "waiting for request" when PROXY protocol header is fully > > processed. This is not the case for HTTP/2 preface though, as it > > does not use a special log action. > > > > Further, in this particular point HTTP/2 preface reading is not > > complete, so changing the log action would be wrong if there was > > a special log action set. > > You're right, removed this one. > > > > + ngx_post_event(rev, &ngx_posted_events); > > > + return; > > > > For the record: as far as I understand, there is no real need to > > post an event here, and just adding a timer and calling > > ngx_handle_read_event() (much like in case of EAGAIN after recv()) > > would be slightly more optimal. I don't object keeping it this > > way though, since it's not a hot path, have some chance to > > actually read the rest of the preface in the posted event, and > > proxy_protocol handling already uses the same approach. > > > > > + } > > > + } > > > + > > > +#endif > > > + > > > c->log->action = "reading client request line"; > > > > > > - ngx_reusable_connection(c, 0); > > > - > > > c->data = ngx_http_create_request(c); > > > if (c->data == NULL) { > > > ngx_http_close_connection(c); > > > @@ -808,13 +835,16 @@ ngx_http_ssl_handshake_handler(ngx_conne > > > #if (NGX_HTTP_V2 \ > > > && defined TLSEXT_TYPE_application_layer_protocol_negotiation) > > > { > > > - unsigned int len; > > > - const unsigned char *data; > > > - ngx_http_connection_t *hc; > > > + unsigned int len; > > > + const unsigned char *data; > > > + ngx_http_connection_t *hc; > > > + ngx_http_v2_srv_conf_t *h2scf; > > > > > > hc = c->data; > > > > > > - if (hc->addr_conf->http2) { > > > + h2scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v2_module); > > > + > > > + if (h2scf->enable || hc->addr_conf->http2) { > > > > > > SSL_get0_alpn_selected(c->ssl->connection, &data, &len); > > > > > > diff --git a/src/http/v2/ngx_http_v2.c b/src/http/v2/ngx_http_v2.c > > > --- a/src/http/v2/ngx_http_v2.c > > > +++ b/src/http/v2/ngx_http_v2.c > > > @@ -63,8 +63,6 @@ static void ngx_http_v2_handle_connectio > > > static void ngx_http_v2_lingering_close(ngx_connection_t *c); > > > static void ngx_http_v2_lingering_close_handler(ngx_event_t *rev); > > > > > > -static u_char *ngx_http_v2_state_proxy_protocol(ngx_http_v2_connection_t *h2c, > > > - u_char *pos, u_char *end); > > > static u_char *ngx_http_v2_state_preface(ngx_http_v2_connection_t *h2c, > > > u_char *pos, u_char *end); > > > static u_char *ngx_http_v2_state_preface_end(ngx_http_v2_connection_t *h2c, > > > @@ -232,6 +230,7 @@ static ngx_http_v2_parse_header_t ngx_h > > > void > > > ngx_http_v2_init(ngx_event_t *rev) > > > { > > > + u_char *p, *end; > > > ngx_connection_t *c; > > > ngx_pool_cleanup_t *cln; > > > ngx_http_connection_t *hc; > > > @@ -314,8 +313,7 @@ ngx_http_v2_init(ngx_event_t *rev) > > > return; > > > } > > > > > > - h2c->state.handler = hc->proxy_protocol ? ngx_http_v2_state_proxy_protocol > > > - : ngx_http_v2_state_preface; > > > + h2c->state.handler = ngx_http_v2_state_preface; > > > > > > ngx_queue_init(&h2c->waiting); > > > ngx_queue_init(&h2c->dependencies); > > > @@ -333,7 +331,23 @@ ngx_http_v2_init(ngx_event_t *rev) > > > } > > > > > > c->idle = 1; > > > - ngx_reusable_connection(c, 0); > > > > See above. > > Brought this back along with the above mentioned calls. > > > > + > > > + if (c->buffer) { > > > + p = c->buffer->pos; > > > + end = c->buffer->last; > > > + > > > + do { > > > + p = h2c->state.handler(h2c, p, end); > > > + > > > + if (p == NULL) { > > > + return; > > > + } > > > + > > > + } while (p != end); > > > + > > > + h2c->total_bytes += p - c->buffer->pos; > > > + c->buffer->pos = p; > > > + } > > > > > > ngx_http_v2_read_handler(rev); > > > } > > > > For the record: it might be better to integrate this into > > ngx_http_v2_read_handler(), similarly to how it is done in > > ngx_event_pipe_read_upstream(). On the other hand, suggested > > approach looks simple enough and might be better. > > Yes, this would make ngx_http_v2_read_handler() too complex. > > > Note well: this implies an extra recv() call on each cleartext > > HTTP/2 connection establishment. Probably not very important > > though. On the other hand, we can consider optimizing out an > > extra call if there are space in c->buffer. > > Why not check rev->ready at the beginning of the loop in > ngx_http_v2_read_handler() ? > > while (rev->ready) { ... } > > Currently it's checked at the end. Usually rev->ready is checked at the end, since read handlers are not expected to be called with rev->ready set to 0, so checking it on the first iteration would be a waste of resources. This approach also guarantees some safety against event handling bugs (that is, if rev->ready wouldn't be set for some reason). A better approach might be to check rev->ready before calling the ngx_http_v2_read_handler() handler, much like in ngx_http_init_connection(). > > > @@ -847,31 +861,10 @@ ngx_http_v2_lingering_close_handler(ngx_ > > > > > > > > > static u_char * > > > -ngx_http_v2_state_proxy_protocol(ngx_http_v2_connection_t *h2c, u_char *pos, > > > - u_char *end) > > > -{ > > > - ngx_log_t *log; > > > - > > > - log = h2c->connection->log; > > > - log->action = "reading PROXY protocol"; > > > - > > > - pos = ngx_proxy_protocol_read(h2c->connection, pos, end); > > > - > > > - log->action = "processing HTTP/2 connection"; > > > - > > > - if (pos == NULL) { > > > - return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR); > > > - } > > > - > > > - return ngx_http_v2_state_preface(h2c, pos, end); > > > -} > > > - > > > - > > > -static u_char * > > > ngx_http_v2_state_preface(ngx_http_v2_connection_t *h2c, u_char *pos, > > > u_char *end) > > > { > > > - static const u_char preface[] = "PRI * HTTP/2.0\r\n"; > > > + static const u_char preface[] = NGX_HTTP_V2_PREFACE_START; > > > > > > if ((size_t) (end - pos) < sizeof(preface) - 1) { > > > return ngx_http_v2_state_save(h2c, pos, end, ngx_http_v2_state_preface); > > > @@ -892,7 +885,7 @@ static u_char * > > > ngx_http_v2_state_preface_end(ngx_http_v2_connection_t *h2c, u_char *pos, > > > u_char *end) > > > { > > > - static const u_char preface[] = "\r\nSM\r\n\r\n"; > > > + static const u_char preface[] = NGX_HTTP_V2_PREFACE_END; > > > > > > if ((size_t) (end - pos) < sizeof(preface) - 1) { > > > return ngx_http_v2_state_save(h2c, pos, end, > > > @@ -3943,10 +3936,22 @@ static void > > > ngx_http_v2_run_request(ngx_http_request_t *r) > > > { > > > ngx_connection_t *fc; > > > + ngx_http_v2_srv_conf_t *h2scf; > > > ngx_http_v2_connection_t *h2c; > > > > > > fc = r->connection; > > > > > > + h2scf = ngx_http_get_module_srv_conf(r, ngx_http_v2_module); > > > + > > > + if (!h2scf->enable && !r->http_connection->addr_conf->http2) { > > > + ngx_log_error(NGX_LOG_INFO, fc->log, 0, > > > + "client attempted to request the server name " > > > + "for which the negotiated protocol is disabled"); > > > + > > > + ngx_http_finalize_request(r, NGX_HTTP_MISDIRECTED_REQUEST); > > > + goto failed; > > > + } > > > + > > > if (ngx_http_v2_construct_request_line(r) != NGX_OK) { > > > goto failed; > > > } > > > diff --git a/src/http/v2/ngx_http_v2.h b/src/http/v2/ngx_http_v2.h > > > --- a/src/http/v2/ngx_http_v2.h > > > +++ b/src/http/v2/ngx_http_v2.h > > > @@ -64,6 +64,16 @@ typedef u_char *(*ngx_http_v2_handler_pt > > > > > > > > > typedef struct { > > > + ngx_flag_t enable; > > > + size_t pool_size; > > > + ngx_uint_t concurrent_streams; > > > + ngx_uint_t concurrent_pushes; > > > + size_t preread_size; > > > + ngx_uint_t streams_index_mask; > > > +} ngx_http_v2_srv_conf_t; > > > + > > > + > > > +typedef struct { > > > ngx_str_t name; > > > ngx_str_t value; > > > } ngx_http_v2_header_t; > > > @@ -408,9 +418,17 @@ ngx_int_t ngx_http_v2_table_size(ngx_htt > > > #define NGX_HTTP_V2_USER_AGENT_INDEX 58 > > > #define NGX_HTTP_V2_VARY_INDEX 59 > > > > > > +#define NGX_HTTP_V2_PREFACE_START "PRI * HTTP/2.0\r\n" > > > +#define NGX_HTTP_V2_PREFACE_END "\r\nSM\r\n\r\n" > > > +#define NGX_HTTP_V2_PREFACE NGX_HTTP_V2_PREFACE_START \ > > > + NGX_HTTP_V2_PREFACE_END > > > + > > > > > > u_char *ngx_http_v2_string_encode(u_char *dst, u_char *src, size_t len, > > > u_char *tmp, ngx_uint_t lower); > > > > > > > > > +extern ngx_module_t ngx_http_v2_module; > > > + > > > + > > > #endif /* _NGX_HTTP_V2_H_INCLUDED_ */ > > > diff --git a/src/http/v2/ngx_http_v2_module.c b/src/http/v2/ngx_http_v2_module.c > > > --- a/src/http/v2/ngx_http_v2_module.c > > > +++ b/src/http/v2/ngx_http_v2_module.c > > > @@ -75,6 +75,13 @@ static ngx_conf_post_t ngx_http_v2_chun > > > > > > static ngx_command_t ngx_http_v2_commands[] = { > > > > > > + { ngx_string("http2"), > > > + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG, > > > + ngx_conf_set_flag_slot, > > > + NGX_HTTP_SRV_CONF_OFFSET, > > > + offsetof(ngx_http_v2_srv_conf_t, enable), > > > + NULL }, > > > + > > > { ngx_string("http2_recv_buffer_size"), > > > NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, > > > ngx_conf_set_size_slot, > > > @@ -314,6 +321,8 @@ ngx_http_v2_create_srv_conf(ngx_conf_t * > > > return NULL; > > > } > > > > > > + h2scf->enable = NGX_CONF_UNSET; > > > + > > > h2scf->pool_size = NGX_CONF_UNSET_SIZE; > > > > > > h2scf->concurrent_streams = NGX_CONF_UNSET_UINT; > > > @@ -333,6 +342,8 @@ ngx_http_v2_merge_srv_conf(ngx_conf_t *c > > > ngx_http_v2_srv_conf_t *prev = parent; > > > ngx_http_v2_srv_conf_t *conf = child; > > > > > > + ngx_conf_merge_value(conf->enable, prev->enable, 0); > > > + > > > ngx_conf_merge_size_value(conf->pool_size, prev->pool_size, 4096); > > > > > > ngx_conf_merge_uint_value(conf->concurrent_streams, > > > diff --git a/src/http/v2/ngx_http_v2_module.h b/src/http/v2/ngx_http_v2_module.h > > > --- a/src/http/v2/ngx_http_v2_module.h > > > +++ b/src/http/v2/ngx_http_v2_module.h > > > @@ -21,15 +21,6 @@ typedef struct { > > > > > > > > > typedef struct { > > > - size_t pool_size; > > > - ngx_uint_t concurrent_streams; > > > - ngx_uint_t concurrent_pushes; > > > - size_t preread_size; > > > - ngx_uint_t streams_index_mask; > > > -} ngx_http_v2_srv_conf_t; > > > - > > > - > > > -typedef struct { > > > size_t chunk_size; > > > > > > ngx_flag_t push_preload; > > > @@ -39,7 +30,4 @@ typedef struct { > > > } ngx_http_v2_loc_conf_t; > > > > > > > > > -extern ngx_module_t ngx_http_v2_module; > > > - > > > - > > > #endif /* _NGX_HTTP_V2_MODULE_H_INCLUDED_ */ > > > > Overall looks good. > > > > -- > > Maxim Dounin > > http://mdounin.ru/ > > _______________________________________________ > > nginx-devel mailing list > > nginx-devel at nginx.org > > https://mailman.nginx.org/mailman/listinfo/nginx-devel > > -- > Roman Arutyunyan > # HG changeset patch > # User Roman Arutyunyan > # Date 1684240208 -14400 > # Tue May 16 16:30:08 2023 +0400 > # Node ID 6d3648910d8ea0bf8891670c7b9ea5539a3d39f9 > # Parent 564c8f447ea4d76d80251bbf07df412942a2261f > HTTP/2: "http2" directive. > > The directive enables HTTP/2 in the current server. The previous way to > enable HTTP/2 via "listen ... http2" is now deprecated. The new approach > allows to share HTTP/2 and HTTP/0.9-1.1 on the same port. > > For SSL connections, HTTP/2 is now selected by ALPN callback based on whether > the protocol is enabled in the virtual server chosen by SNI. This however only > works since OpenSSL 1.0.2h, where ALPN callback is invoked after SNI callback. > For older versions of OpenSSL, HTTP/2 is enabled based on the default virtual > server configuration. > > For plain TCP connections, HTTP/2 is now auto-detected by HTTP/2 preface, if > HTTP/2 is enabled in the default virtual server. If preface is not matched, > HTTP/0.9-1.1 is assumed. > > diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c > --- a/src/http/modules/ngx_http_ssl_module.c > +++ b/src/http/modules/ngx_http_ssl_module.c > @@ -421,6 +421,9 @@ ngx_http_ssl_alpn_select(ngx_ssl_conn_t > #if (NGX_HTTP_V2 || NGX_HTTP_V3) > ngx_http_connection_t *hc; > #endif > +#if (NGX_HTTP_V2) > + ngx_http_v2_srv_conf_t *h2scf; > +#endif > #if (NGX_HTTP_V3) > ngx_http_v3_srv_conf_t *h3scf; > #endif > @@ -442,12 +445,6 @@ ngx_http_ssl_alpn_select(ngx_ssl_conn_t > hc = c->data; > #endif > > -#if (NGX_HTTP_V2) > - if (hc->addr_conf->http2) { > - srv = (unsigned char *) NGX_HTTP_V2_ALPN_PROTO NGX_HTTP_ALPN_PROTOS; > - srvlen = sizeof(NGX_HTTP_V2_ALPN_PROTO NGX_HTTP_ALPN_PROTOS) - 1; > - } else > -#endif > #if (NGX_HTTP_V3) > if (hc->addr_conf->quic) { > > @@ -474,8 +471,19 @@ ngx_http_ssl_alpn_select(ngx_ssl_conn_t > } else > #endif > { > - srv = (unsigned char *) NGX_HTTP_ALPN_PROTOS; > - srvlen = sizeof(NGX_HTTP_ALPN_PROTOS) - 1; > +#if (NGX_HTTP_V2) > + h2scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v2_module); > + > + if (h2scf->enable || hc->addr_conf->http2) { > + srv = (unsigned char *) NGX_HTTP_V2_ALPN_PROTO NGX_HTTP_ALPN_PROTOS; > + srvlen = sizeof(NGX_HTTP_V2_ALPN_PROTO NGX_HTTP_ALPN_PROTOS) - 1; > + > + } else > +#endif > + { > + srv = (unsigned char *) NGX_HTTP_ALPN_PROTOS; > + srvlen = sizeof(NGX_HTTP_ALPN_PROTOS) - 1; > + } > } > > if (SSL_select_next_proto((unsigned char **) out, outlen, srv, srvlen, > diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c > --- a/src/http/ngx_http_core_module.c > +++ b/src/http/ngx_http_core_module.c > @@ -4176,6 +4176,11 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx > > if (ngx_strcmp(value[n].data, "http2") == 0) { > #if (NGX_HTTP_V2) > + ngx_conf_log_error(NGX_LOG_WARN, cf, 0, > + "the \"listen ... http2\" directive " > + "is deprecated, use " > + "the \"http2\" directive instead"); > + > lsopt.http2 = 1; > continue; > #else > diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c > --- a/src/http/ngx_http_request.c > +++ b/src/http/ngx_http_request.c > @@ -318,12 +318,6 @@ ngx_http_init_connection(ngx_connection_ > rev->handler = ngx_http_wait_request_handler; > c->write->handler = ngx_http_empty_handler; > > -#if (NGX_HTTP_V2) > - if (hc->addr_conf->http2) { > - rev->handler = ngx_http_v2_init; > - } > -#endif > - > #if (NGX_HTTP_V3) > if (hc->addr_conf->quic) { > ngx_http_v3_init_stream(c); > @@ -377,6 +371,9 @@ ngx_http_wait_request_handler(ngx_event_ > ngx_buf_t *b; > ngx_connection_t *c; > ngx_http_connection_t *hc; > +#if (NGX_HTTP_V2) > + ngx_http_v2_srv_conf_t *h2scf; > +#endif > ngx_http_core_srv_conf_t *cscf; > > c = rev->data; > @@ -423,6 +420,8 @@ ngx_http_wait_request_handler(ngx_event_ > b->end = b->last + size; > } > > + size = b->end - b->last; > + > n = c->recv(c, b->last, size); > > if (n == NGX_AGAIN) { > @@ -437,12 +436,16 @@ ngx_http_wait_request_handler(ngx_event_ > return; > } > > - /* > - * We are trying to not hold c->buffer's memory for an idle connection. > - */ > - > - if (ngx_pfree(c->pool, b->start) == NGX_OK) { > - b->start = NULL; > + if (b->pos == b->last) { > + > + /* > + * We are trying to not hold c->buffer's memory for an > + * idle connection. > + */ > + > + if (ngx_pfree(c->pool, b->start) == NGX_OK) { > + b->start = NULL; > + } > } > > return; > @@ -483,6 +486,29 @@ ngx_http_wait_request_handler(ngx_event_ > } > } > > +#if (NGX_HTTP_V2) > + > + h2scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v2_module); > + > + if (!hc->ssl && (h2scf->enable || hc->addr_conf->http2)) { > + > + size = ngx_min(sizeof(NGX_HTTP_V2_PREFACE) - 1, > + (size_t) (b->last - b->pos)); > + > + if (ngx_memcmp(b->pos, NGX_HTTP_V2_PREFACE, size) == 0) { > + > + if (size == sizeof(NGX_HTTP_V2_PREFACE) - 1) { > + ngx_http_v2_init(rev); > + return; > + } > + > + ngx_post_event(rev, &ngx_posted_events); > + return; > + } > + } > + > +#endif > + > c->log->action = "reading client request line"; > > ngx_reusable_connection(c, 0); > @@ -802,13 +828,16 @@ ngx_http_ssl_handshake_handler(ngx_conne > #if (NGX_HTTP_V2 \ > && defined TLSEXT_TYPE_application_layer_protocol_negotiation) > { > - unsigned int len; > - const unsigned char *data; > - ngx_http_connection_t *hc; > + unsigned int len; > + const unsigned char *data; > + ngx_http_connection_t *hc; > + ngx_http_v2_srv_conf_t *h2scf; > > hc = c->data; > > - if (hc->addr_conf->http2) { > + h2scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v2_module); > + > + if (h2scf->enable || hc->addr_conf->http2) { > > SSL_get0_alpn_selected(c->ssl->connection, &data, &len); > > diff --git a/src/http/v2/ngx_http_v2.c b/src/http/v2/ngx_http_v2.c > --- a/src/http/v2/ngx_http_v2.c > +++ b/src/http/v2/ngx_http_v2.c > @@ -63,8 +63,6 @@ static void ngx_http_v2_handle_connectio > static void ngx_http_v2_lingering_close(ngx_connection_t *c); > static void ngx_http_v2_lingering_close_handler(ngx_event_t *rev); > > -static u_char *ngx_http_v2_state_proxy_protocol(ngx_http_v2_connection_t *h2c, > - u_char *pos, u_char *end); > static u_char *ngx_http_v2_state_preface(ngx_http_v2_connection_t *h2c, > u_char *pos, u_char *end); > static u_char *ngx_http_v2_state_preface_end(ngx_http_v2_connection_t *h2c, > @@ -232,6 +230,7 @@ static ngx_http_v2_parse_header_t ngx_h > void > ngx_http_v2_init(ngx_event_t *rev) > { > + u_char *p, *end; > ngx_connection_t *c; > ngx_pool_cleanup_t *cln; > ngx_http_connection_t *hc; > @@ -314,8 +313,7 @@ ngx_http_v2_init(ngx_event_t *rev) > return; > } > > - h2c->state.handler = hc->proxy_protocol ? ngx_http_v2_state_proxy_protocol > - : ngx_http_v2_state_preface; > + h2c->state.handler = ngx_http_v2_state_preface; > > ngx_queue_init(&h2c->waiting); > ngx_queue_init(&h2c->dependencies); > @@ -335,6 +333,23 @@ ngx_http_v2_init(ngx_event_t *rev) > c->idle = 1; > ngx_reusable_connection(c, 0); > > + if (c->buffer) { > + p = c->buffer->pos; > + end = c->buffer->last; > + > + do { > + p = h2c->state.handler(h2c, p, end); > + > + if (p == NULL) { > + return; > + } > + > + } while (p != end); > + > + h2c->total_bytes += p - c->buffer->pos; > + c->buffer->pos = p; > + } > + > ngx_http_v2_read_handler(rev); > } > > @@ -847,31 +862,10 @@ ngx_http_v2_lingering_close_handler(ngx_ > > > static u_char * > -ngx_http_v2_state_proxy_protocol(ngx_http_v2_connection_t *h2c, u_char *pos, > - u_char *end) > -{ > - ngx_log_t *log; > - > - log = h2c->connection->log; > - log->action = "reading PROXY protocol"; > - > - pos = ngx_proxy_protocol_read(h2c->connection, pos, end); > - > - log->action = "processing HTTP/2 connection"; > - > - if (pos == NULL) { > - return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR); > - } > - > - return ngx_http_v2_state_preface(h2c, pos, end); > -} > - > - > -static u_char * > ngx_http_v2_state_preface(ngx_http_v2_connection_t *h2c, u_char *pos, > u_char *end) > { > - static const u_char preface[] = "PRI * HTTP/2.0\r\n"; > + static const u_char preface[] = NGX_HTTP_V2_PREFACE_START; > > if ((size_t) (end - pos) < sizeof(preface) - 1) { > return ngx_http_v2_state_save(h2c, pos, end, ngx_http_v2_state_preface); > @@ -892,7 +886,7 @@ static u_char * > ngx_http_v2_state_preface_end(ngx_http_v2_connection_t *h2c, u_char *pos, > u_char *end) > { > - static const u_char preface[] = "\r\nSM\r\n\r\n"; > + static const u_char preface[] = NGX_HTTP_V2_PREFACE_END; > > if ((size_t) (end - pos) < sizeof(preface) - 1) { > return ngx_http_v2_state_save(h2c, pos, end, > @@ -3943,10 +3937,22 @@ static void > ngx_http_v2_run_request(ngx_http_request_t *r) > { > ngx_connection_t *fc; > + ngx_http_v2_srv_conf_t *h2scf; > ngx_http_v2_connection_t *h2c; > > fc = r->connection; > > + h2scf = ngx_http_get_module_srv_conf(r, ngx_http_v2_module); > + > + if (!h2scf->enable && !r->http_connection->addr_conf->http2) { > + ngx_log_error(NGX_LOG_INFO, fc->log, 0, > + "client attempted to request the server name " > + "for which the negotiated protocol is disabled"); > + > + ngx_http_finalize_request(r, NGX_HTTP_MISDIRECTED_REQUEST); > + goto failed; > + } > + > if (ngx_http_v2_construct_request_line(r) != NGX_OK) { > goto failed; > } > diff --git a/src/http/v2/ngx_http_v2.h b/src/http/v2/ngx_http_v2.h > --- a/src/http/v2/ngx_http_v2.h > +++ b/src/http/v2/ngx_http_v2.h > @@ -64,6 +64,16 @@ typedef u_char *(*ngx_http_v2_handler_pt > > > typedef struct { > + ngx_flag_t enable; > + size_t pool_size; > + ngx_uint_t concurrent_streams; > + ngx_uint_t concurrent_pushes; > + size_t preread_size; > + ngx_uint_t streams_index_mask; > +} ngx_http_v2_srv_conf_t; > + > + > +typedef struct { > ngx_str_t name; > ngx_str_t value; > } ngx_http_v2_header_t; > @@ -408,9 +418,17 @@ ngx_int_t ngx_http_v2_table_size(ngx_htt > #define NGX_HTTP_V2_USER_AGENT_INDEX 58 > #define NGX_HTTP_V2_VARY_INDEX 59 > > +#define NGX_HTTP_V2_PREFACE_START "PRI * HTTP/2.0\r\n" > +#define NGX_HTTP_V2_PREFACE_END "\r\nSM\r\n\r\n" > +#define NGX_HTTP_V2_PREFACE NGX_HTTP_V2_PREFACE_START \ > + NGX_HTTP_V2_PREFACE_END > + > > u_char *ngx_http_v2_string_encode(u_char *dst, u_char *src, size_t len, > u_char *tmp, ngx_uint_t lower); > > > +extern ngx_module_t ngx_http_v2_module; > + > + > #endif /* _NGX_HTTP_V2_H_INCLUDED_ */ > diff --git a/src/http/v2/ngx_http_v2_module.c b/src/http/v2/ngx_http_v2_module.c > --- a/src/http/v2/ngx_http_v2_module.c > +++ b/src/http/v2/ngx_http_v2_module.c > @@ -75,6 +75,13 @@ static ngx_conf_post_t ngx_http_v2_chun > > static ngx_command_t ngx_http_v2_commands[] = { > > + { ngx_string("http2"), > + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG, > + ngx_conf_set_flag_slot, > + NGX_HTTP_SRV_CONF_OFFSET, > + offsetof(ngx_http_v2_srv_conf_t, enable), > + NULL }, > + > { ngx_string("http2_recv_buffer_size"), > NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, > ngx_conf_set_size_slot, > @@ -314,6 +321,8 @@ ngx_http_v2_create_srv_conf(ngx_conf_t * > return NULL; > } > > + h2scf->enable = NGX_CONF_UNSET; > + > h2scf->pool_size = NGX_CONF_UNSET_SIZE; > > h2scf->concurrent_streams = NGX_CONF_UNSET_UINT; > @@ -333,6 +342,8 @@ ngx_http_v2_merge_srv_conf(ngx_conf_t *c > ngx_http_v2_srv_conf_t *prev = parent; > ngx_http_v2_srv_conf_t *conf = child; > > + ngx_conf_merge_value(conf->enable, prev->enable, 0); > + > ngx_conf_merge_size_value(conf->pool_size, prev->pool_size, 4096); > > ngx_conf_merge_uint_value(conf->concurrent_streams, > diff --git a/src/http/v2/ngx_http_v2_module.h b/src/http/v2/ngx_http_v2_module.h > --- a/src/http/v2/ngx_http_v2_module.h > +++ b/src/http/v2/ngx_http_v2_module.h > @@ -21,15 +21,6 @@ typedef struct { > > > typedef struct { > - size_t pool_size; > - ngx_uint_t concurrent_streams; > - ngx_uint_t concurrent_pushes; > - size_t preread_size; > - ngx_uint_t streams_index_mask; > -} ngx_http_v2_srv_conf_t; > - > - > -typedef struct { > size_t chunk_size; > > ngx_flag_t push_preload; > @@ -39,7 +30,4 @@ typedef struct { > } ngx_http_v2_loc_conf_t; > > > -extern ngx_module_t ngx_http_v2_module; > - > - > #endif /* _NGX_HTTP_V2_MODULE_H_INCLUDED_ */ Looks good. -- Maxim Dounin http://mdounin.ru/ From mdounin at mdounin.ru Wed Jun 7 16:41:34 2023 From: mdounin at mdounin.ru (Maxim Dounin) Date: Wed, 7 Jun 2023 19:41:34 +0300 Subject: [PATCH] HTTP/2: removed server push In-Reply-To: <7816CF05-E4E3-412E-900A-358031E1016A@nginx.com> References: <7816CF05-E4E3-412E-900A-358031E1016A@nginx.com> Message-ID: Hello! On Tue, Jun 06, 2023 at 08:29:07PM +0400, Sergey Kandaurov wrote: > > > On 4 Jun 2023, at 06:20, Maxim Dounin wrote: > > > > Hello! > > > > On Thu, Jun 01, 2023 at 05:58:38AM +0400, Sergey Kandaurov wrote: > > > >> # HG changeset patch > >> # User Sergey Kandaurov > >> # Date 1685584419 -14400 > >> # Thu Jun 01 05:53:39 2023 +0400 > >> # Node ID cd90a7bed6ebb098efe1e82b7ffa067e5f0e56c1 > >> # Parent 79ed88b1bf961a19b1efccd058fae440c3acbbdc > >> HTTP/2: removed server push. > >> > >> Although it has better implementation status than HTTP/3 server push, > >> it remains of limited use, with adoption numbers seen as negligible. > >> Per IETF 102 materials, server push was used only in 0.04% of sessions. > >> It was considered to be "difficult to use effectively" in RFC 9113. > >> Its use is further limited by badly matching to fetch/cache/connection > >> models in browsers, see related discussions linked from [1]. > >> > >> Server push was disabled in Chrome 106 [2]. > >> > >> The http2_push, http2_push_preload, and http2_max_concurrent_pushes > >> directives are made obsolete. > >> > >> [1] https://jakearchibald.com/2017/h2-push-tougher-than-i-thought/ > >> [2] https://chromestatus.com/feature/6302414934114304 > > > > It might make sense to mention ticket #2432. > > > > It might also make sense to mention changesets essentially > > reverted, notably 7201:641306096f5b and 7207:3d2b0b02bd3d. > > Applied, thanks. [...] > >> @@ -2198,7 +2168,6 @@ ngx_http_v2_state_settings_params(ngx_ht > >> { > >> ssize_t window_delta; > >> ngx_uint_t id, value; > >> - ngx_http_v2_srv_conf_t *h2scf; > >> ngx_http_v2_out_frame_t *frame; > >> > >> window_delta = 0; > >> @@ -2260,14 +2229,6 @@ ngx_http_v2_state_settings_params(ngx_ht > >> NGX_HTTP_V2_PROTOCOL_ERROR); > >> } > >> > >> - h2c->push_disabled = !value; > >> - break; > >> - > >> - case NGX_HTTP_V2_MAX_STREAMS_SETTING: > >> - h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx, > >> - ngx_http_v2_module); > >> - > >> - h2c->concurrent_pushes = ngx_min(value, h2scf->concurrent_pushes); > >> break; > >> > >> case NGX_HTTP_V2_HEADER_TABLE_SIZE_SETTING: > > > > Any specific reasons to keep NGX_HTTP_V2_ENABLE_PUSH_SETTING > > handling? > > Note that here remains a degenerate handling, used to reject invalid > values for SETTINGS_ENABLE_PUSH. IMHO, it makes sense to keep it, since > "Any value other than 0 or 1 MUST be treated as a connection error". Well, I doubt it make sense, and the "MUST" requirement looks like an issue in HTTP/2 specification to me, but I don't object keeping the check as we already have it. [...] > >> @@ -3711,45 +3504,40 @@ ngx_http_v2_parse_scheme(ngx_http_reques > >> static ngx_int_t > >> ngx_http_v2_parse_authority(ngx_http_request_t *r, ngx_str_t *value) > >> { > >> - return ngx_http_v2_parse_header(r, &ngx_http_v2_parse_headers[0], value); > >> -} > >> - > >> - > >> -static ngx_int_t > >> -ngx_http_v2_parse_header(ngx_http_request_t *r, > >> - ngx_http_v2_parse_header_t *header, ngx_str_t *value) > >> -{ > >> ngx_table_elt_t *h; > >> + ngx_http_header_t *hh; > >> ngx_http_core_main_conf_t *cmcf; > >> > >> + static ngx_str_t host = ngx_string("host"); > >> + > >> h = ngx_list_push(&r->headers_in.headers); > >> if (h == NULL) { > >> return NGX_ERROR; > >> } > >> > >> - h->key.len = header->name.len; > >> - h->key.data = header->name.data; > >> - h->lowcase_key = header->name.data; > >> - > >> - if (header->hh == NULL) { > >> - header->hash = ngx_hash_key(header->name.data, header->name.len); > >> - > >> - cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); > >> - > >> - header->hh = ngx_hash_find(&cmcf->headers_in_hash, header->hash, > >> - h->lowcase_key, h->key.len); > >> - if (header->hh == NULL) { > >> - return NGX_ERROR; > >> - } > >> - } > >> - > >> - h->hash = header->hash; > >> + h->key.len = host.len; > >> + h->key.data = host.data; > >> + h->lowcase_key = host.data; > >> + > >> + h->hash = ngx_hash(ngx_hash(ngx_hash('h', 'o'), 's'), 't'); > >> > > > > For the record: order of h->key/h->lowcase_key/h->hash assignments > > differs from the one used before 7207:3d2b0b02bd3d, but this is > > not important, and I agree that the new order is better. > > Yep, it uses to preserve the order, not revert to pre-3d2b0b02bd3d. > Well, it can be rearranged to be consistent with the current order > of assignments in ngx_http_v2_construct_cookie_header(): > > diff --git a/src/http/v2/ngx_http_v2.c b/src/http/v2/ngx_http_v2.c > --- a/src/http/v2/ngx_http_v2.c > +++ b/src/http/v2/ngx_http_v2.c > @@ -3509,15 +3509,16 @@ ngx_http_v2_parse_authority(ngx_http_req > return NGX_ERROR; > } > > + h->hash = ngx_hash(ngx_hash(ngx_hash('h', 'o'), 's'), 't'); > + > h->key.len = host.len; > h->key.data = host.data; > - h->lowcase_key = host.data; > - > - h->hash = ngx_hash(ngx_hash(ngx_hash('h', 'o'), 's'), 't'); > > h->value.len = value->len; > h->value.data = value->data; > > + h->lowcase_key = host.data; > + > cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); > > hh = ngx_hash_find(&cmcf->headers_in_hash, h->hash, > > (just in case, not applied) I missed that we have similar code in ngx_http_v2_construct_cookie_header(). It make sense to apply it then, just for consistency. [...] > # HG changeset patch > # User Sergey Kandaurov > # Date 1686068541 -14400 > # Tue Jun 06 20:22:21 2023 +0400 > # Node ID be9b4d218cc7f6671482a65d781aded278bbc801 > # Parent 79ed88b1bf961a19b1efccd058fae440c3acbbdc > HTTP/2: removed server push (ticket #2432). > > Although it has better implementation status than HTTP/3 server push, > it remains of limited use, with adoption numbers seen as negligible. > Per IETF 102 materials, server push was used only in 0.04% of sessions. > It was considered to be "difficult to use effectively" in RFC 9113. > Its use is further limited by badly matching to fetch/cache/connection > models in browsers, see related discussions linked from [1]. > > Server push was disabled in Chrome 106 [2]. > > The http2_push, http2_push_preload, and http2_max_concurrent_pushes > directives are made obsolete. In particular, this essentially reverts > 7201:641306096f5b and 7207:3d2b0b02bd3d. > > [1] https://jakearchibald.com/2017/h2-push-tougher-than-i-thought/ > [2] https://chromestatus.com/feature/6302414934114304 > > diff --git a/auto/modules b/auto/modules > --- a/auto/modules > +++ b/auto/modules > @@ -423,7 +423,6 @@ if [ $HTTP = YES ]; then > > if [ $HTTP_V2 = YES ]; then > have=NGX_HTTP_V2 . auto/have > - have=NGX_HTTP_HEADERS . auto/have > > ngx_module_name=ngx_http_v2_module > ngx_module_incs=src/http/v2 > @@ -444,7 +443,6 @@ if [ $HTTP = YES ]; then > HTTP_SSL=YES > > have=NGX_HTTP_V3 . auto/have > - have=NGX_HTTP_HEADERS . auto/have > > ngx_module_name=ngx_http_v3_module > ngx_module_incs=src/http/v3 > diff --git a/src/http/v2/ngx_http_v2.c b/src/http/v2/ngx_http_v2.c > --- a/src/http/v2/ngx_http_v2.c > +++ b/src/http/v2/ngx_http_v2.c > @@ -11,14 +11,6 @@ > #include > > > -typedef struct { > - ngx_str_t name; > - ngx_uint_t offset; > - ngx_uint_t hash; > - ngx_http_header_t *hh; > -} ngx_http_v2_parse_header_t; > - > - > /* errors */ > #define NGX_HTTP_V2_NO_ERROR 0x0 > #define NGX_HTTP_V2_PROTOCOL_ERROR 0x1 > @@ -126,7 +118,7 @@ static ngx_int_t ngx_http_v2_parse_int(n > u_char **pos, u_char *end, ngx_uint_t prefix); > > static ngx_http_v2_stream_t *ngx_http_v2_create_stream( > - ngx_http_v2_connection_t *h2c, ngx_uint_t push); > + ngx_http_v2_connection_t *h2c); > static ngx_http_v2_node_t *ngx_http_v2_get_node_by_id( > ngx_http_v2_connection_t *h2c, ngx_uint_t sid, ngx_uint_t alloc); > static ngx_http_v2_node_t *ngx_http_v2_get_closed_node( > @@ -162,14 +154,11 @@ static ngx_int_t ngx_http_v2_parse_schem > ngx_str_t *value); > static ngx_int_t ngx_http_v2_parse_authority(ngx_http_request_t *r, > ngx_str_t *value); > -static ngx_int_t ngx_http_v2_parse_header(ngx_http_request_t *r, > - ngx_http_v2_parse_header_t *header, ngx_str_t *value); > static ngx_int_t ngx_http_v2_construct_request_line(ngx_http_request_t *r); > static ngx_int_t ngx_http_v2_cookie(ngx_http_request_t *r, > ngx_http_v2_header_t *header); > static ngx_int_t ngx_http_v2_construct_cookie_header(ngx_http_request_t *r); > static void ngx_http_v2_run_request(ngx_http_request_t *r); > -static void ngx_http_v2_run_request_handler(ngx_event_t *ev); > static ngx_int_t ngx_http_v2_process_request_body(ngx_http_request_t *r, > u_char *pos, size_t size, ngx_uint_t last, ngx_uint_t flush); > static ngx_int_t ngx_http_v2_filter_request_body(ngx_http_request_t *r); > @@ -210,23 +199,6 @@ static ngx_http_v2_handler_pt ngx_http_v > (sizeof(ngx_http_v2_frame_states) / sizeof(ngx_http_v2_handler_pt)) > > > -static ngx_http_v2_parse_header_t ngx_http_v2_parse_headers[] = { > - { ngx_string("host"), > - offsetof(ngx_http_headers_in_t, host), 0, NULL }, > - > - { ngx_string("accept-encoding"), > - offsetof(ngx_http_headers_in_t, accept_encoding), 0, NULL }, > - > - { ngx_string("accept-language"), > - offsetof(ngx_http_headers_in_t, accept_language), 0, NULL }, > - > - { ngx_string("user-agent"), > - offsetof(ngx_http_headers_in_t, user_agent), 0, NULL }, > - > - { ngx_null_string, 0, 0, NULL } > -}; > - > - > void > ngx_http_v2_init(ngx_event_t *rev) > { > @@ -275,7 +247,6 @@ ngx_http_v2_init(ngx_event_t *rev) > > h2scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v2_module); > > - h2c->concurrent_pushes = h2scf->concurrent_pushes; > h2c->priority_limit = ngx_max(h2scf->concurrent_streams, 100); > > h2c->pool = ngx_create_pool(h2scf->pool_size, h2c->connection->log); > @@ -384,7 +355,7 @@ ngx_http_v2_read_handler(ngx_event_t *re > return; > } > > - if (!h2c->processing && !h2c->pushing) { > + if (!h2c->processing) { > ngx_http_v2_finalize_connection(h2c, NGX_HTTP_V2_NO_ERROR); > return; > } > @@ -427,9 +398,7 @@ ngx_http_v2_read_handler(ngx_event_t *re > break; > } > > - if (n == 0 > - && (h2c->state.incomplete || h2c->processing || h2c->pushing)) > - { > + if (n == 0 && (h2c->state.incomplete || h2c->processing)) { > ngx_log_error(NGX_LOG_INFO, c->log, 0, > "client prematurely closed connection"); > } > @@ -652,7 +621,7 @@ ngx_http_v2_handle_connection(ngx_http_v > ngx_connection_t *c; > ngx_http_core_loc_conf_t *clcf; > > - if (h2c->last_out || h2c->processing || h2c->pushing) { > + if (h2c->last_out || h2c->processing) { > return; > } > > @@ -1337,7 +1306,7 @@ ngx_http_v2_state_headers(ngx_http_v2_co > h2c->closed_nodes--; > } > > - stream = ngx_http_v2_create_stream(h2c, 0); > + stream = ngx_http_v2_create_stream(h2c); > if (stream == NULL) { > return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR); > } > @@ -2126,11 +2095,6 @@ ngx_http_v2_state_rst_stream(ngx_http_v2 > "client canceled stream %ui", h2c->state.sid); > break; > > - case NGX_HTTP_V2_REFUSED_STREAM: > - ngx_log_error(NGX_LOG_INFO, fc->log, 0, > - "client refused stream %ui", h2c->state.sid); > - break; > - > case NGX_HTTP_V2_INTERNAL_ERROR: > ngx_log_error(NGX_LOG_INFO, fc->log, 0, > "client terminated stream %ui due to internal error", > @@ -2198,7 +2162,6 @@ ngx_http_v2_state_settings_params(ngx_ht > { > ssize_t window_delta; > ngx_uint_t id, value; > - ngx_http_v2_srv_conf_t *h2scf; > ngx_http_v2_out_frame_t *frame; > > window_delta = 0; > @@ -2260,14 +2223,6 @@ ngx_http_v2_state_settings_params(ngx_ht > NGX_HTTP_V2_PROTOCOL_ERROR); > } > > - h2c->push_disabled = !value; > - break; > - > - case NGX_HTTP_V2_MAX_STREAMS_SETTING: > - h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx, > - ngx_http_v2_module); > - > - h2c->concurrent_pushes = ngx_min(value, h2scf->concurrent_pushes); > break; > > case NGX_HTTP_V2_HEADER_TABLE_SIZE_SETTING: > @@ -2722,163 +2677,6 @@ ngx_http_v2_parse_int(ngx_http_v2_connec > } > > > -ngx_http_v2_stream_t * > -ngx_http_v2_push_stream(ngx_http_v2_stream_t *parent, ngx_str_t *path) > -{ > - ngx_int_t rc; > - ngx_str_t value; > - ngx_pool_t *pool; > - ngx_uint_t index; > - ngx_table_elt_t **h; > - ngx_connection_t *fc; > - ngx_http_request_t *r; > - ngx_http_v2_node_t *node; > - ngx_http_v2_stream_t *stream; > - ngx_http_v2_srv_conf_t *h2scf; > - ngx_http_v2_connection_t *h2c; > - ngx_http_v2_parse_header_t *header; > - > - h2c = parent->connection; > - > - pool = ngx_create_pool(1024, h2c->connection->log); > - if (pool == NULL) { > - goto rst_stream; > - } > - > - node = ngx_http_v2_get_node_by_id(h2c, h2c->last_push, 1); > - > - if (node == NULL) { > - ngx_destroy_pool(pool); > - goto rst_stream; > - } > - > - stream = ngx_http_v2_create_stream(h2c, 1); > - if (stream == NULL) { > - > - if (node->parent == NULL) { > - h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx, > - ngx_http_v2_module); > - > - index = ngx_http_v2_index(h2scf, h2c->last_push); > - h2c->streams_index[index] = node->index; > - > - ngx_queue_insert_tail(&h2c->closed, &node->reuse); > - h2c->closed_nodes++; > - } > - > - ngx_destroy_pool(pool); > - goto rst_stream; > - } > - > - if (node->parent) { > - ngx_queue_remove(&node->reuse); > - h2c->closed_nodes--; > - } > - > - stream->pool = pool; > - > - r = stream->request; > - fc = r->connection; > - > - stream->in_closed = 1; > - stream->node = node; > - > - node->stream = stream; > - > - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, > - "http2 push stream sid:%ui " > - "depends on %ui excl:0 weight:16", > - h2c->last_push, parent->node->id); > - > - node->weight = NGX_HTTP_V2_DEFAULT_WEIGHT; > - ngx_http_v2_set_dependency(h2c, node, parent->node->id, 0); > - > - r->method_name = ngx_http_core_get_method; > - r->method = NGX_HTTP_GET; > - > - r->schema.data = ngx_pstrdup(pool, &parent->request->schema); > - if (r->schema.data == NULL) { > - goto close; > - } > - > - r->schema.len = parent->request->schema.len; > - > - value.data = ngx_pstrdup(pool, path); > - if (value.data == NULL) { > - goto close; > - } > - > - value.len = path->len; > - > - rc = ngx_http_v2_parse_path(r, &value); > - > - if (rc != NGX_OK) { > - goto error; > - } > - > - for (header = ngx_http_v2_parse_headers; header->name.len; header++) { > - h = (ngx_table_elt_t **) > - ((char *) &parent->request->headers_in + header->offset); > - > - if (*h == NULL) { > - continue; > - } > - > - value.len = (*h)->value.len; > - > - value.data = ngx_pnalloc(pool, value.len + 1); > - if (value.data == NULL) { > - goto close; > - } > - > - ngx_memcpy(value.data, (*h)->value.data, value.len); > - value.data[value.len] = '\0'; > - > - rc = ngx_http_v2_parse_header(r, header, &value); > - > - if (rc != NGX_OK) { > - goto error; > - } > - } > - > - fc->write->handler = ngx_http_v2_run_request_handler; > - ngx_post_event(fc->write, &ngx_posted_events); > - > - return stream; > - > -error: > - > - if (rc == NGX_ABORT) { > - /* header handler has already finalized request */ > - ngx_http_run_posted_requests(fc); > - return NULL; > - } > - > - if (rc == NGX_DECLINED) { > - ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); > - ngx_http_run_posted_requests(fc); > - return NULL; > - } > - > -close: > - > - ngx_http_v2_close_stream(stream, NGX_HTTP_INTERNAL_SERVER_ERROR); > - > - return NULL; > - > -rst_stream: > - > - if (ngx_http_v2_send_rst_stream(h2c, h2c->last_push, > - NGX_HTTP_INTERNAL_SERVER_ERROR) > - != NGX_OK) > - { > - h2c->connection->error = 1; > - } > - > - return NULL; > -} > - > - > static ngx_int_t > ngx_http_v2_send_settings(ngx_http_v2_connection_t *h2c) > { > @@ -3150,7 +2948,7 @@ ngx_http_v2_frame_handler(ngx_http_v2_co > > > static ngx_http_v2_stream_t * > -ngx_http_v2_create_stream(ngx_http_v2_connection_t *h2c, ngx_uint_t push) > +ngx_http_v2_create_stream(ngx_http_v2_connection_t *h2c) > { > ngx_log_t *log; > ngx_event_t *rev, *wev; > @@ -3205,13 +3003,7 @@ ngx_http_v2_create_stream(ngx_http_v2_co > ngx_memcpy(log, h2c->connection->log, sizeof(ngx_log_t)); > > log->data = ctx; > - > - if (push) { > - log->action = "processing pushed request headers"; > - > - } else { > - log->action = "reading client request headers"; > - } > + log->action = "reading client request headers"; > > ngx_memzero(rev, sizeof(ngx_event_t)); > > @@ -3283,12 +3075,7 @@ ngx_http_v2_create_stream(ngx_http_v2_co > stream->send_window = h2c->init_window; > stream->recv_window = h2scf->preread_size; > > - if (push) { > - h2c->pushing++; > - > - } else { > - h2c->processing++; > - } > + h2c->processing++; > > h2c->priority_limit += h2scf->concurrent_streams; > > @@ -3711,45 +3498,40 @@ ngx_http_v2_parse_scheme(ngx_http_reques > static ngx_int_t > ngx_http_v2_parse_authority(ngx_http_request_t *r, ngx_str_t *value) > { > - return ngx_http_v2_parse_header(r, &ngx_http_v2_parse_headers[0], value); > -} > - > - > -static ngx_int_t > -ngx_http_v2_parse_header(ngx_http_request_t *r, > - ngx_http_v2_parse_header_t *header, ngx_str_t *value) > -{ > ngx_table_elt_t *h; > + ngx_http_header_t *hh; > ngx_http_core_main_conf_t *cmcf; > > + static ngx_str_t host = ngx_string("host"); > + > h = ngx_list_push(&r->headers_in.headers); > if (h == NULL) { > return NGX_ERROR; > } > > - h->key.len = header->name.len; > - h->key.data = header->name.data; > - h->lowcase_key = header->name.data; > - > - if (header->hh == NULL) { > - header->hash = ngx_hash_key(header->name.data, header->name.len); > - > - cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); > - > - header->hh = ngx_hash_find(&cmcf->headers_in_hash, header->hash, > - h->lowcase_key, h->key.len); > - if (header->hh == NULL) { > - return NGX_ERROR; > - } > - } > - > - h->hash = header->hash; > + h->key.len = host.len; > + h->key.data = host.data; > + h->lowcase_key = host.data; > + > + h->hash = ngx_hash(ngx_hash(ngx_hash('h', 'o'), 's'), 't'); > > h->value.len = value->len; > h->value.data = value->data; > > - if (header->hh->handler(r, h, header->hh->offset) != NGX_OK) { > - /* header handler has already finalized request */ > + cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); > + > + hh = ngx_hash_find(&cmcf->headers_in_hash, h->hash, > + h->lowcase_key, h->key.len); > + > + if (hh == NULL) { > + return NGX_ERROR; > + } > + > + if (hh->handler(r, h, hh->offset) != NGX_OK) { > + /* > + * request has been finalized already > + * in ngx_http_process_host() > + */ > return NGX_ABORT; > } > > @@ -3992,22 +3774,6 @@ failed: > } > > > -static void > -ngx_http_v2_run_request_handler(ngx_event_t *ev) > -{ > - ngx_connection_t *fc; > - ngx_http_request_t *r; > - > - fc = ev->data; > - r = fc->data; > - > - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0, > - "http2 run request handler"); > - > - ngx_http_v2_run_request(r); > -} > - > - > ngx_int_t > ngx_http_v2_read_request_body(ngx_http_request_t *r) > { > @@ -4611,7 +4377,6 @@ void > ngx_http_v2_close_stream(ngx_http_v2_stream_t *stream, ngx_int_t rc) > { > ngx_pool_t *pool; > - ngx_uint_t push; > ngx_event_t *ev; > ngx_connection_t *fc; > ngx_http_v2_node_t *node; > @@ -4620,10 +4385,9 @@ ngx_http_v2_close_stream(ngx_http_v2_str > h2c = stream->connection; > node = stream->node; > > - ngx_log_debug4(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, > - "http2 close stream %ui, queued %ui, " > - "processing %ui, pushing %ui", > - node->id, stream->queued, h2c->processing, h2c->pushing); > + ngx_log_debug3(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, > + "http2 close stream %ui, queued %ui, processing %ui", > + node->id, stream->queued, h2c->processing); > > fc = stream->request->connection; > > @@ -4658,8 +4422,6 @@ ngx_http_v2_close_stream(ngx_http_v2_str > h2c->state.stream = NULL; > } > > - push = stream->node->id % 2 == 0; > - > node->stream = NULL; > > ngx_queue_insert_tail(&h2c->closed, &node->reuse); > @@ -4709,14 +4471,9 @@ ngx_http_v2_close_stream(ngx_http_v2_str > fc->data = h2c->free_fake_connections; > h2c->free_fake_connections = fc; > > - if (push) { > - h2c->pushing--; > - > - } else { > - h2c->processing--; > - } > - > - if (h2c->processing || h2c->pushing || h2c->blocked) { > + h2c->processing--; > + > + if (h2c->processing || h2c->blocked) { > return; > } > > @@ -4892,7 +4649,7 @@ ngx_http_v2_finalize_connection(ngx_http > } > } > > - if (!h2c->processing && !h2c->pushing) { > + if (!h2c->processing) { > goto done; > } > > @@ -4940,7 +4697,7 @@ ngx_http_v2_finalize_connection(ngx_http > > h2c->blocked = 0; > > - if (h2c->processing || h2c->pushing) { > + if (h2c->processing) { > c->error = 1; > return; > } > diff --git a/src/http/v2/ngx_http_v2.h b/src/http/v2/ngx_http_v2.h > --- a/src/http/v2/ngx_http_v2.h > +++ b/src/http/v2/ngx_http_v2.h > @@ -24,8 +24,6 @@ > #define NGX_HTTP_V2_MAX_FIELD \ > (127 + (1 << (NGX_HTTP_V2_INT_OCTETS - 1) * 7) - 1) > > -#define NGX_HTTP_V2_STREAM_ID_SIZE 4 > - > #define NGX_HTTP_V2_FRAME_HEADER_SIZE 9 > > /* frame types */ > @@ -67,7 +65,6 @@ typedef struct { > ngx_flag_t enable; > size_t pool_size; > ngx_uint_t concurrent_streams; > - ngx_uint_t concurrent_pushes; > size_t preread_size; > ngx_uint_t streams_index_mask; > } ngx_http_v2_srv_conf_t; > @@ -136,9 +133,6 @@ struct ngx_http_v2_connection_s { > ngx_uint_t idle; > ngx_uint_t priority_limit; > > - ngx_uint_t pushing; > - ngx_uint_t concurrent_pushes; > - > size_t send_window; > size_t recv_window; > size_t init_window; > @@ -165,7 +159,6 @@ struct ngx_http_v2_connection_s { > > ngx_uint_t closed_nodes; > ngx_uint_t last_sid; > - ngx_uint_t last_push; > > time_t lingering_time; > > @@ -173,7 +166,6 @@ struct ngx_http_v2_connection_s { > unsigned table_update:1; > unsigned blocked:1; > unsigned goaway:1; > - unsigned push_disabled:1; > }; > > > @@ -303,9 +295,6 @@ void ngx_http_v2_init(ngx_event_t *rev); > ngx_int_t ngx_http_v2_read_request_body(ngx_http_request_t *r); > ngx_int_t ngx_http_v2_read_unbuffered_request_body(ngx_http_request_t *r); > > -ngx_http_v2_stream_t *ngx_http_v2_push_stream(ngx_http_v2_stream_t *parent, > - ngx_str_t *path); > - > void ngx_http_v2_close_stream(ngx_http_v2_stream_t *stream, ngx_int_t rc); > > ngx_int_t ngx_http_v2_send_output_queue(ngx_http_v2_connection_t *h2c); > @@ -407,15 +396,12 @@ ngx_int_t ngx_http_v2_table_size(ngx_htt > #define NGX_HTTP_V2_STATUS_404_INDEX 13 > #define NGX_HTTP_V2_STATUS_500_INDEX 14 > > -#define NGX_HTTP_V2_ACCEPT_ENCODING_INDEX 16 > -#define NGX_HTTP_V2_ACCEPT_LANGUAGE_INDEX 17 > #define NGX_HTTP_V2_CONTENT_LENGTH_INDEX 28 > #define NGX_HTTP_V2_CONTENT_TYPE_INDEX 31 > #define NGX_HTTP_V2_DATE_INDEX 33 > #define NGX_HTTP_V2_LAST_MODIFIED_INDEX 44 > #define NGX_HTTP_V2_LOCATION_INDEX 46 > #define NGX_HTTP_V2_SERVER_INDEX 54 > -#define NGX_HTTP_V2_USER_AGENT_INDEX 58 > #define NGX_HTTP_V2_VARY_INDEX 59 > > #define NGX_HTTP_V2_PREFACE_START "PRI * HTTP/2.0\r\n" > diff --git a/src/http/v2/ngx_http_v2_filter_module.c b/src/http/v2/ngx_http_v2_filter_module.c > --- a/src/http/v2/ngx_http_v2_filter_module.c > +++ b/src/http/v2/ngx_http_v2_filter_module.c > @@ -27,39 +27,8 @@ > #define NGX_HTTP_V2_NO_TRAILERS (ngx_http_v2_out_frame_t *) -1 > > > -typedef struct { > - ngx_str_t name; > - u_char index; > - ngx_uint_t offset; > -} ngx_http_v2_push_header_t; > - > - > -static ngx_http_v2_push_header_t ngx_http_v2_push_headers[] = { > - { ngx_string(":authority"), NGX_HTTP_V2_AUTHORITY_INDEX, > - offsetof(ngx_http_headers_in_t, host) }, > - > - { ngx_string("accept-encoding"), NGX_HTTP_V2_ACCEPT_ENCODING_INDEX, > - offsetof(ngx_http_headers_in_t, accept_encoding) }, > - > - { ngx_string("accept-language"), NGX_HTTP_V2_ACCEPT_LANGUAGE_INDEX, > - offsetof(ngx_http_headers_in_t, accept_language) }, > - > - { ngx_string("user-agent"), NGX_HTTP_V2_USER_AGENT_INDEX, > - offsetof(ngx_http_headers_in_t, user_agent) }, > -}; > - > -#define NGX_HTTP_V2_PUSH_HEADERS \ > - (sizeof(ngx_http_v2_push_headers) / sizeof(ngx_http_v2_push_header_t)) > - > - > -static ngx_int_t ngx_http_v2_push_resources(ngx_http_request_t *r); > -static ngx_int_t ngx_http_v2_push_resource(ngx_http_request_t *r, > - ngx_str_t *path, ngx_str_t *binary); > - > static ngx_http_v2_out_frame_t *ngx_http_v2_create_headers_frame( > ngx_http_request_t *r, u_char *pos, u_char *end, ngx_uint_t fin); > -static ngx_http_v2_out_frame_t *ngx_http_v2_create_push_frame( > - ngx_http_request_t *r, u_char *pos, u_char *end); > static ngx_http_v2_out_frame_t *ngx_http_v2_create_trailers_frame( > ngx_http_request_t *r); > > @@ -82,8 +51,6 @@ static ngx_inline ngx_int_t ngx_http_v2_ > > static ngx_int_t ngx_http_v2_headers_frame_handler( > ngx_http_v2_connection_t *h2c, ngx_http_v2_out_frame_t *frame); > -static ngx_int_t ngx_http_v2_push_frame_handler( > - ngx_http_v2_connection_t *h2c, ngx_http_v2_out_frame_t *frame); > static ngx_int_t ngx_http_v2_data_frame_handler( > ngx_http_v2_connection_t *h2c, ngx_http_v2_out_frame_t *frame); > static ngx_inline void ngx_http_v2_handle_frame( > @@ -244,15 +211,6 @@ ngx_http_v2_header_filter(ngx_http_reque > > h2c = stream->connection; > > - if (!h2c->push_disabled && !h2c->goaway > - && stream->node->id % 2 == 1 > - && r->method != NGX_HTTP_HEAD) > - { > - if (ngx_http_v2_push_resources(r) != NGX_OK) { > - return NGX_ERROR; > - } > - } > - > len = h2c->table_update ? 1 : 0; > > len += status ? 1 : 1 + ngx_http_v2_literal_size("418"); > @@ -653,7 +611,7 @@ ngx_http_v2_header_filter(ngx_http_reque > > ngx_http_v2_queue_blocked_frame(h2c, frame); > > - stream->queued++; > + stream->queued = 1; > > cln = ngx_http_cleanup_add(r, 0); > if (cln == NULL) { > @@ -671,409 +629,6 @@ ngx_http_v2_header_filter(ngx_http_reque > } > > > -static ngx_int_t > -ngx_http_v2_push_resources(ngx_http_request_t *r) > -{ > - u_char *start, *end, *last; > - ngx_int_t rc; > - ngx_str_t path; > - ngx_uint_t i, push; > - ngx_table_elt_t *h; > - ngx_http_v2_loc_conf_t *h2lcf; > - ngx_http_complex_value_t *pushes; > - ngx_str_t binary[NGX_HTTP_V2_PUSH_HEADERS]; > - > - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, > - "http2 push resources"); > - > - ngx_memzero(binary, NGX_HTTP_V2_PUSH_HEADERS * sizeof(ngx_str_t)); > - > - h2lcf = ngx_http_get_module_loc_conf(r, ngx_http_v2_module); > - > - if (h2lcf->pushes) { > - pushes = h2lcf->pushes->elts; > - > - for (i = 0; i < h2lcf->pushes->nelts; i++) { > - > - if (ngx_http_complex_value(r, &pushes[i], &path) != NGX_OK) { > - return NGX_ERROR; > - } > - > - if (path.len == 0) { > - continue; > - } > - > - if (path.len == 3 && ngx_strncmp(path.data, "off", 3) == 0) { > - continue; > - } > - > - rc = ngx_http_v2_push_resource(r, &path, binary); > - > - if (rc == NGX_ERROR) { > - return NGX_ERROR; > - } > - > - if (rc == NGX_ABORT) { > - return NGX_OK; > - } > - > - /* NGX_OK, NGX_DECLINED */ > - } > - } > - > - if (!h2lcf->push_preload) { > - return NGX_OK; > - } > - > - for (h = r->headers_out.link; h; h = h->next) { > - > - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, > - "http2 parse link: \"%V\"", &h->value); > - > - start = h->value.data; > - end = h->value.data + h->value.len; > - > - next_link: > - > - while (start < end && *start == ' ') { start++; } > - > - if (start == end || *start++ != '<') { > - continue; > - } > - > - while (start < end && *start == ' ') { start++; } > - > - for (last = start; last < end && *last != '>'; last++) { > - /* void */ > - } > - > - if (last == start || last == end) { > - continue; > - } > - > - path.len = last - start; > - path.data = start; > - > - start = last + 1; > - > - while (start < end && *start == ' ') { start++; } > - > - if (start == end) { > - continue; > - } > - > - if (*start == ',') { > - start++; > - goto next_link; > - } > - > - if (*start++ != ';') { > - continue; > - } > - > - last = ngx_strlchr(start, end, ','); > - > - if (last == NULL) { > - last = end; > - } > - > - push = 0; > - > - for ( ;; ) { > - > - while (start < last && *start == ' ') { start++; } > - > - if (last - start >= 6 > - && ngx_strncasecmp(start, (u_char *) "nopush", 6) == 0) > - { > - start += 6; > - > - if (start == last || *start == ' ' || *start == ';') { > - push = 0; > - break; > - } > - > - goto next_param; > - } > - > - if (last - start >= 11 > - && ngx_strncasecmp(start, (u_char *) "rel=preload", 11) == 0) > - { > - start += 11; > - > - if (start == last || *start == ' ' || *start == ';') { > - push = 1; > - } > - > - goto next_param; > - } > - > - if (last - start >= 4 > - && ngx_strncasecmp(start, (u_char *) "rel=", 4) == 0) > - { > - start += 4; > - > - while (start < last && *start == ' ') { start++; } > - > - if (start == last || *start++ != '"') { > - goto next_param; > - } > - > - for ( ;; ) { > - > - while (start < last && *start == ' ') { start++; } > - > - if (last - start >= 7 > - && ngx_strncasecmp(start, (u_char *) "preload", 7) == 0) > - { > - start += 7; > - > - if (start < last && (*start == ' ' || *start == '"')) { > - push = 1; > - break; > - } > - } > - > - while (start < last && *start != ' ' && *start != '"') { > - start++; > - } > - > - if (start == last) { > - break; > - } > - > - if (*start == '"') { > - break; > - } > - > - start++; > - } > - } > - > - next_param: > - > - start = ngx_strlchr(start, last, ';'); > - > - if (start == NULL) { > - break; > - } > - > - start++; > - } > - > - if (push) { > - while (path.len && path.data[path.len - 1] == ' ') { > - path.len--; > - } > - } > - > - if (push && path.len > - && !(path.len > 1 && path.data[0] == '/' && path.data[1] == '/')) > - { > - rc = ngx_http_v2_push_resource(r, &path, binary); > - > - if (rc == NGX_ERROR) { > - return NGX_ERROR; > - } > - > - if (rc == NGX_ABORT) { > - return NGX_OK; > - } > - > - /* NGX_OK, NGX_DECLINED */ > - } > - > - if (last < end) { > - start = last + 1; > - goto next_link; > - } > - } > - > - return NGX_OK; > -} > - > - > -static ngx_int_t > -ngx_http_v2_push_resource(ngx_http_request_t *r, ngx_str_t *path, > - ngx_str_t *binary) > -{ > - u_char *start, *pos, *tmp; > - size_t len; > - ngx_str_t *value; > - ngx_uint_t i; > - ngx_table_elt_t **h; > - ngx_connection_t *fc; > - ngx_http_v2_stream_t *stream; > - ngx_http_v2_out_frame_t *frame; > - ngx_http_v2_connection_t *h2c; > - ngx_http_v2_push_header_t *ph; > - > - fc = r->connection; > - > - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0, "http2 push resource"); > - > - stream = r->stream; > - h2c = stream->connection; > - > - if (!ngx_path_separator(path->data[0])) { > - ngx_log_error(NGX_LOG_WARN, fc->log, 0, > - "non-absolute path \"%V\" not pushed", path); > - return NGX_DECLINED; > - } > - > - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, > - "http2 pushing:%ui limit:%ui", > - h2c->pushing, h2c->concurrent_pushes); > - > - if (h2c->pushing >= h2c->concurrent_pushes) { > - return NGX_ABORT; > - } > - > - if (h2c->last_push == 0x7ffffffe) { > - return NGX_ABORT; > - } > - > - if (path->len > NGX_HTTP_V2_MAX_FIELD) { > - return NGX_DECLINED; > - } > - > - if (r->headers_in.host == NULL) { > - return NGX_ABORT; > - } > - > - ph = ngx_http_v2_push_headers; > - > - len = ngx_max(r->schema.len, path->len); > - > - if (binary[0].len) { > - tmp = ngx_palloc(r->pool, len); > - if (tmp == NULL) { > - return NGX_ERROR; > - } > - > - } else { > - for (i = 0; i < NGX_HTTP_V2_PUSH_HEADERS; i++) { > - h = (ngx_table_elt_t **) ((char *) &r->headers_in + ph[i].offset); > - > - if (*h) { > - len = ngx_max(len, (*h)->value.len); > - } > - } > - > - tmp = ngx_palloc(r->pool, len); > - if (tmp == NULL) { > - return NGX_ERROR; > - } > - > - for (i = 0; i < NGX_HTTP_V2_PUSH_HEADERS; i++) { > - h = (ngx_table_elt_t **) ((char *) &r->headers_in + ph[i].offset); > - > - if (*h == NULL) { > - continue; > - } > - > - value = &(*h)->value; > - > - len = 1 + NGX_HTTP_V2_INT_OCTETS + value->len; > - > - pos = ngx_pnalloc(r->pool, len); > - if (pos == NULL) { > - return NGX_ERROR; > - } > - > - binary[i].data = pos; > - > - *pos++ = ngx_http_v2_inc_indexed(ph[i].index); > - pos = ngx_http_v2_write_value(pos, value->data, value->len, tmp); > - > - binary[i].len = pos - binary[i].data; > - } > - } > - > - len = (h2c->table_update ? 1 : 0) > - + 1 > - + 1 + NGX_HTTP_V2_INT_OCTETS + path->len > - + 1 + NGX_HTTP_V2_INT_OCTETS + r->schema.len; > - > - for (i = 0; i < NGX_HTTP_V2_PUSH_HEADERS; i++) { > - len += binary[i].len; > - } > - > - pos = ngx_pnalloc(r->pool, len); > - if (pos == NULL) { > - return NGX_ERROR; > - } > - > - start = pos; > - > - if (h2c->table_update) { > - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0, > - "http2 table size update: 0"); > - *pos++ = (1 << 5) | 0; > - h2c->table_update = 0; > - } > - > - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0, > - "http2 push header: \":method: GET\""); > - > - *pos++ = ngx_http_v2_indexed(NGX_HTTP_V2_METHOD_GET_INDEX); > - > - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, fc->log, 0, > - "http2 push header: \":path: %V\"", path); > - > - *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_PATH_INDEX); > - pos = ngx_http_v2_write_value(pos, path->data, path->len, tmp); > - > - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, fc->log, 0, > - "http2 push header: \":scheme: %V\"", &r->schema); > - > - if (r->schema.len == 5 && ngx_strncmp(r->schema.data, "https", 5) == 0) { > - *pos++ = ngx_http_v2_indexed(NGX_HTTP_V2_SCHEME_HTTPS_INDEX); > - > - } else if (r->schema.len == 4 > - && ngx_strncmp(r->schema.data, "http", 4) == 0) > - { > - *pos++ = ngx_http_v2_indexed(NGX_HTTP_V2_SCHEME_HTTP_INDEX); > - > - } else { > - *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_SCHEME_HTTP_INDEX); > - pos = ngx_http_v2_write_value(pos, r->schema.data, r->schema.len, tmp); > - } > - > - for (i = 0; i < NGX_HTTP_V2_PUSH_HEADERS; i++) { > - h = (ngx_table_elt_t **) ((char *) &r->headers_in + ph[i].offset); > - > - if (*h == NULL) { > - continue; > - } > - > - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, fc->log, 0, > - "http2 push header: \"%V: %V\"", > - &ph[i].name, &(*h)->value); > - > - pos = ngx_cpymem(pos, binary[i].data, binary[i].len); > - } > - > - frame = ngx_http_v2_create_push_frame(r, start, pos); > - if (frame == NULL) { > - return NGX_ERROR; > - } > - > - ngx_http_v2_queue_blocked_frame(h2c, frame); > - > - stream->queued++; > - > - stream = ngx_http_v2_push_stream(stream, path); > - > - if (stream) { > - stream->request->request_length = pos - start; > - return NGX_OK; > - } > - > - return NGX_ERROR; > -} > - > - > static ngx_http_v2_out_frame_t * > ngx_http_v2_create_headers_frame(ngx_http_request_t *r, u_char *pos, > u_char *end, ngx_uint_t fin) > @@ -1180,125 +735,6 @@ ngx_http_v2_create_headers_frame(ngx_htt > > > static ngx_http_v2_out_frame_t * > -ngx_http_v2_create_push_frame(ngx_http_request_t *r, u_char *pos, u_char *end) > -{ > - u_char type, flags; > - size_t rest, frame_size, len; > - ngx_buf_t *b; > - ngx_chain_t *cl, **ll; > - ngx_http_v2_stream_t *stream; > - ngx_http_v2_out_frame_t *frame; > - ngx_http_v2_connection_t *h2c; > - > - stream = r->stream; > - h2c = stream->connection; > - rest = NGX_HTTP_V2_STREAM_ID_SIZE + (end - pos); > - > - frame = ngx_palloc(r->pool, sizeof(ngx_http_v2_out_frame_t)); > - if (frame == NULL) { > - return NULL; > - } > - > - frame->handler = ngx_http_v2_push_frame_handler; > - frame->stream = stream; > - frame->length = rest; > - frame->blocked = 1; > - frame->fin = 0; > - > - ll = &frame->first; > - > - type = NGX_HTTP_V2_PUSH_PROMISE_FRAME; > - flags = NGX_HTTP_V2_NO_FLAG; > - frame_size = h2c->frame_size; > - > - for ( ;; ) { > - if (rest <= frame_size) { > - frame_size = rest; > - flags |= NGX_HTTP_V2_END_HEADERS_FLAG; > - } > - > - b = ngx_create_temp_buf(r->pool, > - NGX_HTTP_V2_FRAME_HEADER_SIZE > - + ((type == NGX_HTTP_V2_PUSH_PROMISE_FRAME) > - ? NGX_HTTP_V2_STREAM_ID_SIZE : 0)); > - if (b == NULL) { > - return NULL; > - } > - > - b->last = ngx_http_v2_write_len_and_type(b->last, frame_size, type); > - *b->last++ = flags; > - b->last = ngx_http_v2_write_sid(b->last, stream->node->id); > - > - b->tag = (ngx_buf_tag_t) &ngx_http_v2_module; > - > - if (type == NGX_HTTP_V2_PUSH_PROMISE_FRAME) { > - h2c->last_push += 2; > - > - b->last = ngx_http_v2_write_sid(b->last, h2c->last_push); > - len = frame_size - NGX_HTTP_V2_STREAM_ID_SIZE; > - > - } else { > - len = frame_size; > - } > - > - cl = ngx_alloc_chain_link(r->pool); > - if (cl == NULL) { > - return NULL; > - } > - > - cl->buf = b; > - > - *ll = cl; > - ll = &cl->next; > - > - b = ngx_calloc_buf(r->pool); > - if (b == NULL) { > - return NULL; > - } > - > - b->pos = pos; > - > - pos += len; > - > - b->last = pos; > - b->start = b->pos; > - b->end = b->last; > - b->temporary = 1; > - > - cl = ngx_alloc_chain_link(r->pool); > - if (cl == NULL) { > - return NULL; > - } > - > - cl->buf = b; > - > - *ll = cl; > - ll = &cl->next; > - > - rest -= frame_size; > - > - if (rest) { > - frame->length += NGX_HTTP_V2_FRAME_HEADER_SIZE; > - > - type = NGX_HTTP_V2_CONTINUATION_FRAME; > - continue; > - } > - > - cl->next = NULL; > - frame->last = cl; > - > - ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, > - "http2:%ui create PUSH_PROMISE frame %p: " > - "sid:%ui len:%uz", > - stream->node->id, frame, h2c->last_push, > - frame->length); > - > - return frame; > - } > -} > - > - > -static ngx_http_v2_out_frame_t * > ngx_http_v2_create_trailers_frame(ngx_http_request_t *r) > { > u_char *pos, *start, *tmp; > @@ -1902,62 +1338,6 @@ ngx_http_v2_headers_frame_handler(ngx_ht > > > static ngx_int_t > -ngx_http_v2_push_frame_handler(ngx_http_v2_connection_t *h2c, > - ngx_http_v2_out_frame_t *frame) > -{ > - ngx_chain_t *cl, *ln; > - ngx_http_v2_stream_t *stream; > - > - stream = frame->stream; > - cl = frame->first; > - > - for ( ;; ) { > - if (cl->buf->pos != cl->buf->last) { > - frame->first = cl; > - > - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, > - "http2:%ui PUSH_PROMISE frame %p was sent partially", > - stream->node->id, frame); > - > - return NGX_AGAIN; > - } > - > - ln = cl->next; > - > - if (cl->buf->tag == (ngx_buf_tag_t) &ngx_http_v2_module) { > - cl->next = stream->free_frame_headers; > - stream->free_frame_headers = cl; > - > - } else { > - cl->next = stream->free_bufs; > - stream->free_bufs = cl; > - } > - > - if (cl == frame->last) { > - break; > - } > - > - cl = ln; > - } > - > - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, > - "http2:%ui PUSH_PROMISE frame %p was sent", > - stream->node->id, frame); > - > - stream->request->header_size += NGX_HTTP_V2_FRAME_HEADER_SIZE > - + frame->length; > - > - h2c->payload_bytes += frame->length; > - > - ngx_http_v2_handle_frame(stream, frame); > - > - ngx_http_v2_handle_stream(h2c, stream); > - > - return NGX_OK; > -} > - > - > -static ngx_int_t > ngx_http_v2_data_frame_handler(ngx_http_v2_connection_t *h2c, > ngx_http_v2_out_frame_t *frame) > { > diff --git a/src/http/v2/ngx_http_v2_module.c b/src/http/v2/ngx_http_v2_module.c > --- a/src/http/v2/ngx_http_v2_module.c > +++ b/src/http/v2/ngx_http_v2_module.c > @@ -27,8 +27,6 @@ static void *ngx_http_v2_create_loc_conf > static char *ngx_http_v2_merge_loc_conf(ngx_conf_t *cf, void *parent, > void *child); > > -static char *ngx_http_v2_push(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); > - > static char *ngx_http_v2_recv_buffer_size(ngx_conf_t *cf, void *post, > void *data); > static char *ngx_http_v2_pool_size(ngx_conf_t *cf, void *post, void *data); > @@ -105,9 +103,9 @@ static ngx_command_t ngx_http_v2_comman > > { ngx_string("http2_max_concurrent_pushes"), > NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, > - ngx_conf_set_num_slot, > - NGX_HTTP_SRV_CONF_OFFSET, > - offsetof(ngx_http_v2_srv_conf_t, concurrent_pushes), > + ngx_http_v2_obsolete, > + 0, > + 0, > NULL }, > > { ngx_string("http2_max_requests"), > @@ -168,15 +166,15 @@ static ngx_command_t ngx_http_v2_comman > > { ngx_string("http2_push_preload"), > NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, > - ngx_conf_set_flag_slot, > - NGX_HTTP_LOC_CONF_OFFSET, > - offsetof(ngx_http_v2_loc_conf_t, push_preload), > + ngx_http_v2_obsolete, > + 0, > + 0, > NULL }, > > { ngx_string("http2_push"), > NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, > - ngx_http_v2_push, > - NGX_HTTP_LOC_CONF_OFFSET, > + ngx_http_v2_obsolete, > + 0, > 0, > NULL }, > > @@ -326,7 +324,6 @@ ngx_http_v2_create_srv_conf(ngx_conf_t * > h2scf->pool_size = NGX_CONF_UNSET_SIZE; > > h2scf->concurrent_streams = NGX_CONF_UNSET_UINT; > - h2scf->concurrent_pushes = NGX_CONF_UNSET_UINT; > > h2scf->preread_size = NGX_CONF_UNSET_SIZE; > > @@ -348,8 +345,6 @@ ngx_http_v2_merge_srv_conf(ngx_conf_t *c > > ngx_conf_merge_uint_value(conf->concurrent_streams, > prev->concurrent_streams, 128); > - ngx_conf_merge_uint_value(conf->concurrent_pushes, > - prev->concurrent_pushes, 10); > > ngx_conf_merge_size_value(conf->preread_size, prev->preread_size, 65536); > > @@ -370,17 +365,8 @@ ngx_http_v2_create_loc_conf(ngx_conf_t * > return NULL; > } > > - /* > - * set by ngx_pcalloc(): > - * > - * h2lcf->pushes = NULL; > - */ > - > h2lcf->chunk_size = NGX_CONF_UNSET_SIZE; > > - h2lcf->push_preload = NGX_CONF_UNSET; > - h2lcf->push = NGX_CONF_UNSET; > - > return h2lcf; > } > > @@ -393,72 +379,6 @@ ngx_http_v2_merge_loc_conf(ngx_conf_t *c > > ngx_conf_merge_size_value(conf->chunk_size, prev->chunk_size, 8 * 1024); > > - ngx_conf_merge_value(conf->push, prev->push, 1); > - > - if (conf->push && conf->pushes == NULL) { > - conf->pushes = prev->pushes; > - } > - > - ngx_conf_merge_value(conf->push_preload, prev->push_preload, 0); > - > - return NGX_CONF_OK; > -} > - > - > -static char * > -ngx_http_v2_push(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) > -{ > - ngx_http_v2_loc_conf_t *h2lcf = conf; > - > - ngx_str_t *value; > - ngx_http_complex_value_t *cv; > - ngx_http_compile_complex_value_t ccv; > - > - value = cf->args->elts; > - > - if (ngx_strcmp(value[1].data, "off") == 0) { > - > - if (h2lcf->pushes) { > - return "\"off\" parameter cannot be used with URI"; > - } > - > - if (h2lcf->push == 0) { > - return "is duplicate"; > - } > - > - h2lcf->push = 0; > - return NGX_CONF_OK; > - } > - > - if (h2lcf->push == 0) { > - return "URI cannot be used with \"off\" parameter"; > - } > - > - h2lcf->push = 1; > - > - if (h2lcf->pushes == NULL) { > - h2lcf->pushes = ngx_array_create(cf->pool, 1, > - sizeof(ngx_http_complex_value_t)); > - if (h2lcf->pushes == NULL) { > - return NGX_CONF_ERROR; > - } > - } > - > - cv = ngx_array_push(h2lcf->pushes); > - if (cv == NULL) { > - return NGX_CONF_ERROR; > - } > - > - ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); > - > - ccv.cf = cf; > - ccv.value = &value[1]; > - ccv.complex_value = cv; > - > - if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { > - return NGX_CONF_ERROR; > - } > - > return NGX_CONF_OK; > } > > @@ -562,10 +482,17 @@ ngx_http_v2_obsolete(ngx_conf_t *cf, ngx > { > ngx_conf_deprecated_t *d = cmd->post; > > - ngx_conf_log_error(NGX_LOG_WARN, cf, 0, > - "the \"%s\" directive is obsolete, " > - "use the \"%s\" directive instead", > - d->old_name, d->new_name); > + if (d) { > + ngx_conf_log_error(NGX_LOG_WARN, cf, 0, > + "the \"%s\" directive is obsolete, " > + "use the \"%s\" directive instead", > + d->old_name, d->new_name); > + > + } else { > + ngx_conf_log_error(NGX_LOG_WARN, cf, 0, > + "the \"%V\" directive is obsolete, ignored", > + &cmd->name); > + } > > return NGX_CONF_OK; > } > diff --git a/src/http/v2/ngx_http_v2_module.h b/src/http/v2/ngx_http_v2_module.h > --- a/src/http/v2/ngx_http_v2_module.h > +++ b/src/http/v2/ngx_http_v2_module.h > @@ -22,11 +22,6 @@ typedef struct { > > typedef struct { > size_t chunk_size; > - > - ngx_flag_t push_preload; > - > - ngx_flag_t push; > - ngx_array_t *pushes; > } ngx_http_v2_loc_conf_t; > > Looks good. -- Maxim Dounin http://mdounin.ru/ From mdounin at mdounin.ru Wed Jun 7 17:23:50 2023 From: mdounin at mdounin.ru (Maxim Dounin) Date: Wed, 7 Jun 2023 20:23:50 +0300 Subject: [PATCH] SSL: removed the "ssl" directive In-Reply-To: References: <564c8f447ea4d76d8025.1685690902@arut-laptop> Message-ID: Hello! On Mon, Jun 05, 2023 at 07:06:26PM +0400, Sergey Kandaurov wrote: > > On 2 Jun 2023, at 11:28, Roman Arutyunyan wrote: > > > > # HG changeset patch > > # User Roman Arutyunyan > > # Date 1685447035 -14400 > > # Tue May 30 15:43:55 2023 +0400 > > # Node ID 564c8f447ea4d76d80251bbf07df412942a2261f > > # Parent b4a57278bf24dd28d39afea0eb09732c05bf1606 > > SSL: removed the "ssl" directive. > > > > It has been deprecated since 46c0c7ef4913 (1.15.0); > > s/;/./ > > The rest looks fine. I would recommend mentioning that it is deprecated in favor of the "ssl" parameter of the "listen" directive, which is available since nginx 0.7.14 (2224:109849282793). Otherwise looks good. -- Maxim Dounin http://mdounin.ru/ From xeioex at nginx.com Thu Jun 8 00:14:27 2023 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 08 Jun 2023 00:14:27 +0000 Subject: [njs] Modules: renaming ngx_js_conf_t to ngx_js_loc_conf_t. Message-ID: details: https://hg.nginx.org/njs/rev/2daeeea1a05a branches: changeset: 2151:2daeeea1a05a user: Dmitry Volyntsev date: Tue Jun 06 21:31:39 2023 -0700 description: Modules: renaming ngx_js_conf_t to ngx_js_loc_conf_t. diffstat: nginx/ngx_http_js_module.c | 8 ++++---- nginx/ngx_js.c | 39 ++++++++++++++++++++------------------- nginx/ngx_js.h | 28 ++++++++++++++-------------- nginx/ngx_stream_js_module.c | 8 ++++---- 4 files changed, 42 insertions(+), 41 deletions(-) diffs (276 lines): diff -r 92678163754a -r 2daeeea1a05a nginx/ngx_http_js_module.c --- a/nginx/ngx_http_js_module.c Mon Jun 05 18:21:07 2023 -0700 +++ b/nginx/ngx_http_js_module.c Tue Jun 06 21:31:39 2023 -0700 @@ -13,7 +13,7 @@ typedef struct { - NGX_JS_COMMON_CONF; + NGX_JS_COMMON_LOC_CONF; ngx_str_t content; ngx_str_t header_filter; @@ -254,7 +254,7 @@ static char *ngx_http_js_content(ngx_con static char *ngx_http_js_body_filter_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static ngx_int_t ngx_http_js_init_conf_vm(ngx_conf_t *cf, - ngx_js_conf_t *conf); + ngx_js_loc_conf_t *conf); static void *ngx_http_js_create_loc_conf(ngx_conf_t *cf); static char *ngx_http_js_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child); @@ -4104,7 +4104,7 @@ ngx_http_js_handle_event(ngx_http_reques static ngx_int_t -ngx_http_js_externals_init(ngx_conf_t *cf, ngx_js_conf_t *conf_in) +ngx_http_js_externals_init(ngx_conf_t *cf, ngx_js_loc_conf_t *conf_in) { ngx_http_js_loc_conf_t *conf = (ngx_http_js_loc_conf_t *) conf_in; @@ -4122,7 +4122,7 @@ ngx_http_js_externals_init(ngx_conf_t *c static ngx_int_t -ngx_http_js_init_conf_vm(ngx_conf_t *cf, ngx_js_conf_t *conf) +ngx_http_js_init_conf_vm(ngx_conf_t *cf, ngx_js_loc_conf_t *conf) { njs_vm_opt_t options; diff -r 92678163754a -r 2daeeea1a05a nginx/ngx_js.c --- a/nginx/ngx_js.c Mon Jun 05 18:21:07 2023 -0700 +++ b/nginx/ngx_js.c Tue Jun 06 21:31:39 2023 -0700 @@ -548,7 +548,7 @@ ngx_js_logger(njs_vm_t *vm, njs_external char * ngx_js_import(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { - ngx_js_conf_t *jscf = conf; + ngx_js_loc_conf_t *jscf = conf; u_char *p, *end, c; ngx_int_t from; @@ -654,7 +654,7 @@ ngx_js_import(ngx_conf_t *cf, ngx_comman char * ngx_js_preload_object(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { - ngx_js_conf_t *jscf = conf; + ngx_js_loc_conf_t *jscf = conf; u_char *p, *end, c; ngx_int_t from; @@ -758,7 +758,7 @@ ngx_js_preload_object(ngx_conf_t *cf, ng ngx_int_t -ngx_js_init_preload_vm(ngx_conf_t *cf, ngx_js_conf_t *conf) +ngx_js_init_preload_vm(ngx_conf_t *cf, ngx_js_loc_conf_t *conf) { u_char *p, *start; size_t size; @@ -854,9 +854,9 @@ error: ngx_int_t -ngx_js_merge_vm(ngx_conf_t *cf, ngx_js_conf_t *conf, - ngx_js_conf_t *prev, - ngx_int_t (*init_vm) (ngx_conf_t *cf, ngx_js_conf_t *conf)) +ngx_js_merge_vm(ngx_conf_t *cf, ngx_js_loc_conf_t *conf, + ngx_js_loc_conf_t *prev, + ngx_int_t (*init_vm) (ngx_conf_t *cf, ngx_js_loc_conf_t *conf)) { ngx_str_t *path, *s; ngx_uint_t i; @@ -864,7 +864,7 @@ ngx_js_merge_vm(ngx_conf_t *cf, ngx_js_c ngx_js_named_path_t *import, *pi, *pij, *preload; if (prev->imports != NGX_CONF_UNSET_PTR && prev->vm == NULL) { - if (init_vm(cf, (ngx_js_conf_t *) prev) != NGX_OK) { + if (init_vm(cf, (ngx_js_loc_conf_t *) prev) != NGX_OK) { return NGX_ERROR; } } @@ -999,14 +999,14 @@ ngx_js_merge_vm(ngx_conf_t *cf, ngx_js_c return NGX_OK; } - return init_vm(cf, (ngx_js_conf_t *) conf); + return init_vm(cf, (ngx_js_loc_conf_t *) conf); } ngx_int_t -ngx_js_init_conf_vm(ngx_conf_t *cf, ngx_js_conf_t *conf, +ngx_js_init_conf_vm(ngx_conf_t *cf, ngx_js_loc_conf_t *conf, njs_vm_opt_t *options, - ngx_int_t (*externals_init)(ngx_conf_t *cf, ngx_js_conf_t *conf)) + ngx_int_t (*externals_init)(ngx_conf_t *cf, ngx_js_loc_conf_t *conf)) { size_t size; u_char *start, *end, *p; @@ -1023,7 +1023,7 @@ ngx_js_init_conf_vm(ngx_conf_t *cf, ngx_ static const njs_str_t file_name_key = njs_str("fileName"); if (conf->preload_objects != NGX_CONF_UNSET_PTR) { - if (ngx_js_init_preload_vm(cf, (ngx_js_conf_t *)conf) != NGX_OK) { + if (ngx_js_init_preload_vm(cf, (ngx_js_loc_conf_t *)conf) != NGX_OK) { return NGX_ERROR; } } @@ -1171,7 +1171,7 @@ ngx_js_init_conf_vm(ngx_conf_t *cf, ngx_ static void ngx_js_cleanup_vm(void *data) { - ngx_js_conf_t *jscf = data; + ngx_js_loc_conf_t *jscf = data; njs_vm_destroy(jscf->vm); @@ -1181,10 +1181,10 @@ ngx_js_cleanup_vm(void *data) } -ngx_js_conf_t * +ngx_js_loc_conf_t * ngx_js_create_conf(ngx_conf_t *cf, size_t size) { - ngx_js_conf_t *conf; + ngx_js_loc_conf_t *conf; conf = ngx_pcalloc(cf->pool, size); if (conf == NULL) { @@ -1206,7 +1206,7 @@ ngx_js_create_conf(ngx_conf_t *cf, size_ #if defined(NGX_HTTP_SSL) || defined(NGX_STREAM_SSL) static char * -ngx_js_set_ssl(ngx_conf_t *cf, ngx_js_conf_t *conf) +ngx_js_set_ssl(ngx_conf_t *cf, ngx_js_loc_conf_t *conf) { ngx_ssl_t *ssl; ngx_pool_cleanup_t *cln; @@ -1251,17 +1251,18 @@ ngx_js_set_ssl(ngx_conf_t *cf, ngx_js_co char * ngx_js_merge_conf(ngx_conf_t *cf, void *parent, void *child, - ngx_int_t (*init_vm)(ngx_conf_t *cf, ngx_js_conf_t *conf)) + ngx_int_t (*init_vm)(ngx_conf_t *cf, ngx_js_loc_conf_t *conf)) { - ngx_js_conf_t *prev = parent; - ngx_js_conf_t *conf = child; + ngx_js_loc_conf_t *prev = parent; + ngx_js_loc_conf_t *conf = child; ngx_conf_merge_msec_value(conf->timeout, prev->timeout, 60000); ngx_conf_merge_size_value(conf->buffer_size, prev->buffer_size, 16384); ngx_conf_merge_size_value(conf->max_response_body_size, prev->max_response_body_size, 1048576); - if (ngx_js_merge_vm(cf, (ngx_js_conf_t *) conf, (ngx_js_conf_t *) prev, + if (ngx_js_merge_vm(cf, (ngx_js_loc_conf_t *) conf, + (ngx_js_loc_conf_t *) prev, init_vm) != NGX_OK) { diff -r 92678163754a -r 2daeeea1a05a nginx/ngx_js.h --- a/nginx/ngx_js.h Mon Jun 05 18:21:07 2023 -0700 +++ b/nginx/ngx_js.h Tue Jun 06 21:31:39 2023 -0700 @@ -50,7 +50,7 @@ typedef struct { } ngx_js_named_path_t; -#define _NGX_JS_COMMON_CONF \ +#define _NGX_JS_COMMON_LOC_CONF \ njs_vm_t *vm; \ ngx_array_t *imports; \ ngx_array_t *paths; \ @@ -64,8 +64,8 @@ typedef struct { #if defined(NGX_HTTP_SSL) || defined(NGX_STREAM_SSL) -#define NGX_JS_COMMON_CONF \ - _NGX_JS_COMMON_CONF; \ +#define NGX_JS_COMMON_LOC_CONF \ + _NGX_JS_COMMON_LOC_CONF; \ \ ngx_ssl_t *ssl; \ ngx_str_t ssl_ciphers; \ @@ -75,13 +75,13 @@ typedef struct { ngx_str_t ssl_trusted_certificate #else -#define NGX_JS_COMMON_CONF _NGX_JS_COMMON_CONF +#define NGX_JS_COMMON_LOC_CONF _NGX_JS_COMMON_LOC_CONF #endif typedef struct { - NGX_JS_COMMON_CONF; -} ngx_js_conf_t; + NGX_JS_COMMON_LOC_CONF; +} ngx_js_loc_conf_t; #define ngx_external_connection(vm, e) \ @@ -124,16 +124,16 @@ void ngx_js_logger(njs_vm_t *vm, njs_ext njs_log_level_t level, const u_char *start, size_t length); char * ngx_js_import(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); char * ngx_js_preload_object(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); -ngx_int_t ngx_js_init_preload_vm(ngx_conf_t *cf, ngx_js_conf_t *conf); -ngx_int_t ngx_js_merge_vm(ngx_conf_t *cf, ngx_js_conf_t *conf, - ngx_js_conf_t *prev, - ngx_int_t (*init_vm)(ngx_conf_t *cf, ngx_js_conf_t *conf)); -ngx_int_t ngx_js_init_conf_vm(ngx_conf_t *cf, ngx_js_conf_t *conf, +ngx_int_t ngx_js_init_preload_vm(ngx_conf_t *cf, ngx_js_loc_conf_t *conf); +ngx_int_t ngx_js_merge_vm(ngx_conf_t *cf, ngx_js_loc_conf_t *conf, + ngx_js_loc_conf_t *prev, + ngx_int_t (*init_vm)(ngx_conf_t *cf, ngx_js_loc_conf_t *conf)); +ngx_int_t ngx_js_init_conf_vm(ngx_conf_t *cf, ngx_js_loc_conf_t *conf, njs_vm_opt_t *options, - ngx_int_t (*externals_init)(ngx_conf_t *cf, ngx_js_conf_t *conf)); -ngx_js_conf_t *ngx_js_create_conf(ngx_conf_t *cf, size_t size); + ngx_int_t (*externals_init)(ngx_conf_t *cf, ngx_js_loc_conf_t *conf)); +ngx_js_loc_conf_t *ngx_js_create_conf(ngx_conf_t *cf, size_t size); char * ngx_js_merge_conf(ngx_conf_t *cf, void *parent, void *child, - ngx_int_t (*init_vm)(ngx_conf_t *cf, ngx_js_conf_t *conf)); + ngx_int_t (*init_vm)(ngx_conf_t *cf, ngx_js_loc_conf_t *conf)); njs_int_t ngx_js_ext_string(njs_vm_t *vm, njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, njs_value_t *retval); diff -r 92678163754a -r 2daeeea1a05a nginx/ngx_stream_js_module.c --- a/nginx/ngx_stream_js_module.c Mon Jun 05 18:21:07 2023 -0700 +++ b/nginx/ngx_stream_js_module.c Tue Jun 06 21:31:39 2023 -0700 @@ -13,7 +13,7 @@ typedef struct { - NGX_JS_COMMON_CONF; + NGX_JS_COMMON_LOC_CONF; ngx_str_t access; ngx_str_t preread; @@ -119,7 +119,7 @@ static char *ngx_stream_js_set(ngx_conf_ static char *ngx_stream_js_var(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static ngx_int_t ngx_stream_js_init_conf_vm(ngx_conf_t *cf, - ngx_js_conf_t *conf); + ngx_js_loc_conf_t *conf); static void *ngx_stream_js_create_srv_conf(ngx_conf_t *cf); static char *ngx_stream_js_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child); @@ -1670,7 +1670,7 @@ ngx_stream_js_handle_event(ngx_stream_se static ngx_int_t -ngx_stream_js_externals_init(ngx_conf_t *cf, ngx_js_conf_t *conf_in) +ngx_stream_js_externals_init(ngx_conf_t *cf, ngx_js_loc_conf_t *conf_in) { ngx_stream_js_srv_conf_t *conf = (ngx_stream_js_srv_conf_t *) conf_in; @@ -1697,7 +1697,7 @@ ngx_stream_js_externals_init(ngx_conf_t static ngx_int_t -ngx_stream_js_init_conf_vm(ngx_conf_t *cf, ngx_js_conf_t *conf) +ngx_stream_js_init_conf_vm(ngx_conf_t *cf, ngx_js_loc_conf_t *conf) { njs_vm_opt_t options; From xeioex at nginx.com Thu Jun 8 00:14:28 2023 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 08 Jun 2023 00:14:28 +0000 Subject: [njs] Types: removed descryption for methods removed in 4df790f42ce7. Message-ID: details: https://hg.nginx.org/njs/rev/fa51408510ad branches: changeset: 2152:fa51408510ad user: Dmitry Volyntsev date: Tue Jun 06 21:33:46 2023 -0700 description: Types: removed descryption for methods removed in 4df790f42ce7. Since the disctinction between byte strings and ordinary strings is eliminated the NjsByteString type is also removed. diffstat: test/ts/test.ts | 28 +- ts/ngx_core.d.ts | 50 ++-- ts/ngx_http_js_module.d.ts | 452 ++++++++++++++++++++-------------------- ts/ngx_stream_js_module.d.ts | 134 +++++----- ts/njs_core.d.ts | 85 +------ ts/njs_modules/fs.d.ts | 6 +- ts/njs_modules/querystring.d.ts | 18 +- ts/njs_modules/xml.d.ts | 2 +- ts/njs_shell.d.ts | 4 +- 9 files changed, 355 insertions(+), 424 deletions(-) diffs (truncated from 1299 to 1000 lines): diff -r 2daeeea1a05a -r fa51408510ad test/ts/test.ts --- a/test/ts/test.ts Tue Jun 06 21:31:39 2023 -0700 +++ b/test/ts/test.ts Tue Jun 06 21:33:46 2023 -0700 @@ -5,20 +5,9 @@ import xml from 'xml'; import zlib from 'zlib'; async function http_module(r: NginxHTTPRequest) { - var bs: NjsByteString; var s: string; var vod: void; - // builtin string vs NjsByteString - - s = 'ordinary string'; - bs = String.bytesFrom('000000', 'hex'); - var bs2: NjsByteString | null = s.toBytes(); - bs = s.toUTF8(); - bs.fromBytes(undefined, undefined); - - s = bs + ''; - // r.uri if (r.uri == '/') { @@ -26,14 +15,13 @@ async function http_module(r: NginxHTTPR // r.args - bs = r.args.x; - bs = r.args[1]; - var s2: string | null = r.args.x.fromUTF8(); + s = r.args.x; + s = r.args[1]; s = r.args.x + ''; // r.headersIn - r.headersIn['Accept']?.fromBytes() == 'dddd'; + r.headersIn['Accept'] == 'dddd'; // r.headersOut @@ -50,7 +38,7 @@ async function http_module(r: NginxHTTPR // r.log - r.log(bs); + r.log(s); r.log(Buffer.from("abc")); r.log(r.headersOut['Connection'] ?? ''); @@ -155,7 +143,7 @@ async function fs_module() { await fs.promises.rmdir('d/e/f', {recursive: false}); } -function qs_module(str: NjsByteString) { +function qs_module(str: string) { var o; var s:string; @@ -163,7 +151,7 @@ function qs_module(str: NjsByteString) { s = qs.stringify(o); } -function xml_module(str: NjsByteString) { +function xml_module(str: string) { let doc; let node; let children, selectedChildren; @@ -195,7 +183,7 @@ function xml_module(str: NjsByteString) node.$tags = [node, node]; } -function zlib_module(str: NjsByteString) { +function zlib_module(str: string) { zlib.deflateRawSync(str, {level: zlib.constants.Z_BEST_COMPRESSION, memLevel: 9}); zlib.deflateSync(str, {strategy: zlib.constants.Z_RLE}); @@ -203,7 +191,7 @@ function zlib_module(str: NjsByteString) zlib.inflateSync(str, {chunkSize: 2048}); } -function crypto_module(str: NjsByteString) { +function crypto_module(str: string) { var h; var b:Buffer; var s:string; diff -r 2daeeea1a05a -r fa51408510ad ts/ngx_core.d.ts --- a/ts/ngx_core.d.ts Tue Jun 06 21:31:39 2023 -0700 +++ b/ts/ngx_core.d.ts Tue Jun 06 21:33:46 2023 -0700 @@ -1,4 +1,4 @@ -type NgxHeaders = Headers | Object | [NjsFixedSizeArray<2, NjsStringLike>]; +type NgxHeaders = Headers | Object | [NjsFixedSizeArray<2, string>]; declare class Headers { /** @@ -8,7 +8,7 @@ declare class Headers { * @param value A value of the header. * @since 0.7.10 */ - append(name:NjsStringLike, value: NjsStringLike): void; + append(name:string, value: string): void; /** * Headers constructors. * @@ -16,38 +16,38 @@ declare class Headers { * @returns returns Headers object. * @since 0.7.10 */ - constructor(init?: Object | [NjsFixedSizeArray<2, NjsStringLike>]); + constructor(init?: Object | [NjsFixedSizeArray<2, string>]); /** * Deletes a header from the Headers object. * @param name A name of the header to be deleted. * @since 0.7.10 */ - delete(name:NjsStringLike): void; + delete(name:string): void; /** * Returns a string containing the values of all headers * with the specified name separated by a comma and a space. * @param name A name of the header. */ - get(name:NjsStringLike): NjsByteString; + get(name:string): string; /** * Returns an array containing the values of all headers * with the specified name. * @param name A name of the header. */ - getAll(name:NjsStringLike): Array; + getAll(name:string): Array; /** * Executes a provided function once for each key/value * pair in the Headers object. * @param fn the function to be envoked. * @since 0.7.10 */ - forEach(fn:(name: NjsStringLike, value: NjsStringLike) => void): void; + forEach(fn:(name: string, value: string) => void): void; /** * Returns a boolean value indicating whether a header with * the specified name exists. * @param name A name of the header. */ - has(name:NjsStringLike): boolean; + has(name:string): boolean; /** * Sets a new value for an existing header inside the Headers object, * or adds the header if it does not already exist. @@ -55,14 +55,14 @@ declare class Headers { * @param value A value of the header. * @since 0.7.10 */ - set(name:NjsStringLike, value: NjsStringLike): void; + set(name:string, value: string): void; } interface NgxRequestOptions { /** * Request body, by default is empty. */ - body?: NjsStringLike; + body?: string; /** * Cache mode, by default is "default". */ @@ -78,7 +78,7 @@ interface NgxRequestOptions { /** * Request method, by default the GET method is used. */ - method?: NjsStringLike; + method?: string; /** * Mode, by default is "no-cors". */ @@ -97,7 +97,7 @@ declare class Request { /** * Cache mode. */ - readonly cache: NjsByteString; + readonly cache: string; /** * Request constructors. * @@ -105,11 +105,11 @@ declare class Request { * @returns returns Request object. * @since 0.7.10 */ - constructor(input: NjsStringLike | Request, options?: NgxRequestOptions); + constructor(input: string | Request, options?: NgxRequestOptions); /** * Credentials. */ - readonly credentials: NjsByteString; + readonly credentials: string; /** * Returns a Promise that resolves with an result of applying of * JSON.parse() to a body. @@ -122,15 +122,15 @@ declare class Request { /** * Request mode. */ - readonly mode: NjsByteString; + readonly mode: string; /** * Returns a Promise that resolves with an body as String. */ - text(): Promise; + text(): Promise; /** * Request url. */ - readonly url: NjsByteString; + readonly url: string; } interface NgxResponseOptions { @@ -145,7 +145,7 @@ interface NgxResponseOptions { /** * Response status test, '' by default. */ - statusText?: NjsStringLike; + statusText?: string; } declare class Response { @@ -165,7 +165,7 @@ declare class Response { * @returns returns Response object. * @since 0.7.10 */ - constructor(body?: NjsStringLike, options?: NgxResponseOptions); + constructor(body?: string, options?: NgxResponseOptions); /** * Takes a Response stream and reads it to completion. * Returns a Promise that resolves with the result of @@ -193,27 +193,27 @@ declare class Response { /** * The status message corresponding to the status code. */ - readonly statusText: NjsByteString; + readonly statusText: string; /** * Takes a Response stream and reads it to completion. * Returns a Promise that resolves with a string. */ - text(): Promise; + text(): Promise; /** * The type of the response. */ - readonly type: NjsByteString; + readonly type: string; /** * Response url. */ - readonly url: NjsByteString; + readonly url: string; } interface NgxFetchOptions { /** * Request body, by default is empty. */ - body?: NjsStringLike, + body?: string, /** * The buffer size for reading the response, by default is 16384 (4096 before 0.7.4). * Nginx specific. @@ -233,7 +233,7 @@ interface NgxFetchOptions { /** * Request method, by default the GET method is used. */ - method?: NjsStringLike; + method?: string; /** * Enables or disables verification of the HTTPS server certificate, * by default is true. diff -r 2daeeea1a05a -r fa51408510ad ts/ngx_http_js_module.d.ts --- a/ts/ngx_http_js_module.d.ts Tue Jun 06 21:31:39 2023 -0700 +++ b/ts/ngx_http_js_module.d.ts Tue Jun 06 21:33:46 2023 -0700 @@ -2,235 +2,235 @@ /// interface NginxHTTPArgs { - readonly [prop: string]: NjsByteString; + readonly [prop: string]: string; } interface NginxHeadersIn { // common request headers - readonly 'Accept'?: NjsByteString; - readonly 'Accept-Charset'?: NjsByteString; - readonly 'Accept-Encoding'?: NjsByteString; - readonly 'Accept-Language'?: NjsByteString; - readonly 'Authorization'?: NjsByteString; - readonly 'Cache-Control'?: NjsByteString; - readonly 'Connection'?: NjsByteString; - readonly 'Content-Length'?: NjsByteString; - readonly 'Content-Type'?: NjsByteString; - readonly 'Cookie'?: NjsByteString; - readonly 'Date'?: NjsByteString; - readonly 'Expect'?: NjsByteString; - readonly 'Forwarded'?: NjsByteString; - readonly 'From'?: NjsByteString; - readonly 'Host'?: NjsByteString; - readonly 'If-Match'?: NjsByteString; - readonly 'If-Modified-Since'?: NjsByteString; - readonly 'If-None-Match'?: NjsByteString; - readonly 'If-Range'?: NjsByteString; - readonly 'If-Unmodified-Since'?: NjsByteString; - readonly 'Max-Forwards'?: NjsByteString; - readonly 'Origin'?: NjsByteString; - readonly 'Pragma'?: NjsByteString; - readonly 'Proxy-Authorization'?: NjsByteString; - readonly 'Range'?: NjsByteString; - readonly 'Referer'?: NjsByteString; - readonly 'TE'?: NjsByteString; - readonly 'User-Agent'?: NjsByteString; - readonly 'Upgrade'?: NjsByteString; - readonly 'Via'?: NjsByteString; - readonly 'Warning'?: NjsByteString; - readonly 'X-Forwarded-For'?: NjsByteString; + readonly 'Accept'?: string; + readonly 'Accept-Charset'?: string; + readonly 'Accept-Encoding'?: string; + readonly 'Accept-Language'?: string; + readonly 'Authorization'?: string; + readonly 'Cache-Control'?: string; + readonly 'Connection'?: string; + readonly 'Content-Length'?: string; + readonly 'Content-Type'?: string; + readonly 'Cookie'?: string; + readonly 'Date'?: string; + readonly 'Expect'?: string; + readonly 'Forwarded'?: string; + readonly 'From'?: string; + readonly 'Host'?: string; + readonly 'If-Match'?: string; + readonly 'If-Modified-Since'?: string; + readonly 'If-None-Match'?: string; + readonly 'If-Range'?: string; + readonly 'If-Unmodified-Since'?: string; + readonly 'Max-Forwards'?: string; + readonly 'Origin'?: string; + readonly 'Pragma'?: string; + readonly 'Proxy-Authorization'?: string; + readonly 'Range'?: string; + readonly 'Referer'?: string; + readonly 'TE'?: string; + readonly 'User-Agent'?: string; + readonly 'Upgrade'?: string; + readonly 'Via'?: string; + readonly 'Warning'?: string; + readonly 'X-Forwarded-For'?: string; - readonly [prop: string]: NjsByteString | undefined; + readonly [prop: string]: string | undefined; } interface NginxHeadersOut { // common response headers - 'Age'?: NjsStringLike; - 'Allow'?: NjsStringLike; - 'Alt-Svc'?: NjsStringLike; - 'Cache-Control'?: NjsStringLike; - 'Connection'?: NjsStringLike; - 'Content-Disposition'?: NjsStringLike; - 'Content-Encoding'?: NjsStringLike; - 'Content-Language'?: NjsStringLike; - 'Content-Length'?: NjsStringLike; - 'Content-Location'?: NjsStringLike; - 'Content-Range'?: NjsStringLike; - 'Content-Type'?: NjsStringLike; - 'Date'?: NjsStringLike; - 'ETag'?: NjsStringLike; - 'Expires'?: NjsStringLike; - 'Last-Modified'?: NjsStringLike; - 'Link'?: NjsStringLike; - 'Location'?: NjsStringLike; - 'Pragma'?: NjsStringLike; - 'Proxy-Authenticate'?: NjsStringLike; - 'Retry-After'?: NjsStringLike; - 'Server'?: NjsStringLike; - 'Trailer'?: NjsStringLike; - 'Transfer-Encoding'?: NjsStringLike; - 'Upgrade'?: NjsStringLike; - 'Vary'?: NjsStringLike; - 'Via'?: NjsStringLike; - 'Warning'?: NjsStringLike; - 'WWW-Authenticate'?: NjsStringLike; + 'Age'?: string; + 'Allow'?: string; + 'Alt-Svc'?: string; + 'Cache-Control'?: string; + 'Connection'?: string; + 'Content-Disposition'?: string; + 'Content-Encoding'?: string; + 'Content-Language'?: string; + 'Content-Length'?: string; + 'Content-Location'?: string; + 'Content-Range'?: string; + 'Content-Type'?: string; + 'Date'?: string; + 'ETag'?: string; + 'Expires'?: string; + 'Last-Modified'?: string; + 'Link'?: string; + 'Location'?: string; + 'Pragma'?: string; + 'Proxy-Authenticate'?: string; + 'Retry-After'?: string; + 'Server'?: string; + 'Trailer'?: string; + 'Transfer-Encoding'?: string; + 'Upgrade'?: string; + 'Vary'?: string; + 'Via'?: string; + 'Warning'?: string; + 'WWW-Authenticate'?: string; - 'Set-Cookie'?: NjsStringLike[]; + 'Set-Cookie'?: string[]; - [prop: string]: NjsStringLike | NjsStringLike[] | undefined; + [prop: string]: string | string[] | undefined; } interface NginxVariables { - readonly 'ancient_browser'?: NjsByteString; - readonly 'arg_'?: NjsByteString; - readonly 'args'?: NjsByteString; - readonly 'binary_remote_addr'?: NjsByteString; - readonly 'body_bytes_sent'?: NjsByteString; - readonly 'bytes_received'?: NjsByteString; - readonly 'bytes_sent'?: NjsByteString; - readonly 'connection'?: NjsByteString; - readonly 'connection_requests'?: NjsByteString; - readonly 'connections_active'?: NjsByteString; - readonly 'connections_reading'?: NjsByteString; - readonly 'connections_waiting'?: NjsByteString; - readonly 'connections_writing'?: NjsByteString; - readonly 'content_length'?: NjsByteString; - readonly 'content_type'?: NjsByteString; - readonly 'cookie_'?: NjsByteString; - readonly 'date_gmt'?: NjsByteString; - readonly 'date_local'?: NjsByteString; - readonly 'document_root'?: NjsByteString; - readonly 'document_uri'?: NjsByteString; - readonly 'fastcgi_path_info'?: NjsByteString; - readonly 'fastcgi_script_name'?: NjsByteString; - readonly 'geoip_area_code'?: NjsByteString; - readonly 'geoip_city'?: NjsByteString; - readonly 'geoip_city_continent_code'?: NjsByteString; - readonly 'geoip_city_country_code'?: NjsByteString; - readonly 'geoip_city_country_code3'?: NjsByteString; - readonly 'geoip_city_country_name'?: NjsByteString; - readonly 'geoip_country_code'?: NjsByteString; - readonly 'geoip_country_code3'?: NjsByteString; - readonly 'geoip_country_name'?: NjsByteString; - readonly 'geoip_dma_code'?: NjsByteString; - readonly 'geoip_latitude'?: NjsByteString; - readonly 'geoip_longitude'?: NjsByteString; - readonly 'geoip_org'?: NjsByteString; - readonly 'geoip_postal_code'?: NjsByteString; - readonly 'geoip_region'?: NjsByteString; - readonly 'geoip_region_name'?: NjsByteString; - readonly 'gzip_ratio'?: NjsByteString; - readonly 'host'?: NjsByteString; - readonly 'hostname'?: NjsByteString; - readonly 'http2'?: NjsByteString; - readonly 'http_'?: NjsByteString; - readonly 'https'?: NjsByteString; - readonly 'invalid_referer'?: NjsByteString; - readonly 'is_args'?: NjsByteString; - readonly 'jwt_claim_'?: NjsByteString; - readonly 'jwt_header_'?: NjsByteString; - readonly 'limit_conn_status'?: NjsByteString; - readonly 'limit_rate'?: NjsByteString; - readonly 'limit_req_status'?: NjsByteString; - readonly 'memcached_key'?: NjsByteString; - readonly 'modern_browser'?: NjsByteString; - readonly 'msec'?: NjsByteString; - readonly 'msie'?: NjsByteString; - readonly 'nginx_version'?: NjsByteString; - readonly 'pid'?: NjsByteString; - readonly 'pipe'?: NjsByteString; - readonly 'protocol'?: NjsByteString; - readonly 'proxy_add_x_forwarded_for'?: NjsByteString; - readonly 'proxy_host'?: NjsByteString; - readonly 'proxy_port'?: NjsByteString; - readonly 'proxy_protocol_addr'?: NjsByteString; - readonly 'proxy_protocol_port'?: NjsByteString; - readonly 'proxy_protocol_server_addr'?: NjsByteString; - readonly 'proxy_protocol_server_port'?: NjsByteString; - readonly 'query_string'?: NjsByteString; - readonly 'realip_remote_addr'?: NjsByteString; - readonly 'realip_remote_port'?: NjsByteString; - readonly 'realpath_root'?: NjsByteString; - readonly 'remote_addr'?: NjsByteString; - readonly 'remote_port'?: NjsByteString; - readonly 'remote_user'?: NjsByteString; - readonly 'request'?: NjsByteString; - readonly 'request_body'?: NjsByteString; - readonly 'request_body_file'?: NjsByteString; - readonly 'request_completion'?: NjsByteString; - readonly 'request_filename'?: NjsByteString; - readonly 'request_id'?: NjsByteString; - readonly 'request_length'?: NjsByteString; - readonly 'request_method'?: NjsByteString; - readonly 'request_time'?: NjsByteString; - readonly 'request_uri'?: NjsByteString; - readonly 'scheme'?: NjsByteString; - readonly 'secure_link'?: NjsByteString; - readonly 'secure_link_expires'?: NjsByteString; - readonly 'sent_http_'?: NjsByteString; - readonly 'sent_trailer_'?: NjsByteString; - readonly 'server_addr'?: NjsByteString; - readonly 'server_name'?: NjsByteString; - readonly 'server_port'?: NjsByteString; - readonly 'server_protocol'?: NjsByteString; - readonly 'session_log_binary_id'?: NjsByteString; - readonly 'session_log_id'?: NjsByteString; - readonly 'session_time'?: NjsByteString; - readonly 'slice_range'?: NjsByteString; - readonly 'spdy'?: NjsByteString; - readonly 'spdy_request_priority'?: NjsByteString; - readonly 'ssl_cipher'?: NjsByteString; - readonly 'ssl_ciphers'?: NjsByteString; - readonly 'ssl_client_cert'?: NjsByteString; - readonly 'ssl_client_escaped_cert'?: NjsByteString; - readonly 'ssl_client_fingerprint'?: NjsByteString; - readonly 'ssl_client_i_dn'?: NjsByteString; - readonly 'ssl_client_i_dn_legacy'?: NjsByteString; - readonly 'ssl_client_raw_cert'?: NjsByteString; - readonly 'ssl_client_s_dn'?: NjsByteString; - readonly 'ssl_client_s_dn_legacy'?: NjsByteString; - readonly 'ssl_client_serial'?: NjsByteString; - readonly 'ssl_client_v_end'?: NjsByteString; - readonly 'ssl_client_v_remain'?: NjsByteString; - readonly 'ssl_client_v_start'?: NjsByteString; - readonly 'ssl_client_verify'?: NjsByteString; - readonly 'ssl_curves'?: NjsByteString; - readonly 'ssl_early_data'?: NjsByteString; - readonly 'ssl_preread_alpn_protocols'?: NjsByteString; - readonly 'ssl_preread_protocol'?: NjsByteString; - readonly 'ssl_preread_server_name'?: NjsByteString; - readonly 'ssl_protocol'?: NjsByteString; - readonly 'ssl_server_name'?: NjsByteString; - readonly 'ssl_session_id'?: NjsByteString; - readonly 'ssl_session_reused'?: NjsByteString; - readonly 'status'?: NjsByteString; - readonly 'tcpinfo_rtt'?: NjsByteString; - readonly 'tcpinfo_rttvar'?: NjsByteString; - readonly 'tcpinfo_snd_cwnd'?: NjsByteString; - readonly 'tcpinfo_rcv_space'?: NjsByteString; - readonly 'time_iso8601'?: NjsByteString; - readonly 'time_local'?: NjsByteString; - readonly 'uid_got'?: NjsByteString; - readonly 'uid_reset'?: NjsByteString; - readonly 'uid_set'?: NjsByteString; - readonly 'upstream_addr'?: NjsByteString; - readonly 'upstream_bytes_received'?: NjsByteString; - readonly 'upstream_bytes_sent'?: NjsByteString; - readonly 'upstream_cache_status'?: NjsByteString; - readonly 'upstream_connect_time'?: NjsByteString; - readonly 'upstream_cookie_'?: NjsByteString; - readonly 'upstream_first_byte_time'?: NjsByteString; - readonly 'upstream_header_time'?: NjsByteString; - readonly 'upstream_http_'?: NjsByteString; - readonly 'upstream_queue_time'?: NjsByteString; - readonly 'upstream_response_length'?: NjsByteString; - readonly 'upstream_response_time'?: NjsByteString; - readonly 'upstream_session_time'?: NjsByteString; - readonly 'upstream_status'?: NjsByteString; - readonly 'upstream_trailer_'?: NjsByteString; - readonly 'uri'?: NjsByteString; + readonly 'ancient_browser'?: string; + readonly 'arg_'?: string; + readonly 'args'?: string; + readonly 'binary_remote_addr'?: string; + readonly 'body_bytes_sent'?: string; + readonly 'bytes_received'?: string; + readonly 'bytes_sent'?: string; + readonly 'connection'?: string; + readonly 'connection_requests'?: string; + readonly 'connections_active'?: string; + readonly 'connections_reading'?: string; + readonly 'connections_waiting'?: string; + readonly 'connections_writing'?: string; + readonly 'content_length'?: string; + readonly 'content_type'?: string; + readonly 'cookie_'?: string; + readonly 'date_gmt'?: string; + readonly 'date_local'?: string; + readonly 'document_root'?: string; + readonly 'document_uri'?: string; + readonly 'fastcgi_path_info'?: string; + readonly 'fastcgi_script_name'?: string; + readonly 'geoip_area_code'?: string; + readonly 'geoip_city'?: string; + readonly 'geoip_city_continent_code'?: string; + readonly 'geoip_city_country_code'?: string; + readonly 'geoip_city_country_code3'?: string; + readonly 'geoip_city_country_name'?: string; + readonly 'geoip_country_code'?: string; + readonly 'geoip_country_code3'?: string; + readonly 'geoip_country_name'?: string; + readonly 'geoip_dma_code'?: string; + readonly 'geoip_latitude'?: string; + readonly 'geoip_longitude'?: string; + readonly 'geoip_org'?: string; + readonly 'geoip_postal_code'?: string; + readonly 'geoip_region'?: string; + readonly 'geoip_region_name'?: string; + readonly 'gzip_ratio'?: string; + readonly 'host'?: string; + readonly 'hostname'?: string; + readonly 'http2'?: string; + readonly 'http_'?: string; + readonly 'https'?: string; + readonly 'invalid_referer'?: string; + readonly 'is_args'?: string; + readonly 'jwt_claim_'?: string; + readonly 'jwt_header_'?: string; + readonly 'limit_conn_status'?: string; + readonly 'limit_rate'?: string; + readonly 'limit_req_status'?: string; + readonly 'memcached_key'?: string; + readonly 'modern_browser'?: string; + readonly 'msec'?: string; + readonly 'msie'?: string; + readonly 'nginx_version'?: string; + readonly 'pid'?: string; + readonly 'pipe'?: string; + readonly 'protocol'?: string; + readonly 'proxy_add_x_forwarded_for'?: string; + readonly 'proxy_host'?: string; + readonly 'proxy_port'?: string; + readonly 'proxy_protocol_addr'?: string; + readonly 'proxy_protocol_port'?: string; + readonly 'proxy_protocol_server_addr'?: string; + readonly 'proxy_protocol_server_port'?: string; + readonly 'query_string'?: string; + readonly 'realip_remote_addr'?: string; + readonly 'realip_remote_port'?: string; + readonly 'realpath_root'?: string; + readonly 'remote_addr'?: string; + readonly 'remote_port'?: string; + readonly 'remote_user'?: string; + readonly 'request'?: string; + readonly 'request_body'?: string; + readonly 'request_body_file'?: string; + readonly 'request_completion'?: string; + readonly 'request_filename'?: string; + readonly 'request_id'?: string; + readonly 'request_length'?: string; + readonly 'request_method'?: string; + readonly 'request_time'?: string; + readonly 'request_uri'?: string; + readonly 'scheme'?: string; + readonly 'secure_link'?: string; + readonly 'secure_link_expires'?: string; + readonly 'sent_http_'?: string; + readonly 'sent_trailer_'?: string; + readonly 'server_addr'?: string; + readonly 'server_name'?: string; + readonly 'server_port'?: string; + readonly 'server_protocol'?: string; + readonly 'session_log_binary_id'?: string; + readonly 'session_log_id'?: string; + readonly 'session_time'?: string; + readonly 'slice_range'?: string; + readonly 'spdy'?: string; + readonly 'spdy_request_priority'?: string; + readonly 'ssl_cipher'?: string; + readonly 'ssl_ciphers'?: string; + readonly 'ssl_client_cert'?: string; + readonly 'ssl_client_escaped_cert'?: string; + readonly 'ssl_client_fingerprint'?: string; + readonly 'ssl_client_i_dn'?: string; + readonly 'ssl_client_i_dn_legacy'?: string; + readonly 'ssl_client_raw_cert'?: string; + readonly 'ssl_client_s_dn'?: string; + readonly 'ssl_client_s_dn_legacy'?: string; + readonly 'ssl_client_serial'?: string; + readonly 'ssl_client_v_end'?: string; + readonly 'ssl_client_v_remain'?: string; + readonly 'ssl_client_v_start'?: string; + readonly 'ssl_client_verify'?: string; + readonly 'ssl_curves'?: string; + readonly 'ssl_early_data'?: string; + readonly 'ssl_preread_alpn_protocols'?: string; + readonly 'ssl_preread_protocol'?: string; + readonly 'ssl_preread_server_name'?: string; + readonly 'ssl_protocol'?: string; + readonly 'ssl_server_name'?: string; + readonly 'ssl_session_id'?: string; + readonly 'ssl_session_reused'?: string; + readonly 'status'?: string; + readonly 'tcpinfo_rtt'?: string; + readonly 'tcpinfo_rttvar'?: string; + readonly 'tcpinfo_snd_cwnd'?: string; + readonly 'tcpinfo_rcv_space'?: string; + readonly 'time_iso8601'?: string; + readonly 'time_local'?: string; + readonly 'uid_got'?: string; + readonly 'uid_reset'?: string; + readonly 'uid_set'?: string; + readonly 'upstream_addr'?: string; + readonly 'upstream_bytes_received'?: string; + readonly 'upstream_bytes_sent'?: string; + readonly 'upstream_cache_status'?: string; + readonly 'upstream_connect_time'?: string; + readonly 'upstream_cookie_'?: string; + readonly 'upstream_first_byte_time'?: string; + readonly 'upstream_header_time'?: string; + readonly 'upstream_http_'?: string; + readonly 'upstream_queue_time'?: string; + readonly 'upstream_response_length'?: string; + readonly 'upstream_response_time'?: string; + readonly 'upstream_session_time'?: string; + readonly 'upstream_status'?: string; + readonly 'upstream_trailer_'?: string; + readonly 'uri'?: string; - [prop: string]: NjsStringLike | undefined; + [prop: string]: string | undefined; } /** @@ -244,11 +244,11 @@ interface NginxSubrequestOptions { /** * Arguments string, by default an empty string is used. */ - args?: NjsStringLike, + args?: string, /** * Request body, by default the request body of the parent request object is used. */ - body?: NjsStringLike, + body?: string, /** * HTTP method, by default the GET method is used. */ @@ -316,7 +316,7 @@ interface NginxHTTPRequest { /** * HTTP protocol version. */ - readonly httpVersion: NjsByteString; + readonly httpVersion: string; /** * Performs an internal redirect to the specified uri. * If the uri starts with the “@” prefix, it is considered a named location. @@ -333,7 +333,7 @@ interface NginxHTTPRequest { /** * HTTP method. */ - readonly method: NjsByteString; + readonly method: string; /** * Parent for subrequest object. */ @@ -342,17 +342,17 @@ interface NginxHTTPRequest { * An array of key-value pairs exactly as they were received from the client. * @since 0.4.1 */ - readonly rawHeadersIn: [NjsFixedSizeArray<2, NjsStringLike>]; + readonly rawHeadersIn: [NjsFixedSizeArray<2, string>]; /** * An array of key-value pairs of response headers. * Header field names are not converted to lower case, duplicate field values are not merged. * @since 0.4.1 */ - readonly rawHeadersOut: [NjsFixedSizeArray<2, NjsStringLike>]; + readonly rawHeadersOut: [NjsFixedSizeArray<2, string>]; /** * Client address. */ - readonly remoteAddress: NjsByteString; + readonly remoteAddress: string; /** * Client request body if it has not been written to a temporary file. * To ensure that the client request body is in memory, its size should be @@ -370,7 +370,7 @@ interface NginxHTTPRequest { * @see requestBuffer * @since 0.5.0 */ - readonly requestText?: NjsByteString; + readonly requestText?: string; /** * The same as `requestBuffer`, but returns a string. * @@ -380,7 +380,7 @@ interface NginxHTTPRequest { * @see requestText * @deprecated Use `requestText` or `requestBuffer` instead. */ - readonly requestBody?: NjsByteString; + readonly requestBody?: string; /** * Subrequest response body. The size of response body is limited by * the subrequest_output_buffer_size directive. @@ -395,7 +395,7 @@ interface NginxHTTPRequest { * * @see responseBuffer */ - readonly responseText?: NjsByteString; + readonly responseText?: string; /** * The same as `responseBuffer`, but returns a string. * @@ -405,7 +405,7 @@ interface NginxHTTPRequest { * @see responseText * @deprecated Use `responseText` or `responseBuffer` instead. */ - readonly responseBody?: NjsByteString; + readonly responseBody?: string; /** * Sends the entire response with the specified status to the client. * It is possible to specify either a redirect URL (for codes 301, 302, 303, 307, and 308) @@ -457,7 +457,7 @@ interface NginxHTTPRequest { /** * Current URI in request, normalized. */ - readonly uri: NjsByteString; + readonly uri: string; /** * nginx variables as Buffers. * diff -r 2daeeea1a05a -r fa51408510ad ts/ngx_stream_js_module.d.ts --- a/ts/ngx_stream_js_module.d.ts Tue Jun 06 21:31:39 2023 -0700 +++ b/ts/ngx_stream_js_module.d.ts Tue Jun 06 21:33:46 2023 -0700 @@ -2,72 +2,72 @@ /// interface NginxStreamVariables { - readonly 'binary_remote_addr'?: NjsByteString; - readonly 'bytes_received'?: NjsByteString; - readonly 'bytes_sent'?: NjsByteString; - readonly 'connection'?: NjsByteString; - readonly 'geoip_area_code'?: NjsByteString; - readonly 'geoip_city'?: NjsByteString; - readonly 'geoip_city_continent_code'?: NjsByteString; - readonly 'geoip_city_country_code'?: NjsByteString; - readonly 'geoip_city_country_code3'?: NjsByteString; - readonly 'geoip_city_country_name'?: NjsByteString; - readonly 'geoip_country_code'?: NjsByteString; - readonly 'geoip_country_code3'?: NjsByteString; - readonly 'geoip_country_name'?: NjsByteString; - readonly 'geoip_dma_code'?: NjsByteString; - readonly 'geoip_latitude'?: NjsByteString; - readonly 'geoip_longitude'?: NjsByteString; - readonly 'geoip_org'?: NjsByteString; - readonly 'geoip_postal_code'?: NjsByteString; - readonly 'geoip_region'?: NjsByteString; - readonly 'geoip_region_name'?: NjsByteString; - readonly 'hostname'?: NjsByteString; - readonly 'limit_conn_status'?: NjsByteString; - readonly 'msec'?: NjsByteString; - readonly 'nginx_version'?: NjsByteString; - readonly 'pid'?: NjsByteString; - readonly 'proxy_add_x_forwarded_for'?: NjsByteString; - readonly 'proxy_host'?: NjsByteString; - readonly 'proxy_port'?: NjsByteString; - readonly 'proxy_protocol_addr'?: NjsByteString; - readonly 'proxy_protocol_port'?: NjsByteString; - readonly 'proxy_protocol_server_addr'?: NjsByteString; - readonly 'proxy_protocol_server_port'?: NjsByteString; - readonly 'realip_remote_addr'?: NjsByteString; - readonly 'realip_remote_port'?: NjsByteString; - readonly 'remote_addr'?: NjsByteString; - readonly 'remote_port'?: NjsByteString; - readonly 'server_addr'?: NjsByteString; - readonly 'server_port'?: NjsByteString; - readonly 'ssl_cipher'?: NjsByteString; - readonly 'ssl_ciphers'?: NjsByteString; - readonly 'ssl_client_cert'?: NjsByteString; - readonly 'ssl_client_escaped_cert'?: NjsByteString; - readonly 'ssl_client_fingerprint'?: NjsByteString; - readonly 'ssl_client_i_dn'?: NjsByteString; - readonly 'ssl_client_raw_cert'?: NjsByteString; - readonly 'ssl_client_s_dn'?: NjsByteString; - readonly 'ssl_client_s_dn_legacy'?: NjsByteString; - readonly 'ssl_client_serial'?: NjsByteString; - readonly 'ssl_client_v_end'?: NjsByteString; - readonly 'ssl_client_v_remain'?: NjsByteString; - readonly 'ssl_client_v_start'?: NjsByteString; - readonly 'ssl_client_verify'?: NjsByteString; - readonly 'ssl_curves'?: NjsByteString; - readonly 'ssl_early_data'?: NjsByteString; - readonly 'ssl_preread_alpn_protocols'?: NjsByteString; - readonly 'ssl_preread_protocol'?: NjsByteString; - readonly 'ssl_preread_server_name'?: NjsByteString; - readonly 'ssl_protocol'?: NjsByteString; - readonly 'ssl_server_name'?: NjsByteString; - readonly 'ssl_session_id'?: NjsByteString; - readonly 'ssl_session_reused'?: NjsByteString; - readonly 'status'?: NjsByteString; - readonly 'time_iso8601'?: NjsByteString; - readonly 'time_local'?: NjsByteString; + readonly 'binary_remote_addr'?: string; + readonly 'bytes_received'?: string; + readonly 'bytes_sent'?: string; + readonly 'connection'?: string; + readonly 'geoip_area_code'?: string; + readonly 'geoip_city'?: string; + readonly 'geoip_city_continent_code'?: string; + readonly 'geoip_city_country_code'?: string; + readonly 'geoip_city_country_code3'?: string; + readonly 'geoip_city_country_name'?: string; + readonly 'geoip_country_code'?: string; + readonly 'geoip_country_code3'?: string; + readonly 'geoip_country_name'?: string; + readonly 'geoip_dma_code'?: string; + readonly 'geoip_latitude'?: string; + readonly 'geoip_longitude'?: string; + readonly 'geoip_org'?: string; + readonly 'geoip_postal_code'?: string; + readonly 'geoip_region'?: string; + readonly 'geoip_region_name'?: string; + readonly 'hostname'?: string; + readonly 'limit_conn_status'?: string; + readonly 'msec'?: string; + readonly 'nginx_version'?: string; + readonly 'pid'?: string; + readonly 'proxy_add_x_forwarded_for'?: string; + readonly 'proxy_host'?: string; + readonly 'proxy_port'?: string; + readonly 'proxy_protocol_addr'?: string; + readonly 'proxy_protocol_port'?: string; + readonly 'proxy_protocol_server_addr'?: string; + readonly 'proxy_protocol_server_port'?: string; + readonly 'realip_remote_addr'?: string; + readonly 'realip_remote_port'?: string; + readonly 'remote_addr'?: string; + readonly 'remote_port'?: string; + readonly 'server_addr'?: string; + readonly 'server_port'?: string; + readonly 'ssl_cipher'?: string; + readonly 'ssl_ciphers'?: string; + readonly 'ssl_client_cert'?: string; + readonly 'ssl_client_escaped_cert'?: string; + readonly 'ssl_client_fingerprint'?: string; + readonly 'ssl_client_i_dn'?: string; + readonly 'ssl_client_raw_cert'?: string; + readonly 'ssl_client_s_dn'?: string; + readonly 'ssl_client_s_dn_legacy'?: string; + readonly 'ssl_client_serial'?: string; + readonly 'ssl_client_v_end'?: string; + readonly 'ssl_client_v_remain'?: string; + readonly 'ssl_client_v_start'?: string; + readonly 'ssl_client_verify'?: string; + readonly 'ssl_curves'?: string; + readonly 'ssl_early_data'?: string; + readonly 'ssl_preread_alpn_protocols'?: string; + readonly 'ssl_preread_protocol'?: string; + readonly 'ssl_preread_server_name'?: string; + readonly 'ssl_protocol'?: string; + readonly 'ssl_server_name'?: string; + readonly 'ssl_session_id'?: string; + readonly 'ssl_session_reused'?: string; + readonly 'status'?: string; + readonly 'time_iso8601'?: string; + readonly 'time_local'?: string; - [prop: string]: NjsByteString | undefined; + [prop: string]: string | undefined; } /** @@ -165,13 +165,13 @@ interface NginxStreamRequest { * @see off() */ on(event: "upload" | "download", - callback: (data: NjsByteString, flags: NginxStreamCallbackFlags) => void): void; + callback: (data: string, flags: NginxStreamCallbackFlags) => void): void; on(event: "upstream" | "downstream", callback: (data: Buffer, flags: NginxStreamCallbackFlags) => void): void; /** * Client address. */ - readonly remoteAddress: NjsByteString; + readonly remoteAddress: string; /** * Adds data to the chain of data chunks that will be forwarded in * the forward direction: in download callback to a client; in upload diff -r 2daeeea1a05a -r fa51408510ad ts/njs_core.d.ts --- a/ts/njs_core.d.ts Tue Jun 06 21:31:39 2023 -0700 +++ b/ts/njs_core.d.ts Tue Jun 06 21:33:46 2023 -0700 @@ -5,63 +5,6 @@ type NjsFixedSizeArray; - -interface StringConstructor { - /** - * Creates a byte string from an encoded string. - * - * @deprecated will be removed in the future. - */ From arut at nginx.com Thu Jun 8 12:53:56 2023 From: arut at nginx.com (Roman Arutyunyan) Date: Thu, 08 Jun 2023 12:53:56 +0000 Subject: [nginx] HTTP/2: "http2" directive. Message-ID: details: https://hg.nginx.org/nginx/rev/08ef02ad5c54 branches: changeset: 9119:08ef02ad5c54 user: Roman Arutyunyan date: Tue May 16 16:30:08 2023 +0400 description: HTTP/2: "http2" directive. The directive enables HTTP/2 in the current server. The previous way to enable HTTP/2 via "listen ... http2" is now deprecated. The new approach allows to share HTTP/2 and HTTP/0.9-1.1 on the same port. For SSL connections, HTTP/2 is now selected by ALPN callback based on whether the protocol is enabled in the virtual server chosen by SNI. This however only works since OpenSSL 1.0.2h, where ALPN callback is invoked after SNI callback. For older versions of OpenSSL, HTTP/2 is enabled based on the default virtual server configuration. For plain TCP connections, HTTP/2 is now auto-detected by HTTP/2 preface, if HTTP/2 is enabled in the default virtual server. If preface is not matched, HTTP/0.9-1.1 is assumed. diffstat: src/http/modules/ngx_http_ssl_module.c | 24 ++++++++---- src/http/ngx_http_core_module.c | 5 ++ src/http/ngx_http_request.c | 61 +++++++++++++++++++++++++-------- src/http/v2/ngx_http_v2.c | 60 ++++++++++++++++++--------------- src/http/v2/ngx_http_v2.h | 18 ++++++++++ src/http/v2/ngx_http_v2_module.c | 11 ++++++ src/http/v2/ngx_http_v2_module.h | 12 ------ 7 files changed, 128 insertions(+), 63 deletions(-) diffs (391 lines): diff -r b4a57278bf24 -r 08ef02ad5c54 src/http/modules/ngx_http_ssl_module.c --- a/src/http/modules/ngx_http_ssl_module.c Sun May 28 11:17:07 2023 +0400 +++ b/src/http/modules/ngx_http_ssl_module.c Tue May 16 16:30:08 2023 +0400 @@ -435,6 +435,9 @@ ngx_http_ssl_alpn_select(ngx_ssl_conn_t #if (NGX_HTTP_V2 || NGX_HTTP_V3) ngx_http_connection_t *hc; #endif +#if (NGX_HTTP_V2) + ngx_http_v2_srv_conf_t *h2scf; +#endif #if (NGX_HTTP_V3) ngx_http_v3_srv_conf_t *h3scf; #endif @@ -456,12 +459,6 @@ ngx_http_ssl_alpn_select(ngx_ssl_conn_t hc = c->data; #endif -#if (NGX_HTTP_V2) - if (hc->addr_conf->http2) { - srv = (unsigned char *) NGX_HTTP_V2_ALPN_PROTO NGX_HTTP_ALPN_PROTOS; - srvlen = sizeof(NGX_HTTP_V2_ALPN_PROTO NGX_HTTP_ALPN_PROTOS) - 1; - } else -#endif #if (NGX_HTTP_V3) if (hc->addr_conf->quic) { @@ -488,8 +485,19 @@ ngx_http_ssl_alpn_select(ngx_ssl_conn_t } else #endif { - srv = (unsigned char *) NGX_HTTP_ALPN_PROTOS; - srvlen = sizeof(NGX_HTTP_ALPN_PROTOS) - 1; +#if (NGX_HTTP_V2) + h2scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v2_module); + + if (h2scf->enable || hc->addr_conf->http2) { + srv = (unsigned char *) NGX_HTTP_V2_ALPN_PROTO NGX_HTTP_ALPN_PROTOS; + srvlen = sizeof(NGX_HTTP_V2_ALPN_PROTO NGX_HTTP_ALPN_PROTOS) - 1; + + } else +#endif + { + srv = (unsigned char *) NGX_HTTP_ALPN_PROTOS; + srvlen = sizeof(NGX_HTTP_ALPN_PROTOS) - 1; + } } if (SSL_select_next_proto((unsigned char **) out, outlen, srv, srvlen, diff -r b4a57278bf24 -r 08ef02ad5c54 src/http/ngx_http_core_module.c --- a/src/http/ngx_http_core_module.c Sun May 28 11:17:07 2023 +0400 +++ b/src/http/ngx_http_core_module.c Tue May 16 16:30:08 2023 +0400 @@ -4176,6 +4176,11 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx if (ngx_strcmp(value[n].data, "http2") == 0) { #if (NGX_HTTP_V2) + ngx_conf_log_error(NGX_LOG_WARN, cf, 0, + "the \"listen ... http2\" directive " + "is deprecated, use " + "the \"http2\" directive instead"); + lsopt.http2 = 1; continue; #else diff -r b4a57278bf24 -r 08ef02ad5c54 src/http/ngx_http_request.c --- a/src/http/ngx_http_request.c Sun May 28 11:17:07 2023 +0400 +++ b/src/http/ngx_http_request.c Tue May 16 16:30:08 2023 +0400 @@ -318,12 +318,6 @@ ngx_http_init_connection(ngx_connection_ rev->handler = ngx_http_wait_request_handler; c->write->handler = ngx_http_empty_handler; -#if (NGX_HTTP_V2) - if (hc->addr_conf->http2) { - rev->handler = ngx_http_v2_init; - } -#endif - #if (NGX_HTTP_V3) if (hc->addr_conf->quic) { ngx_http_v3_init_stream(c); @@ -383,6 +377,9 @@ ngx_http_wait_request_handler(ngx_event_ ngx_buf_t *b; ngx_connection_t *c; ngx_http_connection_t *hc; +#if (NGX_HTTP_V2) + ngx_http_v2_srv_conf_t *h2scf; +#endif ngx_http_core_srv_conf_t *cscf; c = rev->data; @@ -429,6 +426,8 @@ ngx_http_wait_request_handler(ngx_event_ b->end = b->last + size; } + size = b->end - b->last; + n = c->recv(c, b->last, size); if (n == NGX_AGAIN) { @@ -443,12 +442,16 @@ ngx_http_wait_request_handler(ngx_event_ return; } - /* - * We are trying to not hold c->buffer's memory for an idle connection. - */ - - if (ngx_pfree(c->pool, b->start) == NGX_OK) { - b->start = NULL; + if (b->pos == b->last) { + + /* + * We are trying to not hold c->buffer's memory for an + * idle connection. + */ + + if (ngx_pfree(c->pool, b->start) == NGX_OK) { + b->start = NULL; + } } return; @@ -489,6 +492,29 @@ ngx_http_wait_request_handler(ngx_event_ } } +#if (NGX_HTTP_V2) + + h2scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v2_module); + + if (!hc->ssl && (h2scf->enable || hc->addr_conf->http2)) { + + size = ngx_min(sizeof(NGX_HTTP_V2_PREFACE) - 1, + (size_t) (b->last - b->pos)); + + if (ngx_memcmp(b->pos, NGX_HTTP_V2_PREFACE, size) == 0) { + + if (size == sizeof(NGX_HTTP_V2_PREFACE) - 1) { + ngx_http_v2_init(rev); + return; + } + + ngx_post_event(rev, &ngx_posted_events); + return; + } + } + +#endif + c->log->action = "reading client request line"; ngx_reusable_connection(c, 0); @@ -808,13 +834,16 @@ ngx_http_ssl_handshake_handler(ngx_conne #if (NGX_HTTP_V2 \ && defined TLSEXT_TYPE_application_layer_protocol_negotiation) { - unsigned int len; - const unsigned char *data; - ngx_http_connection_t *hc; + unsigned int len; + const unsigned char *data; + ngx_http_connection_t *hc; + ngx_http_v2_srv_conf_t *h2scf; hc = c->data; - if (hc->addr_conf->http2) { + h2scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v2_module); + + if (h2scf->enable || hc->addr_conf->http2) { SSL_get0_alpn_selected(c->ssl->connection, &data, &len); diff -r b4a57278bf24 -r 08ef02ad5c54 src/http/v2/ngx_http_v2.c --- a/src/http/v2/ngx_http_v2.c Sun May 28 11:17:07 2023 +0400 +++ b/src/http/v2/ngx_http_v2.c Tue May 16 16:30:08 2023 +0400 @@ -63,8 +63,6 @@ static void ngx_http_v2_handle_connectio static void ngx_http_v2_lingering_close(ngx_connection_t *c); static void ngx_http_v2_lingering_close_handler(ngx_event_t *rev); -static u_char *ngx_http_v2_state_proxy_protocol(ngx_http_v2_connection_t *h2c, - u_char *pos, u_char *end); static u_char *ngx_http_v2_state_preface(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end); static u_char *ngx_http_v2_state_preface_end(ngx_http_v2_connection_t *h2c, @@ -232,6 +230,7 @@ static ngx_http_v2_parse_header_t ngx_h void ngx_http_v2_init(ngx_event_t *rev) { + u_char *p, *end; ngx_connection_t *c; ngx_pool_cleanup_t *cln; ngx_http_connection_t *hc; @@ -314,8 +313,7 @@ ngx_http_v2_init(ngx_event_t *rev) return; } - h2c->state.handler = hc->proxy_protocol ? ngx_http_v2_state_proxy_protocol - : ngx_http_v2_state_preface; + h2c->state.handler = ngx_http_v2_state_preface; ngx_queue_init(&h2c->waiting); ngx_queue_init(&h2c->dependencies); @@ -335,6 +333,23 @@ ngx_http_v2_init(ngx_event_t *rev) c->idle = 1; ngx_reusable_connection(c, 0); + if (c->buffer) { + p = c->buffer->pos; + end = c->buffer->last; + + do { + p = h2c->state.handler(h2c, p, end); + + if (p == NULL) { + return; + } + + } while (p != end); + + h2c->total_bytes += p - c->buffer->pos; + c->buffer->pos = p; + } + ngx_http_v2_read_handler(rev); } @@ -847,31 +862,10 @@ ngx_http_v2_lingering_close_handler(ngx_ static u_char * -ngx_http_v2_state_proxy_protocol(ngx_http_v2_connection_t *h2c, u_char *pos, - u_char *end) -{ - ngx_log_t *log; - - log = h2c->connection->log; - log->action = "reading PROXY protocol"; - - pos = ngx_proxy_protocol_read(h2c->connection, pos, end); - - log->action = "processing HTTP/2 connection"; - - if (pos == NULL) { - return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_PROTOCOL_ERROR); - } - - return ngx_http_v2_state_preface(h2c, pos, end); -} - - -static u_char * ngx_http_v2_state_preface(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end) { - static const u_char preface[] = "PRI * HTTP/2.0\r\n"; + static const u_char preface[] = NGX_HTTP_V2_PREFACE_START; if ((size_t) (end - pos) < sizeof(preface) - 1) { return ngx_http_v2_state_save(h2c, pos, end, ngx_http_v2_state_preface); @@ -892,7 +886,7 @@ static u_char * ngx_http_v2_state_preface_end(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end) { - static const u_char preface[] = "\r\nSM\r\n\r\n"; + static const u_char preface[] = NGX_HTTP_V2_PREFACE_END; if ((size_t) (end - pos) < sizeof(preface) - 1) { return ngx_http_v2_state_save(h2c, pos, end, @@ -3943,10 +3937,22 @@ static void ngx_http_v2_run_request(ngx_http_request_t *r) { ngx_connection_t *fc; + ngx_http_v2_srv_conf_t *h2scf; ngx_http_v2_connection_t *h2c; fc = r->connection; + h2scf = ngx_http_get_module_srv_conf(r, ngx_http_v2_module); + + if (!h2scf->enable && !r->http_connection->addr_conf->http2) { + ngx_log_error(NGX_LOG_INFO, fc->log, 0, + "client attempted to request the server name " + "for which the negotiated protocol is disabled"); + + ngx_http_finalize_request(r, NGX_HTTP_MISDIRECTED_REQUEST); + goto failed; + } + if (ngx_http_v2_construct_request_line(r) != NGX_OK) { goto failed; } diff -r b4a57278bf24 -r 08ef02ad5c54 src/http/v2/ngx_http_v2.h --- a/src/http/v2/ngx_http_v2.h Sun May 28 11:17:07 2023 +0400 +++ b/src/http/v2/ngx_http_v2.h Tue May 16 16:30:08 2023 +0400 @@ -64,6 +64,16 @@ typedef u_char *(*ngx_http_v2_handler_pt typedef struct { + ngx_flag_t enable; + size_t pool_size; + ngx_uint_t concurrent_streams; + ngx_uint_t concurrent_pushes; + size_t preread_size; + ngx_uint_t streams_index_mask; +} ngx_http_v2_srv_conf_t; + + +typedef struct { ngx_str_t name; ngx_str_t value; } ngx_http_v2_header_t; @@ -408,9 +418,17 @@ ngx_int_t ngx_http_v2_table_size(ngx_htt #define NGX_HTTP_V2_USER_AGENT_INDEX 58 #define NGX_HTTP_V2_VARY_INDEX 59 +#define NGX_HTTP_V2_PREFACE_START "PRI * HTTP/2.0\r\n" +#define NGX_HTTP_V2_PREFACE_END "\r\nSM\r\n\r\n" +#define NGX_HTTP_V2_PREFACE NGX_HTTP_V2_PREFACE_START \ + NGX_HTTP_V2_PREFACE_END + u_char *ngx_http_v2_string_encode(u_char *dst, u_char *src, size_t len, u_char *tmp, ngx_uint_t lower); +extern ngx_module_t ngx_http_v2_module; + + #endif /* _NGX_HTTP_V2_H_INCLUDED_ */ diff -r b4a57278bf24 -r 08ef02ad5c54 src/http/v2/ngx_http_v2_module.c --- a/src/http/v2/ngx_http_v2_module.c Sun May 28 11:17:07 2023 +0400 +++ b/src/http/v2/ngx_http_v2_module.c Tue May 16 16:30:08 2023 +0400 @@ -75,6 +75,13 @@ static ngx_conf_post_t ngx_http_v2_chun static ngx_command_t ngx_http_v2_commands[] = { + { ngx_string("http2"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_HTTP_SRV_CONF_OFFSET, + offsetof(ngx_http_v2_srv_conf_t, enable), + NULL }, + { ngx_string("http2_recv_buffer_size"), NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, ngx_conf_set_size_slot, @@ -314,6 +321,8 @@ ngx_http_v2_create_srv_conf(ngx_conf_t * return NULL; } + h2scf->enable = NGX_CONF_UNSET; + h2scf->pool_size = NGX_CONF_UNSET_SIZE; h2scf->concurrent_streams = NGX_CONF_UNSET_UINT; @@ -333,6 +342,8 @@ ngx_http_v2_merge_srv_conf(ngx_conf_t *c ngx_http_v2_srv_conf_t *prev = parent; ngx_http_v2_srv_conf_t *conf = child; + ngx_conf_merge_value(conf->enable, prev->enable, 0); + ngx_conf_merge_size_value(conf->pool_size, prev->pool_size, 4096); ngx_conf_merge_uint_value(conf->concurrent_streams, diff -r b4a57278bf24 -r 08ef02ad5c54 src/http/v2/ngx_http_v2_module.h --- a/src/http/v2/ngx_http_v2_module.h Sun May 28 11:17:07 2023 +0400 +++ b/src/http/v2/ngx_http_v2_module.h Tue May 16 16:30:08 2023 +0400 @@ -21,15 +21,6 @@ typedef struct { typedef struct { - size_t pool_size; - ngx_uint_t concurrent_streams; - ngx_uint_t concurrent_pushes; - size_t preread_size; - ngx_uint_t streams_index_mask; -} ngx_http_v2_srv_conf_t; - - -typedef struct { size_t chunk_size; ngx_flag_t push_preload; @@ -39,7 +30,4 @@ typedef struct { } ngx_http_v2_loc_conf_t; -extern ngx_module_t ngx_http_v2_module; - - #endif /* _NGX_HTTP_V2_MODULE_H_INCLUDED_ */ From arut at nginx.com Thu Jun 8 12:53:59 2023 From: arut at nginx.com (Roman Arutyunyan) Date: Thu, 08 Jun 2023 12:53:59 +0000 Subject: [nginx] SSL: removed the "ssl" directive. Message-ID: details: https://hg.nginx.org/nginx/rev/0aaa09927703 branches: changeset: 9120:0aaa09927703 user: Roman Arutyunyan date: Thu Jun 08 14:49:27 2023 +0400 description: SSL: removed the "ssl" directive. It has been deprecated since 7270:46c0c7ef4913 (1.15.0) in favour of the "ssl" parameter of the "listen" directive, which has been available since 2224:109849282793 (0.7.14). diffstat: src/http/modules/ngx_http_ssl_module.c | 78 +--------------------------------- src/http/modules/ngx_http_ssl_module.h | 5 -- src/http/ngx_http_request.c | 8 +--- src/mail/ngx_mail_handler.c | 6 +- src/mail/ngx_mail_ssl_module.c | 53 ----------------------- src/mail/ngx_mail_ssl_module.h | 1 - 6 files changed, 5 insertions(+), 146 deletions(-) diffs (312 lines): diff -r 08ef02ad5c54 -r 0aaa09927703 src/http/modules/ngx_http_ssl_module.c --- a/src/http/modules/ngx_http_ssl_module.c Tue May 16 16:30:08 2023 +0400 +++ b/src/http/modules/ngx_http_ssl_module.c Thu Jun 08 14:49:27 2023 +0400 @@ -43,8 +43,6 @@ static char *ngx_http_ssl_merge_srv_conf static ngx_int_t ngx_http_ssl_compile_certificates(ngx_conf_t *cf, ngx_http_ssl_srv_conf_t *conf); -static char *ngx_http_ssl_enable(ngx_conf_t *cf, ngx_command_t *cmd, - void *conf); static char *ngx_http_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char *ngx_http_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd, @@ -90,24 +88,12 @@ static ngx_conf_enum_t ngx_http_ssl_ocs }; -static ngx_conf_deprecated_t ngx_http_ssl_deprecated = { - ngx_conf_deprecated, "ssl", "listen ... ssl" -}; - - static ngx_conf_post_t ngx_http_ssl_conf_command_post = { ngx_http_ssl_conf_command_check }; static ngx_command_t ngx_http_ssl_commands[] = { - { ngx_string("ssl"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG, - ngx_http_ssl_enable, - NGX_HTTP_SRV_CONF_OFFSET, - offsetof(ngx_http_ssl_srv_conf_t, enable), - &ngx_http_ssl_deprecated }, - { ngx_string("ssl_certificate"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, ngx_conf_set_str_array_slot, @@ -625,7 +611,6 @@ ngx_http_ssl_create_srv_conf(ngx_conf_t * sscf->stapling_responder = { 0, NULL }; */ - sscf->enable = NGX_CONF_UNSET; sscf->prefer_server_ciphers = NGX_CONF_UNSET; sscf->early_data = NGX_CONF_UNSET; sscf->reject_handshake = NGX_CONF_UNSET; @@ -657,17 +642,6 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t * ngx_pool_cleanup_t *cln; - if (conf->enable == NGX_CONF_UNSET) { - if (prev->enable == NGX_CONF_UNSET) { - conf->enable = 0; - - } else { - conf->enable = prev->enable; - conf->file = prev->file; - conf->line = prev->line; - } - } - ngx_conf_merge_value(conf->session_timeout, prev->session_timeout, 300); @@ -722,37 +696,7 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t * conf->ssl.log = cf->log; - if (conf->enable) { - - if (conf->certificates) { - if (conf->certificate_keys == NULL) { - ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "no \"ssl_certificate_key\" is defined for " - "the \"ssl\" directive in %s:%ui", - conf->file, conf->line); - return NGX_CONF_ERROR; - } - - if (conf->certificate_keys->nelts < conf->certificates->nelts) { - ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "no \"ssl_certificate_key\" is defined " - "for certificate \"%V\" and " - "the \"ssl\" directive in %s:%ui", - ((ngx_str_t *) conf->certificates->elts) - + conf->certificates->nelts - 1, - conf->file, conf->line); - return NGX_CONF_ERROR; - } - - } else if (!conf->reject_handshake) { - ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "no \"ssl_certificate\" is defined for " - "the \"ssl\" directive in %s:%ui", - conf->file, conf->line); - return NGX_CONF_ERROR; - } - - } else if (conf->certificates) { + if (conf->certificates) { if (conf->certificate_keys == NULL || conf->certificate_keys->nelts < conf->certificates->nelts) @@ -1039,26 +983,6 @@ found: static char * -ngx_http_ssl_enable(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_http_ssl_srv_conf_t *sscf = conf; - - char *rv; - - rv = ngx_conf_set_flag_slot(cf, cmd, conf); - - if (rv != NGX_CONF_OK) { - return rv; - } - - sscf->file = cf->conf_file->file.name.data; - sscf->line = cf->conf_file->line; - - return NGX_CONF_OK; -} - - -static char * ngx_http_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_ssl_srv_conf_t *sscf = conf; diff -r 08ef02ad5c54 -r 0aaa09927703 src/http/modules/ngx_http_ssl_module.h --- a/src/http/modules/ngx_http_ssl_module.h Tue May 16 16:30:08 2023 +0400 +++ b/src/http/modules/ngx_http_ssl_module.h Thu Jun 08 14:49:27 2023 +0400 @@ -15,8 +15,6 @@ typedef struct { - ngx_flag_t enable; - ngx_ssl_t ssl; ngx_flag_t prefer_server_ciphers; @@ -64,9 +62,6 @@ typedef struct { ngx_flag_t stapling_verify; ngx_str_t stapling_file; ngx_str_t stapling_responder; - - u_char *file; - ngx_uint_t line; } ngx_http_ssl_srv_conf_t; diff -r 08ef02ad5c54 -r 0aaa09927703 src/http/ngx_http_request.c --- a/src/http/ngx_http_request.c Tue May 16 16:30:08 2023 +0400 +++ b/src/http/ngx_http_request.c Thu Jun 08 14:49:27 2023 +0400 @@ -326,17 +326,11 @@ ngx_http_init_connection(ngx_connection_ #endif #if (NGX_HTTP_SSL) - { - ngx_http_ssl_srv_conf_t *sscf; - - sscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_ssl_module); - - if (sscf->enable || hc->addr_conf->ssl) { + if (hc->addr_conf->ssl) { hc->ssl = 1; c->log->action = "SSL handshaking"; rev->handler = ngx_http_ssl_handshake; } - } #endif if (hc->addr_conf->proxy_protocol) { diff -r 08ef02ad5c54 -r 0aaa09927703 src/mail/ngx_mail_handler.c --- a/src/mail/ngx_mail_handler.c Tue May 16 16:30:08 2023 +0400 +++ b/src/mail/ngx_mail_handler.c Thu Jun 08 14:49:27 2023 +0400 @@ -283,10 +283,10 @@ ngx_mail_init_session_handler(ngx_event_ s = c->data; - sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); + if (s->ssl) { + c->log->action = "SSL handshaking"; - if (sslcf->enable || s->ssl) { - c->log->action = "SSL handshaking"; + sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); ngx_mail_ssl_init_connection(&sslcf->ssl, c); return; diff -r 08ef02ad5c54 -r 0aaa09927703 src/mail/ngx_mail_ssl_module.c --- a/src/mail/ngx_mail_ssl_module.c Tue May 16 16:30:08 2023 +0400 +++ b/src/mail/ngx_mail_ssl_module.c Thu Jun 08 14:49:27 2023 +0400 @@ -23,8 +23,6 @@ static int ngx_mail_ssl_alpn_select(ngx_ static void *ngx_mail_ssl_create_conf(ngx_conf_t *cf); static char *ngx_mail_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child); -static char *ngx_mail_ssl_enable(ngx_conf_t *cf, ngx_command_t *cmd, - void *conf); static char *ngx_mail_ssl_starttls(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char *ngx_mail_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, @@ -65,24 +63,12 @@ static ngx_conf_enum_t ngx_mail_ssl_ver }; -static ngx_conf_deprecated_t ngx_mail_ssl_deprecated = { - ngx_conf_deprecated, "ssl", "listen ... ssl" -}; - - static ngx_conf_post_t ngx_mail_ssl_conf_command_post = { ngx_mail_ssl_conf_command_check }; static ngx_command_t ngx_mail_ssl_commands[] = { - { ngx_string("ssl"), - NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_FLAG, - ngx_mail_ssl_enable, - NGX_MAIL_SRV_CONF_OFFSET, - offsetof(ngx_mail_ssl_conf_t, enable), - &ngx_mail_ssl_deprecated }, - { ngx_string("starttls"), NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, ngx_mail_ssl_starttls, @@ -322,7 +308,6 @@ ngx_mail_ssl_create_conf(ngx_conf_t *cf) * scf->shm_zone = NULL; */ - scf->enable = NGX_CONF_UNSET; scf->starttls = NGX_CONF_UNSET_UINT; scf->certificates = NGX_CONF_UNSET_PTR; scf->certificate_keys = NGX_CONF_UNSET_PTR; @@ -349,7 +334,6 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, char *mode; ngx_pool_cleanup_t *cln; - ngx_conf_merge_value(conf->enable, prev->enable, 0); ngx_conf_merge_uint_value(conf->starttls, prev->starttls, NGX_MAIL_STARTTLS_OFF); @@ -394,9 +378,6 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, if (conf->listen) { mode = "listen ... ssl"; - } else if (conf->enable) { - mode = "ssl"; - } else if (conf->starttls != NGX_MAIL_STARTTLS_OFF) { mode = "starttls"; @@ -546,34 +527,6 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, static char * -ngx_mail_ssl_enable(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) -{ - ngx_mail_ssl_conf_t *scf = conf; - - char *rv; - - rv = ngx_conf_set_flag_slot(cf, cmd, conf); - - if (rv != NGX_CONF_OK) { - return rv; - } - - if (scf->enable && (ngx_int_t) scf->starttls > NGX_MAIL_STARTTLS_OFF) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "\"starttls\" directive conflicts with \"ssl on\""); - return NGX_CONF_ERROR; - } - - if (!scf->listen) { - scf->file = cf->conf_file->file.name.data; - scf->line = cf->conf_file->line; - } - - return NGX_CONF_OK; -} - - -static char * ngx_mail_ssl_starttls(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_mail_ssl_conf_t *scf = conf; @@ -586,12 +539,6 @@ ngx_mail_ssl_starttls(ngx_conf_t *cf, ng return rv; } - if (scf->enable == 1 && (ngx_int_t) scf->starttls > NGX_MAIL_STARTTLS_OFF) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "\"ssl\" directive conflicts with \"starttls\""); - return NGX_CONF_ERROR; - } - if (!scf->listen) { scf->file = cf->conf_file->file.name.data; scf->line = cf->conf_file->line; diff -r 08ef02ad5c54 -r 0aaa09927703 src/mail/ngx_mail_ssl_module.h --- a/src/mail/ngx_mail_ssl_module.h Tue May 16 16:30:08 2023 +0400 +++ b/src/mail/ngx_mail_ssl_module.h Thu Jun 08 14:49:27 2023 +0400 @@ -20,7 +20,6 @@ typedef struct { - ngx_flag_t enable; ngx_flag_t prefer_server_ciphers; ngx_ssl_t ssl; From pluknet at nginx.com Thu Jun 8 12:58:41 2023 From: pluknet at nginx.com (Sergey Kandaurov) Date: Thu, 08 Jun 2023 12:58:41 +0000 Subject: [nginx] HTTP/2: removed server push (ticket #2432). Message-ID: details: https://hg.nginx.org/nginx/rev/262c01782566 branches: changeset: 9121:262c01782566 user: Sergey Kandaurov date: Thu Jun 08 16:56:46 2023 +0400 description: HTTP/2: removed server push (ticket #2432). Although it has better implementation status than HTTP/3 server push, it remains of limited use, with adoption numbers seen as negligible. Per IETF 102 materials, server push was used only in 0.04% of sessions. It was considered to be "difficult to use effectively" in RFC 9113. Its use is further limited by badly matching to fetch/cache/connection models in browsers, see related discussions linked from [1]. Server push was disabled in Chrome 106 [2]. The http2_push, http2_push_preload, and http2_max_concurrent_pushes directives are made obsolete. In particular, this essentially reverts 7201:641306096f5b and 7207:3d2b0b02bd3d. [1] https://jakearchibald.com/2017/h2-push-tougher-than-i-thought/ [2] https://chromestatus.com/feature/6302414934114304 diffstat: auto/modules | 2 - src/http/v2/ngx_http_v2.c | 320 ++-------------- src/http/v2/ngx_http_v2.h | 14 - src/http/v2/ngx_http_v2_filter_module.c | 622 +------------------------------- src/http/v2/ngx_http_v2_module.c | 111 +---- src/http/v2/ngx_http_v2_module.h | 5 - 6 files changed, 59 insertions(+), 1015 deletions(-) diffs (truncated from 1466 to 1000 lines): diff -r 0aaa09927703 -r 262c01782566 auto/modules --- a/auto/modules Thu Jun 08 14:49:27 2023 +0400 +++ b/auto/modules Thu Jun 08 16:56:46 2023 +0400 @@ -423,7 +423,6 @@ if [ $HTTP = YES ]; then if [ $HTTP_V2 = YES ]; then have=NGX_HTTP_V2 . auto/have - have=NGX_HTTP_HEADERS . auto/have ngx_module_name=ngx_http_v2_module ngx_module_incs=src/http/v2 @@ -444,7 +443,6 @@ if [ $HTTP = YES ]; then HTTP_SSL=YES have=NGX_HTTP_V3 . auto/have - have=NGX_HTTP_HEADERS . auto/have ngx_module_name=ngx_http_v3_module ngx_module_incs=src/http/v3 diff -r 0aaa09927703 -r 262c01782566 src/http/v2/ngx_http_v2.c --- a/src/http/v2/ngx_http_v2.c Thu Jun 08 14:49:27 2023 +0400 +++ b/src/http/v2/ngx_http_v2.c Thu Jun 08 16:56:46 2023 +0400 @@ -11,14 +11,6 @@ #include -typedef struct { - ngx_str_t name; - ngx_uint_t offset; - ngx_uint_t hash; - ngx_http_header_t *hh; -} ngx_http_v2_parse_header_t; - - /* errors */ #define NGX_HTTP_V2_NO_ERROR 0x0 #define NGX_HTTP_V2_PROTOCOL_ERROR 0x1 @@ -126,7 +118,7 @@ static ngx_int_t ngx_http_v2_parse_int(n u_char **pos, u_char *end, ngx_uint_t prefix); static ngx_http_v2_stream_t *ngx_http_v2_create_stream( - ngx_http_v2_connection_t *h2c, ngx_uint_t push); + ngx_http_v2_connection_t *h2c); static ngx_http_v2_node_t *ngx_http_v2_get_node_by_id( ngx_http_v2_connection_t *h2c, ngx_uint_t sid, ngx_uint_t alloc); static ngx_http_v2_node_t *ngx_http_v2_get_closed_node( @@ -162,14 +154,11 @@ static ngx_int_t ngx_http_v2_parse_schem ngx_str_t *value); static ngx_int_t ngx_http_v2_parse_authority(ngx_http_request_t *r, ngx_str_t *value); -static ngx_int_t ngx_http_v2_parse_header(ngx_http_request_t *r, - ngx_http_v2_parse_header_t *header, ngx_str_t *value); static ngx_int_t ngx_http_v2_construct_request_line(ngx_http_request_t *r); static ngx_int_t ngx_http_v2_cookie(ngx_http_request_t *r, ngx_http_v2_header_t *header); static ngx_int_t ngx_http_v2_construct_cookie_header(ngx_http_request_t *r); static void ngx_http_v2_run_request(ngx_http_request_t *r); -static void ngx_http_v2_run_request_handler(ngx_event_t *ev); static ngx_int_t ngx_http_v2_process_request_body(ngx_http_request_t *r, u_char *pos, size_t size, ngx_uint_t last, ngx_uint_t flush); static ngx_int_t ngx_http_v2_filter_request_body(ngx_http_request_t *r); @@ -210,23 +199,6 @@ static ngx_http_v2_handler_pt ngx_http_v (sizeof(ngx_http_v2_frame_states) / sizeof(ngx_http_v2_handler_pt)) -static ngx_http_v2_parse_header_t ngx_http_v2_parse_headers[] = { - { ngx_string("host"), - offsetof(ngx_http_headers_in_t, host), 0, NULL }, - - { ngx_string("accept-encoding"), - offsetof(ngx_http_headers_in_t, accept_encoding), 0, NULL }, - - { ngx_string("accept-language"), - offsetof(ngx_http_headers_in_t, accept_language), 0, NULL }, - - { ngx_string("user-agent"), - offsetof(ngx_http_headers_in_t, user_agent), 0, NULL }, - - { ngx_null_string, 0, 0, NULL } -}; - - void ngx_http_v2_init(ngx_event_t *rev) { @@ -275,7 +247,6 @@ ngx_http_v2_init(ngx_event_t *rev) h2scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v2_module); - h2c->concurrent_pushes = h2scf->concurrent_pushes; h2c->priority_limit = ngx_max(h2scf->concurrent_streams, 100); h2c->pool = ngx_create_pool(h2scf->pool_size, h2c->connection->log); @@ -385,7 +356,7 @@ ngx_http_v2_read_handler(ngx_event_t *re return; } - if (!h2c->processing && !h2c->pushing) { + if (!h2c->processing) { ngx_http_v2_finalize_connection(h2c, NGX_HTTP_V2_NO_ERROR); return; } @@ -428,9 +399,7 @@ ngx_http_v2_read_handler(ngx_event_t *re break; } - if (n == 0 - && (h2c->state.incomplete || h2c->processing || h2c->pushing)) - { + if (n == 0 && (h2c->state.incomplete || h2c->processing)) { ngx_log_error(NGX_LOG_INFO, c->log, 0, "client prematurely closed connection"); } @@ -653,7 +622,7 @@ ngx_http_v2_handle_connection(ngx_http_v ngx_connection_t *c; ngx_http_core_loc_conf_t *clcf; - if (h2c->last_out || h2c->processing || h2c->pushing) { + if (h2c->last_out || h2c->processing) { return; } @@ -1338,7 +1307,7 @@ ngx_http_v2_state_headers(ngx_http_v2_co h2c->closed_nodes--; } - stream = ngx_http_v2_create_stream(h2c, 0); + stream = ngx_http_v2_create_stream(h2c); if (stream == NULL) { return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR); } @@ -2127,11 +2096,6 @@ ngx_http_v2_state_rst_stream(ngx_http_v2 "client canceled stream %ui", h2c->state.sid); break; - case NGX_HTTP_V2_REFUSED_STREAM: - ngx_log_error(NGX_LOG_INFO, fc->log, 0, - "client refused stream %ui", h2c->state.sid); - break; - case NGX_HTTP_V2_INTERNAL_ERROR: ngx_log_error(NGX_LOG_INFO, fc->log, 0, "client terminated stream %ui due to internal error", @@ -2199,7 +2163,6 @@ ngx_http_v2_state_settings_params(ngx_ht { ssize_t window_delta; ngx_uint_t id, value; - ngx_http_v2_srv_conf_t *h2scf; ngx_http_v2_out_frame_t *frame; window_delta = 0; @@ -2261,14 +2224,6 @@ ngx_http_v2_state_settings_params(ngx_ht NGX_HTTP_V2_PROTOCOL_ERROR); } - h2c->push_disabled = !value; - break; - - case NGX_HTTP_V2_MAX_STREAMS_SETTING: - h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx, - ngx_http_v2_module); - - h2c->concurrent_pushes = ngx_min(value, h2scf->concurrent_pushes); break; case NGX_HTTP_V2_HEADER_TABLE_SIZE_SETTING: @@ -2723,163 +2678,6 @@ ngx_http_v2_parse_int(ngx_http_v2_connec } -ngx_http_v2_stream_t * -ngx_http_v2_push_stream(ngx_http_v2_stream_t *parent, ngx_str_t *path) -{ - ngx_int_t rc; - ngx_str_t value; - ngx_pool_t *pool; - ngx_uint_t index; - ngx_table_elt_t **h; - ngx_connection_t *fc; - ngx_http_request_t *r; - ngx_http_v2_node_t *node; - ngx_http_v2_stream_t *stream; - ngx_http_v2_srv_conf_t *h2scf; - ngx_http_v2_connection_t *h2c; - ngx_http_v2_parse_header_t *header; - - h2c = parent->connection; - - pool = ngx_create_pool(1024, h2c->connection->log); - if (pool == NULL) { - goto rst_stream; - } - - node = ngx_http_v2_get_node_by_id(h2c, h2c->last_push, 1); - - if (node == NULL) { - ngx_destroy_pool(pool); - goto rst_stream; - } - - stream = ngx_http_v2_create_stream(h2c, 1); - if (stream == NULL) { - - if (node->parent == NULL) { - h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx, - ngx_http_v2_module); - - index = ngx_http_v2_index(h2scf, h2c->last_push); - h2c->streams_index[index] = node->index; - - ngx_queue_insert_tail(&h2c->closed, &node->reuse); - h2c->closed_nodes++; - } - - ngx_destroy_pool(pool); - goto rst_stream; - } - - if (node->parent) { - ngx_queue_remove(&node->reuse); - h2c->closed_nodes--; - } - - stream->pool = pool; - - r = stream->request; - fc = r->connection; - - stream->in_closed = 1; - stream->node = node; - - node->stream = stream; - - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, - "http2 push stream sid:%ui " - "depends on %ui excl:0 weight:16", - h2c->last_push, parent->node->id); - - node->weight = NGX_HTTP_V2_DEFAULT_WEIGHT; - ngx_http_v2_set_dependency(h2c, node, parent->node->id, 0); - - r->method_name = ngx_http_core_get_method; - r->method = NGX_HTTP_GET; - - r->schema.data = ngx_pstrdup(pool, &parent->request->schema); - if (r->schema.data == NULL) { - goto close; - } - - r->schema.len = parent->request->schema.len; - - value.data = ngx_pstrdup(pool, path); - if (value.data == NULL) { - goto close; - } - - value.len = path->len; - - rc = ngx_http_v2_parse_path(r, &value); - - if (rc != NGX_OK) { - goto error; - } - - for (header = ngx_http_v2_parse_headers; header->name.len; header++) { - h = (ngx_table_elt_t **) - ((char *) &parent->request->headers_in + header->offset); - - if (*h == NULL) { - continue; - } - - value.len = (*h)->value.len; - - value.data = ngx_pnalloc(pool, value.len + 1); - if (value.data == NULL) { - goto close; - } - - ngx_memcpy(value.data, (*h)->value.data, value.len); - value.data[value.len] = '\0'; - - rc = ngx_http_v2_parse_header(r, header, &value); - - if (rc != NGX_OK) { - goto error; - } - } - - fc->write->handler = ngx_http_v2_run_request_handler; - ngx_post_event(fc->write, &ngx_posted_events); - - return stream; - -error: - - if (rc == NGX_ABORT) { - /* header handler has already finalized request */ - ngx_http_run_posted_requests(fc); - return NULL; - } - - if (rc == NGX_DECLINED) { - ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); - ngx_http_run_posted_requests(fc); - return NULL; - } - -close: - - ngx_http_v2_close_stream(stream, NGX_HTTP_INTERNAL_SERVER_ERROR); - - return NULL; - -rst_stream: - - if (ngx_http_v2_send_rst_stream(h2c, h2c->last_push, - NGX_HTTP_INTERNAL_SERVER_ERROR) - != NGX_OK) - { - h2c->connection->error = 1; - } - - return NULL; -} - - static ngx_int_t ngx_http_v2_send_settings(ngx_http_v2_connection_t *h2c) { @@ -3151,7 +2949,7 @@ ngx_http_v2_frame_handler(ngx_http_v2_co static ngx_http_v2_stream_t * -ngx_http_v2_create_stream(ngx_http_v2_connection_t *h2c, ngx_uint_t push) +ngx_http_v2_create_stream(ngx_http_v2_connection_t *h2c) { ngx_log_t *log; ngx_event_t *rev, *wev; @@ -3206,13 +3004,7 @@ ngx_http_v2_create_stream(ngx_http_v2_co ngx_memcpy(log, h2c->connection->log, sizeof(ngx_log_t)); log->data = ctx; - - if (push) { - log->action = "processing pushed request headers"; - - } else { - log->action = "reading client request headers"; - } + log->action = "reading client request headers"; ngx_memzero(rev, sizeof(ngx_event_t)); @@ -3284,12 +3076,7 @@ ngx_http_v2_create_stream(ngx_http_v2_co stream->send_window = h2c->init_window; stream->recv_window = h2scf->preread_size; - if (push) { - h2c->pushing++; - - } else { - h2c->processing++; - } + h2c->processing++; h2c->priority_limit += h2scf->concurrent_streams; @@ -3712,45 +3499,41 @@ ngx_http_v2_parse_scheme(ngx_http_reques static ngx_int_t ngx_http_v2_parse_authority(ngx_http_request_t *r, ngx_str_t *value) { - return ngx_http_v2_parse_header(r, &ngx_http_v2_parse_headers[0], value); -} - - -static ngx_int_t -ngx_http_v2_parse_header(ngx_http_request_t *r, - ngx_http_v2_parse_header_t *header, ngx_str_t *value) -{ ngx_table_elt_t *h; + ngx_http_header_t *hh; ngx_http_core_main_conf_t *cmcf; + static ngx_str_t host = ngx_string("host"); + h = ngx_list_push(&r->headers_in.headers); if (h == NULL) { return NGX_ERROR; } - h->key.len = header->name.len; - h->key.data = header->name.data; - h->lowcase_key = header->name.data; - - if (header->hh == NULL) { - header->hash = ngx_hash_key(header->name.data, header->name.len); - - cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); - - header->hh = ngx_hash_find(&cmcf->headers_in_hash, header->hash, - h->lowcase_key, h->key.len); - if (header->hh == NULL) { - return NGX_ERROR; - } - } - - h->hash = header->hash; + h->hash = ngx_hash(ngx_hash(ngx_hash('h', 'o'), 's'), 't'); + + h->key.len = host.len; + h->key.data = host.data; h->value.len = value->len; h->value.data = value->data; - if (header->hh->handler(r, h, header->hh->offset) != NGX_OK) { - /* header handler has already finalized request */ + h->lowcase_key = host.data; + + cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); + + hh = ngx_hash_find(&cmcf->headers_in_hash, h->hash, + h->lowcase_key, h->key.len); + + if (hh == NULL) { + return NGX_ERROR; + } + + if (hh->handler(r, h, hh->offset) != NGX_OK) { + /* + * request has been finalized already + * in ngx_http_process_host() + */ return NGX_ABORT; } @@ -3993,22 +3776,6 @@ failed: } -static void -ngx_http_v2_run_request_handler(ngx_event_t *ev) -{ - ngx_connection_t *fc; - ngx_http_request_t *r; - - fc = ev->data; - r = fc->data; - - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0, - "http2 run request handler"); - - ngx_http_v2_run_request(r); -} - - ngx_int_t ngx_http_v2_read_request_body(ngx_http_request_t *r) { @@ -4612,7 +4379,6 @@ void ngx_http_v2_close_stream(ngx_http_v2_stream_t *stream, ngx_int_t rc) { ngx_pool_t *pool; - ngx_uint_t push; ngx_event_t *ev; ngx_connection_t *fc; ngx_http_v2_node_t *node; @@ -4621,10 +4387,9 @@ ngx_http_v2_close_stream(ngx_http_v2_str h2c = stream->connection; node = stream->node; - ngx_log_debug4(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, - "http2 close stream %ui, queued %ui, " - "processing %ui, pushing %ui", - node->id, stream->queued, h2c->processing, h2c->pushing); + ngx_log_debug3(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, + "http2 close stream %ui, queued %ui, processing %ui", + node->id, stream->queued, h2c->processing); fc = stream->request->connection; @@ -4659,8 +4424,6 @@ ngx_http_v2_close_stream(ngx_http_v2_str h2c->state.stream = NULL; } - push = stream->node->id % 2 == 0; - node->stream = NULL; ngx_queue_insert_tail(&h2c->closed, &node->reuse); @@ -4710,14 +4473,9 @@ ngx_http_v2_close_stream(ngx_http_v2_str fc->data = h2c->free_fake_connections; h2c->free_fake_connections = fc; - if (push) { - h2c->pushing--; - - } else { - h2c->processing--; - } - - if (h2c->processing || h2c->pushing || h2c->blocked) { + h2c->processing--; + + if (h2c->processing || h2c->blocked) { return; } @@ -4893,7 +4651,7 @@ ngx_http_v2_finalize_connection(ngx_http } } - if (!h2c->processing && !h2c->pushing) { + if (!h2c->processing) { goto done; } @@ -4941,7 +4699,7 @@ ngx_http_v2_finalize_connection(ngx_http h2c->blocked = 0; - if (h2c->processing || h2c->pushing) { + if (h2c->processing) { c->error = 1; return; } diff -r 0aaa09927703 -r 262c01782566 src/http/v2/ngx_http_v2.h --- a/src/http/v2/ngx_http_v2.h Thu Jun 08 14:49:27 2023 +0400 +++ b/src/http/v2/ngx_http_v2.h Thu Jun 08 16:56:46 2023 +0400 @@ -24,8 +24,6 @@ #define NGX_HTTP_V2_MAX_FIELD \ (127 + (1 << (NGX_HTTP_V2_INT_OCTETS - 1) * 7) - 1) -#define NGX_HTTP_V2_STREAM_ID_SIZE 4 - #define NGX_HTTP_V2_FRAME_HEADER_SIZE 9 /* frame types */ @@ -67,7 +65,6 @@ typedef struct { ngx_flag_t enable; size_t pool_size; ngx_uint_t concurrent_streams; - ngx_uint_t concurrent_pushes; size_t preread_size; ngx_uint_t streams_index_mask; } ngx_http_v2_srv_conf_t; @@ -136,9 +133,6 @@ struct ngx_http_v2_connection_s { ngx_uint_t idle; ngx_uint_t priority_limit; - ngx_uint_t pushing; - ngx_uint_t concurrent_pushes; - size_t send_window; size_t recv_window; size_t init_window; @@ -165,7 +159,6 @@ struct ngx_http_v2_connection_s { ngx_uint_t closed_nodes; ngx_uint_t last_sid; - ngx_uint_t last_push; time_t lingering_time; @@ -173,7 +166,6 @@ struct ngx_http_v2_connection_s { unsigned table_update:1; unsigned blocked:1; unsigned goaway:1; - unsigned push_disabled:1; }; @@ -303,9 +295,6 @@ void ngx_http_v2_init(ngx_event_t *rev); ngx_int_t ngx_http_v2_read_request_body(ngx_http_request_t *r); ngx_int_t ngx_http_v2_read_unbuffered_request_body(ngx_http_request_t *r); -ngx_http_v2_stream_t *ngx_http_v2_push_stream(ngx_http_v2_stream_t *parent, - ngx_str_t *path); - void ngx_http_v2_close_stream(ngx_http_v2_stream_t *stream, ngx_int_t rc); ngx_int_t ngx_http_v2_send_output_queue(ngx_http_v2_connection_t *h2c); @@ -407,15 +396,12 @@ ngx_int_t ngx_http_v2_table_size(ngx_htt #define NGX_HTTP_V2_STATUS_404_INDEX 13 #define NGX_HTTP_V2_STATUS_500_INDEX 14 -#define NGX_HTTP_V2_ACCEPT_ENCODING_INDEX 16 -#define NGX_HTTP_V2_ACCEPT_LANGUAGE_INDEX 17 #define NGX_HTTP_V2_CONTENT_LENGTH_INDEX 28 #define NGX_HTTP_V2_CONTENT_TYPE_INDEX 31 #define NGX_HTTP_V2_DATE_INDEX 33 #define NGX_HTTP_V2_LAST_MODIFIED_INDEX 44 #define NGX_HTTP_V2_LOCATION_INDEX 46 #define NGX_HTTP_V2_SERVER_INDEX 54 -#define NGX_HTTP_V2_USER_AGENT_INDEX 58 #define NGX_HTTP_V2_VARY_INDEX 59 #define NGX_HTTP_V2_PREFACE_START "PRI * HTTP/2.0\r\n" diff -r 0aaa09927703 -r 262c01782566 src/http/v2/ngx_http_v2_filter_module.c --- a/src/http/v2/ngx_http_v2_filter_module.c Thu Jun 08 14:49:27 2023 +0400 +++ b/src/http/v2/ngx_http_v2_filter_module.c Thu Jun 08 16:56:46 2023 +0400 @@ -27,39 +27,8 @@ #define NGX_HTTP_V2_NO_TRAILERS (ngx_http_v2_out_frame_t *) -1 -typedef struct { - ngx_str_t name; - u_char index; - ngx_uint_t offset; -} ngx_http_v2_push_header_t; - - -static ngx_http_v2_push_header_t ngx_http_v2_push_headers[] = { - { ngx_string(":authority"), NGX_HTTP_V2_AUTHORITY_INDEX, - offsetof(ngx_http_headers_in_t, host) }, - - { ngx_string("accept-encoding"), NGX_HTTP_V2_ACCEPT_ENCODING_INDEX, - offsetof(ngx_http_headers_in_t, accept_encoding) }, - - { ngx_string("accept-language"), NGX_HTTP_V2_ACCEPT_LANGUAGE_INDEX, - offsetof(ngx_http_headers_in_t, accept_language) }, - - { ngx_string("user-agent"), NGX_HTTP_V2_USER_AGENT_INDEX, - offsetof(ngx_http_headers_in_t, user_agent) }, -}; - -#define NGX_HTTP_V2_PUSH_HEADERS \ - (sizeof(ngx_http_v2_push_headers) / sizeof(ngx_http_v2_push_header_t)) - - -static ngx_int_t ngx_http_v2_push_resources(ngx_http_request_t *r); -static ngx_int_t ngx_http_v2_push_resource(ngx_http_request_t *r, - ngx_str_t *path, ngx_str_t *binary); - static ngx_http_v2_out_frame_t *ngx_http_v2_create_headers_frame( ngx_http_request_t *r, u_char *pos, u_char *end, ngx_uint_t fin); -static ngx_http_v2_out_frame_t *ngx_http_v2_create_push_frame( - ngx_http_request_t *r, u_char *pos, u_char *end); static ngx_http_v2_out_frame_t *ngx_http_v2_create_trailers_frame( ngx_http_request_t *r); @@ -82,8 +51,6 @@ static ngx_inline ngx_int_t ngx_http_v2_ static ngx_int_t ngx_http_v2_headers_frame_handler( ngx_http_v2_connection_t *h2c, ngx_http_v2_out_frame_t *frame); -static ngx_int_t ngx_http_v2_push_frame_handler( - ngx_http_v2_connection_t *h2c, ngx_http_v2_out_frame_t *frame); static ngx_int_t ngx_http_v2_data_frame_handler( ngx_http_v2_connection_t *h2c, ngx_http_v2_out_frame_t *frame); static ngx_inline void ngx_http_v2_handle_frame( @@ -244,15 +211,6 @@ ngx_http_v2_header_filter(ngx_http_reque h2c = stream->connection; - if (!h2c->push_disabled && !h2c->goaway - && stream->node->id % 2 == 1 - && r->method != NGX_HTTP_HEAD) - { - if (ngx_http_v2_push_resources(r) != NGX_OK) { - return NGX_ERROR; - } - } - len = h2c->table_update ? 1 : 0; len += status ? 1 : 1 + ngx_http_v2_literal_size("418"); @@ -653,7 +611,7 @@ ngx_http_v2_header_filter(ngx_http_reque ngx_http_v2_queue_blocked_frame(h2c, frame); - stream->queued++; + stream->queued = 1; cln = ngx_http_cleanup_add(r, 0); if (cln == NULL) { @@ -671,409 +629,6 @@ ngx_http_v2_header_filter(ngx_http_reque } -static ngx_int_t -ngx_http_v2_push_resources(ngx_http_request_t *r) -{ - u_char *start, *end, *last; - ngx_int_t rc; - ngx_str_t path; - ngx_uint_t i, push; - ngx_table_elt_t *h; - ngx_http_v2_loc_conf_t *h2lcf; - ngx_http_complex_value_t *pushes; - ngx_str_t binary[NGX_HTTP_V2_PUSH_HEADERS]; - - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http2 push resources"); - - ngx_memzero(binary, NGX_HTTP_V2_PUSH_HEADERS * sizeof(ngx_str_t)); - - h2lcf = ngx_http_get_module_loc_conf(r, ngx_http_v2_module); - - if (h2lcf->pushes) { - pushes = h2lcf->pushes->elts; - - for (i = 0; i < h2lcf->pushes->nelts; i++) { - - if (ngx_http_complex_value(r, &pushes[i], &path) != NGX_OK) { - return NGX_ERROR; - } - - if (path.len == 0) { - continue; - } - - if (path.len == 3 && ngx_strncmp(path.data, "off", 3) == 0) { - continue; - } - - rc = ngx_http_v2_push_resource(r, &path, binary); - - if (rc == NGX_ERROR) { - return NGX_ERROR; - } - - if (rc == NGX_ABORT) { - return NGX_OK; - } - - /* NGX_OK, NGX_DECLINED */ - } - } - - if (!h2lcf->push_preload) { - return NGX_OK; - } - - for (h = r->headers_out.link; h; h = h->next) { - - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http2 parse link: \"%V\"", &h->value); - - start = h->value.data; - end = h->value.data + h->value.len; - - next_link: - - while (start < end && *start == ' ') { start++; } - - if (start == end || *start++ != '<') { - continue; - } - - while (start < end && *start == ' ') { start++; } - - for (last = start; last < end && *last != '>'; last++) { - /* void */ - } - - if (last == start || last == end) { - continue; - } - - path.len = last - start; - path.data = start; - - start = last + 1; - - while (start < end && *start == ' ') { start++; } - - if (start == end) { - continue; - } - - if (*start == ',') { - start++; - goto next_link; - } - - if (*start++ != ';') { - continue; - } - - last = ngx_strlchr(start, end, ','); - - if (last == NULL) { - last = end; - } - - push = 0; - - for ( ;; ) { - - while (start < last && *start == ' ') { start++; } - - if (last - start >= 6 - && ngx_strncasecmp(start, (u_char *) "nopush", 6) == 0) - { - start += 6; - - if (start == last || *start == ' ' || *start == ';') { - push = 0; - break; - } - - goto next_param; - } - - if (last - start >= 11 - && ngx_strncasecmp(start, (u_char *) "rel=preload", 11) == 0) - { - start += 11; - - if (start == last || *start == ' ' || *start == ';') { - push = 1; - } - - goto next_param; - } - - if (last - start >= 4 - && ngx_strncasecmp(start, (u_char *) "rel=", 4) == 0) - { - start += 4; - - while (start < last && *start == ' ') { start++; } - - if (start == last || *start++ != '"') { - goto next_param; - } - - for ( ;; ) { - - while (start < last && *start == ' ') { start++; } - - if (last - start >= 7 - && ngx_strncasecmp(start, (u_char *) "preload", 7) == 0) - { - start += 7; - - if (start < last && (*start == ' ' || *start == '"')) { - push = 1; - break; - } - } - - while (start < last && *start != ' ' && *start != '"') { - start++; - } - - if (start == last) { - break; - } - - if (*start == '"') { - break; - } - - start++; - } - } - - next_param: - - start = ngx_strlchr(start, last, ';'); - - if (start == NULL) { - break; - } - - start++; - } - - if (push) { - while (path.len && path.data[path.len - 1] == ' ') { - path.len--; - } - } - - if (push && path.len - && !(path.len > 1 && path.data[0] == '/' && path.data[1] == '/')) - { - rc = ngx_http_v2_push_resource(r, &path, binary); - - if (rc == NGX_ERROR) { - return NGX_ERROR; - } - - if (rc == NGX_ABORT) { - return NGX_OK; - } - - /* NGX_OK, NGX_DECLINED */ - } - - if (last < end) { - start = last + 1; - goto next_link; - } - } - - return NGX_OK; -} - - -static ngx_int_t -ngx_http_v2_push_resource(ngx_http_request_t *r, ngx_str_t *path, - ngx_str_t *binary) -{ - u_char *start, *pos, *tmp; - size_t len; - ngx_str_t *value; - ngx_uint_t i; - ngx_table_elt_t **h; - ngx_connection_t *fc; - ngx_http_v2_stream_t *stream; - ngx_http_v2_out_frame_t *frame; - ngx_http_v2_connection_t *h2c; - ngx_http_v2_push_header_t *ph; - - fc = r->connection; - - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0, "http2 push resource"); - - stream = r->stream; - h2c = stream->connection; - - if (!ngx_path_separator(path->data[0])) { - ngx_log_error(NGX_LOG_WARN, fc->log, 0, - "non-absolute path \"%V\" not pushed", path); - return NGX_DECLINED; - } - - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, - "http2 pushing:%ui limit:%ui", - h2c->pushing, h2c->concurrent_pushes); - - if (h2c->pushing >= h2c->concurrent_pushes) { - return NGX_ABORT; - } - - if (h2c->last_push == 0x7ffffffe) { - return NGX_ABORT; - } - - if (path->len > NGX_HTTP_V2_MAX_FIELD) { - return NGX_DECLINED; - } - - if (r->headers_in.host == NULL) { - return NGX_ABORT; - } - - ph = ngx_http_v2_push_headers; - - len = ngx_max(r->schema.len, path->len); - - if (binary[0].len) { - tmp = ngx_palloc(r->pool, len); - if (tmp == NULL) { - return NGX_ERROR; - } - - } else { - for (i = 0; i < NGX_HTTP_V2_PUSH_HEADERS; i++) { - h = (ngx_table_elt_t **) ((char *) &r->headers_in + ph[i].offset); - - if (*h) { - len = ngx_max(len, (*h)->value.len); - } - } - - tmp = ngx_palloc(r->pool, len); - if (tmp == NULL) { - return NGX_ERROR; - } - - for (i = 0; i < NGX_HTTP_V2_PUSH_HEADERS; i++) { - h = (ngx_table_elt_t **) ((char *) &r->headers_in + ph[i].offset); - - if (*h == NULL) { - continue; - } - - value = &(*h)->value; - - len = 1 + NGX_HTTP_V2_INT_OCTETS + value->len; - - pos = ngx_pnalloc(r->pool, len); - if (pos == NULL) { - return NGX_ERROR; - } - - binary[i].data = pos; - - *pos++ = ngx_http_v2_inc_indexed(ph[i].index); - pos = ngx_http_v2_write_value(pos, value->data, value->len, tmp); - - binary[i].len = pos - binary[i].data; - } - } - - len = (h2c->table_update ? 1 : 0) From arut at nginx.com Fri Jun 9 07:12:51 2023 From: arut at nginx.com (=?iso-8859-1?q?Roman_Arutyunyan?=) Date: Fri, 09 Jun 2023 11:12:51 +0400 Subject: [PATCH 0 of 3] QUIC ciphers cleanup and CCM support Message-ID: Patches 1 & 2 do minor cleanup in encryption code. Patch 3 adds TLS_AES_128_CCM_SHA256 support to QUIC, which currently is the only cipher suite not supported by nginx QUIC implementation. It's disabled by default in OpenSSL and can be enabled by the following directive: ssl_conf_command Ciphersuites TLS_AES_128_CCM_SHA256; From arut at nginx.com Fri Jun 9 07:12:52 2023 From: arut at nginx.com (=?iso-8859-1?q?Roman_Arutyunyan?=) Date: Fri, 09 Jun 2023 11:12:52 +0400 Subject: [PATCH 1 of 3] QUIC: a new constant for AEAD tag length In-Reply-To: References: Message-ID: <1a9d3535b6bff6855132.1686294772@arut-laptop> # HG changeset patch # User Roman Arutyunyan # Date 1686291954 -14400 # Fri Jun 09 10:25:54 2023 +0400 # Node ID 1a9d3535b6bff6855132b2685d1ca8d6b7a3af6b # Parent 262c0178256623c59a54bea81fcf3f92d12d75b6 QUIC: a new constant for AEAD tag length. Previously used constant EVP_GCM_TLS_TAG_LEN had misleading name since it was used not only with GCM, but also with CHACHAPOLY. Now a new constant NGX_QUIC_TAG_LEN introduced. Luckily all AEAD algorithms used by QUIC have the same tag length of 16. diff --git a/src/event/quic/ngx_event_quic_openssl_compat.c b/src/event/quic/ngx_event_quic_openssl_compat.c --- a/src/event/quic/ngx_event_quic_openssl_compat.c +++ b/src/event/quic/ngx_event_quic_openssl_compat.c @@ -445,7 +445,7 @@ SSL_provide_quic_data(SSL *ssl, enum ssl u_char in[NGX_QUIC_COMPAT_RECORD_SIZE + 1]; u_char out[NGX_QUIC_COMPAT_RECORD_SIZE + 1 + SSL3_RT_HEADER_LENGTH - + EVP_GCM_TLS_TAG_LEN]; + + NGX_QUIC_TAG_LEN]; c = ngx_ssl_get_connection(ssl); @@ -528,7 +528,7 @@ ngx_quic_compat_create_header(ngx_quic_c } else { type = SSL3_RT_APPLICATION_DATA; - len += EVP_GCM_TLS_TAG_LEN; + len += NGX_QUIC_TAG_LEN; } out[0] = type; @@ -552,7 +552,7 @@ ngx_quic_compat_create_record(ngx_quic_c ad.data = res->data; ad.len = ngx_quic_compat_create_header(rec, ad.data, 0); - out.len = rec->payload.len + EVP_GCM_TLS_TAG_LEN; + out.len = rec->payload.len + NGX_QUIC_TAG_LEN; out.data = res->data + ad.len; #ifdef NGX_QUIC_DEBUG_CRYPTO diff --git a/src/event/quic/ngx_event_quic_protection.c b/src/event/quic/ngx_event_quic_protection.c --- a/src/event/quic/ngx_event_quic_protection.c +++ b/src/event/quic/ngx_event_quic_protection.c @@ -406,7 +406,7 @@ ngx_quic_tls_open(const ngx_quic_cipher_ } if (EVP_DecryptUpdate(ctx, out->data, &len, in->data, - in->len - EVP_GCM_TLS_TAG_LEN) + in->len - NGX_QUIC_TAG_LEN) != 1) { EVP_CIPHER_CTX_free(ctx); @@ -415,9 +415,9 @@ ngx_quic_tls_open(const ngx_quic_cipher_ } out->len = len; - tag = in->data + in->len - EVP_GCM_TLS_TAG_LEN; + tag = in->data + in->len - NGX_QUIC_TAG_LEN; - if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, EVP_GCM_TLS_TAG_LEN, tag) + if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, NGX_QUIC_TAG_LEN, tag) == 0) { EVP_CIPHER_CTX_free(ctx); @@ -519,7 +519,7 @@ ngx_quic_tls_seal(const ngx_quic_cipher_ out->len += len; - if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, EVP_GCM_TLS_TAG_LEN, + if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, NGX_QUIC_TAG_LEN, out->data + in->len) == 0) { @@ -531,7 +531,7 @@ ngx_quic_tls_seal(const ngx_quic_cipher_ EVP_CIPHER_CTX_free(ctx); - out->len += EVP_GCM_TLS_TAG_LEN; + out->len += NGX_QUIC_TAG_LEN; #endif return NGX_OK; } @@ -738,7 +738,7 @@ ngx_quic_create_packet(ngx_quic_header_t ad.data = res->data; ad.len = ngx_quic_create_header(pkt, ad.data, &pnp); - out.len = pkt->payload.len + EVP_GCM_TLS_TAG_LEN; + out.len = pkt->payload.len + NGX_QUIC_TAG_LEN; out.data = res->data + ad.len; #ifdef NGX_QUIC_DEBUG_CRYPTO @@ -802,7 +802,7 @@ ngx_quic_create_retry_packet(ngx_quic_he ad.len = ngx_quic_create_retry_itag(pkt, ad.data, &start); itag.data = ad.data + ad.len; - itag.len = EVP_GCM_TLS_TAG_LEN; + itag.len = NGX_QUIC_TAG_LEN; #ifdef NGX_QUIC_DEBUG_CRYPTO ngx_log_debug2(NGX_LOG_DEBUG_EVENT, pkt->log, 0, @@ -979,7 +979,7 @@ ngx_quic_decrypt(ngx_quic_header_t *pkt, * AES and ChaCha20 algorithms sample 16 bytes */ - if (len < EVP_GCM_TLS_TAG_LEN + 4) { + if (len < NGX_QUIC_TAG_LEN + 4) { return NGX_DECLINED; } @@ -1039,7 +1039,7 @@ ngx_quic_decrypt(ngx_quic_header_t *pkt, "quic ad len:%uz %xV", ad.len, &ad); #endif - pkt->payload.len = in.len - EVP_GCM_TLS_TAG_LEN; + pkt->payload.len = in.len - NGX_QUIC_TAG_LEN; pkt->payload.data = pkt->plaintext + ad.len; rc = ngx_quic_tls_open(ciphers.c, secret, &pkt->payload, diff --git a/src/event/quic/ngx_event_quic_protection.h b/src/event/quic/ngx_event_quic_protection.h --- a/src/event/quic/ngx_event_quic_protection.h +++ b/src/event/quic/ngx_event_quic_protection.h @@ -16,8 +16,9 @@ #define NGX_QUIC_ENCRYPTION_LAST ((ssl_encryption_application) + 1) -/* RFC 5116, 5.1 and RFC 8439, 2.3 for all supported ciphers */ +/* RFC 5116, 5.1 and RFC 8439, 2.3/2.5 for all supported ciphers */ #define NGX_QUIC_IV_LEN 12 +#define NGX_QUIC_TAG_LEN 16 /* largest hash used in TLS is SHA-384 */ #define NGX_QUIC_MAX_MD_SIZE 48 diff --git a/src/event/quic/ngx_event_quic_transport.c b/src/event/quic/ngx_event_quic_transport.c --- a/src/event/quic/ngx_event_quic_transport.c +++ b/src/event/quic/ngx_event_quic_transport.c @@ -578,7 +578,7 @@ ngx_quic_payload_size(ngx_quic_header_t if (ngx_quic_short_pkt(pkt->flags)) { - len = 1 + pkt->dcid.len + pkt->num_len + EVP_GCM_TLS_TAG_LEN; + len = 1 + pkt->dcid.len + pkt->num_len + NGX_QUIC_TAG_LEN; if (len > pkt_len) { return 0; } @@ -596,7 +596,7 @@ ngx_quic_payload_size(ngx_quic_header_t /* (pkt_len - len) is 'remainder' packet length (see RFC 9000, 17.2) */ len += ngx_quic_varint_len(pkt_len - len) - + pkt->num_len + EVP_GCM_TLS_TAG_LEN; + + pkt->num_len + NGX_QUIC_TAG_LEN; if (len > pkt_len) { return 0; @@ -622,7 +622,7 @@ ngx_quic_create_long_header(ngx_quic_hea size_t rem_len; u_char *p, *start; - rem_len = pkt->num_len + pkt->payload.len + EVP_GCM_TLS_TAG_LEN; + rem_len = pkt->num_len + pkt->payload.len + NGX_QUIC_TAG_LEN; if (out == NULL) { return 5 + 2 + pkt->dcid.len + pkt->scid.len From arut at nginx.com Fri Jun 9 07:12:53 2023 From: arut at nginx.com (=?iso-8859-1?q?Roman_Arutyunyan?=) Date: Fri, 09 Jun 2023 11:12:53 +0400 Subject: [PATCH 2 of 3] QUIC: common cipher control constants instead of GCM-related In-Reply-To: References: Message-ID: <74fa16d2a34a63a83fa7.1686294773@arut-laptop> # HG changeset patch # User Roman Arutyunyan # Date 1686291802 -14400 # Fri Jun 09 10:23:22 2023 +0400 # Node ID 74fa16d2a34a63a83fa76b46a56d8d68d44fa1bf # Parent 1a9d3535b6bff6855132b2685d1ca8d6b7a3af6b QUIC: common cipher control constants instead of GCM-related. The constants are used for both GCM and CHACHAPOLY. diff --git a/src/event/quic/ngx_event_quic_protection.c b/src/event/quic/ngx_event_quic_protection.c --- a/src/event/quic/ngx_event_quic_protection.c +++ b/src/event/quic/ngx_event_quic_protection.c @@ -384,12 +384,12 @@ ngx_quic_tls_open(const ngx_quic_cipher_ return NGX_ERROR; } - if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, s->iv.len, NULL) + if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, s->iv.len, NULL) == 0) { EVP_CIPHER_CTX_free(ctx); ngx_ssl_error(NGX_LOG_INFO, log, 0, - "EVP_CIPHER_CTX_ctrl(EVP_CTRL_GCM_SET_IVLEN) failed"); + "EVP_CIPHER_CTX_ctrl(EVP_CTRL_AEAD_SET_IVLEN) failed"); return NGX_ERROR; } @@ -417,12 +417,12 @@ ngx_quic_tls_open(const ngx_quic_cipher_ out->len = len; tag = in->data + in->len - NGX_QUIC_TAG_LEN; - if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, NGX_QUIC_TAG_LEN, tag) + if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, NGX_QUIC_TAG_LEN, tag) == 0) { EVP_CIPHER_CTX_free(ctx); ngx_ssl_error(NGX_LOG_INFO, log, 0, - "EVP_CIPHER_CTX_ctrl(EVP_CTRL_GCM_SET_TAG) failed"); + "EVP_CIPHER_CTX_ctrl(EVP_CTRL_AEAD_SET_TAG) failed"); return NGX_ERROR; } @@ -482,12 +482,12 @@ ngx_quic_tls_seal(const ngx_quic_cipher_ return NGX_ERROR; } - if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, s->iv.len, NULL) + if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, s->iv.len, NULL) == 0) { EVP_CIPHER_CTX_free(ctx); ngx_ssl_error(NGX_LOG_INFO, log, 0, - "EVP_CIPHER_CTX_ctrl(EVP_CTRL_GCM_SET_IVLEN) failed"); + "EVP_CIPHER_CTX_ctrl(EVP_CTRL_AEAD_SET_IVLEN) failed"); return NGX_ERROR; } @@ -519,13 +519,13 @@ ngx_quic_tls_seal(const ngx_quic_cipher_ out->len += len; - if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, NGX_QUIC_TAG_LEN, + if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, NGX_QUIC_TAG_LEN, out->data + in->len) == 0) { EVP_CIPHER_CTX_free(ctx); ngx_ssl_error(NGX_LOG_INFO, log, 0, - "EVP_CIPHER_CTX_ctrl(EVP_CTRL_GCM_GET_TAG) failed"); + "EVP_CIPHER_CTX_ctrl(EVP_CTRL_AEAD_GET_TAG) failed"); return NGX_ERROR; } From arut at nginx.com Fri Jun 9 07:12:54 2023 From: arut at nginx.com (=?iso-8859-1?q?Roman_Arutyunyan?=) Date: Fri, 09 Jun 2023 11:12:54 +0400 Subject: [PATCH 3 of 3] QUIC: TLS_AES_128_CCM_SHA256 cipher suite support In-Reply-To: References: Message-ID: <91c420191eaa6b8d8bd3.1686294774@arut-laptop> # HG changeset patch # User Roman Arutyunyan # Date 1686292815 -14400 # Fri Jun 09 10:40:15 2023 +0400 # Node ID 91c420191eaa6b8d8bd3dc1447d5e0880f41108f # Parent 74fa16d2a34a63a83fa76b46a56d8d68d44fa1bf QUIC: TLS_AES_128_CCM_SHA256 cipher suite support. diff --git a/src/event/quic/ngx_event_quic_protection.c b/src/event/quic/ngx_event_quic_protection.c --- a/src/event/quic/ngx_event_quic_protection.c +++ b/src/event/quic/ngx_event_quic_protection.c @@ -94,6 +94,15 @@ ngx_quic_ciphers(ngx_uint_t id, ngx_quic len = 32; break; +#ifndef OPENSSL_IS_BORINGSSL + case TLS1_3_CK_AES_128_CCM_SHA256: + ciphers->c = EVP_aes_128_ccm(); + ciphers->hp = EVP_aes_128_ctr(); + ciphers->d = EVP_sha256(); + len = 16; + break; +#endif + default: return NGX_ERROR; } @@ -393,18 +402,49 @@ ngx_quic_tls_open(const ngx_quic_cipher_ return NGX_ERROR; } + if (EVP_CIPHER_mode(cipher) == EVP_CIPH_CCM_MODE + && EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, NGX_QUIC_TAG_LEN, + NULL) + == 0) + { + EVP_CIPHER_CTX_free(ctx); + ngx_ssl_error(NGX_LOG_INFO, log, 0, + "EVP_CIPHER_CTX_ctrl(EVP_CTRL_AEAD_SET_TAG) failed"); + return NGX_ERROR; + } + if (EVP_DecryptInit_ex(ctx, NULL, NULL, s->key.data, nonce) != 1) { EVP_CIPHER_CTX_free(ctx); ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_DecryptInit_ex() failed"); return NGX_ERROR; } + if (EVP_CIPHER_mode(cipher) == EVP_CIPH_CCM_MODE + && EVP_DecryptUpdate(ctx, NULL, &len, NULL, in->len - NGX_QUIC_TAG_LEN) + != 1) + { + EVP_CIPHER_CTX_free(ctx); + ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_DecryptUpdate() failed"); + return NGX_ERROR; + } + if (EVP_DecryptUpdate(ctx, NULL, &len, ad->data, ad->len) != 1) { EVP_CIPHER_CTX_free(ctx); ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_DecryptUpdate() failed"); return NGX_ERROR; } + tag = in->data + in->len - NGX_QUIC_TAG_LEN; + + if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, NGX_QUIC_TAG_LEN, tag) + == 0) + { + EVP_CIPHER_CTX_free(ctx); + ngx_ssl_error(NGX_LOG_INFO, log, 0, + "EVP_CIPHER_CTX_ctrl(EVP_CTRL_AEAD_SET_TAG) failed"); + return NGX_ERROR; + } + if (EVP_DecryptUpdate(ctx, out->data, &len, in->data, in->len - NGX_QUIC_TAG_LEN) != 1) @@ -415,16 +455,6 @@ ngx_quic_tls_open(const ngx_quic_cipher_ } out->len = len; - tag = in->data + in->len - NGX_QUIC_TAG_LEN; - - if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, NGX_QUIC_TAG_LEN, tag) - == 0) - { - EVP_CIPHER_CTX_free(ctx); - ngx_ssl_error(NGX_LOG_INFO, log, 0, - "EVP_CIPHER_CTX_ctrl(EVP_CTRL_AEAD_SET_TAG) failed"); - return NGX_ERROR; - } if (EVP_DecryptFinal_ex(ctx, out->data + len, &len) <= 0) { EVP_CIPHER_CTX_free(ctx); @@ -491,12 +521,31 @@ ngx_quic_tls_seal(const ngx_quic_cipher_ return NGX_ERROR; } + if (EVP_CIPHER_mode(cipher) == EVP_CIPH_CCM_MODE + && EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, NGX_QUIC_TAG_LEN, + NULL) + == 0) + { + EVP_CIPHER_CTX_free(ctx); + ngx_ssl_error(NGX_LOG_INFO, log, 0, + "EVP_CIPHER_CTX_ctrl(EVP_CTRL_AEAD_SET_TAG) failed"); + return NGX_ERROR; + } + if (EVP_EncryptInit_ex(ctx, NULL, NULL, s->key.data, nonce) != 1) { EVP_CIPHER_CTX_free(ctx); ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_EncryptInit_ex() failed"); return NGX_ERROR; } + if (EVP_CIPHER_mode(cipher) == EVP_CIPH_CCM_MODE + && EVP_EncryptUpdate(ctx, NULL, &len, NULL, in->len) != 1) + { + EVP_CIPHER_CTX_free(ctx); + ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_EncryptUpdate() failed"); + return NGX_ERROR; + } + if (EVP_EncryptUpdate(ctx, NULL, &len, ad->data, ad->len) != 1) { EVP_CIPHER_CTX_free(ctx); ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_EncryptUpdate() failed"); diff --git a/src/event/quic/ngx_event_quic_protection.h b/src/event/quic/ngx_event_quic_protection.h --- a/src/event/quic/ngx_event_quic_protection.h +++ b/src/event/quic/ngx_event_quic_protection.h @@ -16,7 +16,7 @@ #define NGX_QUIC_ENCRYPTION_LAST ((ssl_encryption_application) + 1) -/* RFC 5116, 5.1 and RFC 8439, 2.3/2.5 for all supported ciphers */ +/* RFC 5116, 5.1/5.3 and RFC 8439, 2.3/2.5 for all supported ciphers */ #define NGX_QUIC_IV_LEN 12 #define NGX_QUIC_TAG_LEN 16 From thresh at nginx.com Fri Jun 9 21:38:34 2023 From: thresh at nginx.com (=?iso-8859-1?q?Konstantin_Pavlov?=) Date: Fri, 09 Jun 2023 14:38:34 -0700 Subject: [PATCH] Linux packages: added Debian 12 "bookworm" Message-ID: <2fa6471cd138071038f0.1686346714@QGCD7XG9R9> # HG changeset patch # User Konstantin Pavlov # Date 1686346579 25200 # Fri Jun 09 14:36:19 2023 -0700 # Node ID 2fa6471cd138071038f055031a7a379a7e9ab108 # Parent b81a26d7aa2a0b0870c11ce13415a1a21fc12c5d Linux packages: added Debian 12 "bookworm". diff -r b81a26d7aa2a -r 2fa6471cd138 xml/en/linux_packages.xml --- a/xml/en/linux_packages.xml Wed Jun 07 14:21:31 2023 +0400 +++ b/xml/en/linux_packages.xml Fri Jun 09 14:36:19 2023 -0700 @@ -7,7 +7,7 @@
+ rev="88">
@@ -59,6 +59,11 @@ versions: x86_64, aarch64/arm64 + +12.x “bookworm” +x86_64, aarch64/arm64 + + diff -r b81a26d7aa2a -r 2fa6471cd138 xml/ru/linux_packages.xml --- a/xml/ru/linux_packages.xml Wed Jun 07 14:21:31 2023 +0400 +++ b/xml/ru/linux_packages.xml Fri Jun 09 14:36:19 2023 -0700 @@ -7,7 +7,7 @@
+ rev="88">
@@ -59,6 +59,11 @@ x86_64, aarch64/arm64 + +12.x “bookworm” +x86_64, aarch64/arm64 + + From maxim at nginx.com Fri Jun 9 21:50:18 2023 From: maxim at nginx.com (Maxim Konovalov) Date: Fri, 9 Jun 2023 14:50:18 -0700 Subject: [PATCH] Linux packages: added Debian 12 "bookworm" In-Reply-To: <2fa6471cd138071038f0.1686346714@QGCD7XG9R9> References: <2fa6471cd138071038f0.1686346714@QGCD7XG9R9> Message-ID: On 09.06.2023 14:38, Konstantin Pavlov wrote: > # HG changeset patch > # User Konstantin Pavlov > # Date 1686346579 25200 > # Fri Jun 09 14:36:19 2023 -0700 > # Node ID 2fa6471cd138071038f055031a7a379a7e9ab108 > # Parent b81a26d7aa2a0b0870c11ce13415a1a21fc12c5d > Linux packages: added Debian 12 "bookworm". > [...] Looks good. -- Maxim Konovalov From pluknet at nginx.com Mon Jun 12 19:39:20 2023 From: pluknet at nginx.com (=?iso-8859-1?q?Sergey_Kandaurov?=) Date: Mon, 12 Jun 2023 23:39:20 +0400 Subject: [PATCH] QUIC: fixed rttvar on subsequent RTT samples (ticket #2505) Message-ID: # HG changeset patch # User Sergey Kandaurov # Date 1686598736 -14400 # Mon Jun 12 23:38:56 2023 +0400 # Node ID a32905d6fc108962a73b4affdb38eba5cc6fd549 # Parent 262c0178256623c59a54bea81fcf3f92d12d75b6 QUIC: fixed rttvar on subsequent RTT samples (ticket #2505). Previously, computing rttvar used an updated smoothed_rtt value as per RFC 9002, section 5.3, which appears to be specified in a wrong order. A technical errata ID 7539 is reported. diff --git a/src/event/quic/ngx_event_quic_ack.c b/src/event/quic/ngx_event_quic_ack.c --- a/src/event/quic/ngx_event_quic_ack.c +++ b/src/event/quic/ngx_event_quic_ack.c @@ -207,9 +207,9 @@ ngx_quic_rtt_sample(ngx_connection_t *c, adjusted_rtt -= ack_delay; } - qc->avg_rtt += (adjusted_rtt >> 3) - (qc->avg_rtt >> 3); rttvar_sample = ngx_abs((ngx_msec_int_t) (qc->avg_rtt - adjusted_rtt)); qc->rttvar += (rttvar_sample >> 2) - (qc->rttvar >> 2); + qc->avg_rtt += (adjusted_rtt >> 3) - (qc->avg_rtt >> 3); } ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0, From xeioex at nginx.com Tue Jun 13 05:05:13 2023 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 13 Jun 2023 05:05:13 +0000 Subject: [njs] Fixed Date.parse() with ISO-8601 date-only forms. Message-ID: details: https://hg.nginx.org/njs/rev/803a5061b362 branches: changeset: 2153:803a5061b362 user: Dmitry Volyntsev date: Mon Jun 12 20:51:54 2023 -0700 description: Fixed Date.parse() with ISO-8601 date-only forms. According to the spec when the UTC offset representation is absent, date-only forms are interpreted as a UTC time and date-time forms are interpreted as a local time. diffstat: src/njs_date.c | 7 ++++--- src/test/njs_unit_test.c | 7 +++++++ 2 files changed, 11 insertions(+), 3 deletions(-) diffs (55 lines): diff -r fa51408510ad -r 803a5061b362 src/njs_date.c --- a/src/njs_date.c Tue Jun 06 21:33:46 2023 -0700 +++ b/src/njs_date.c Mon Jun 12 20:51:54 2023 -0700 @@ -530,6 +530,8 @@ njs_date_string_parse(njs_value_t *date) next = njs_date_number_parse(&tm[NJS_DATE_YR], p, end, 4); if (next != NULL) { + utc = 1; + /* ISO-8601 format: "1970-09-28T06:00:00.000Z" */ if (next == end) { @@ -592,7 +594,6 @@ njs_date_string_parse(njs_value_t *date) return NAN; } - utc = 1; end--; if (*end != 'Z') { @@ -636,6 +637,8 @@ njs_date_string_parse(njs_value_t *date) tm[NJS_DATE_MSEC] *= 10; } +done: + return njs_make_date(tm, !utc); } @@ -683,8 +686,6 @@ njs_date_string_parse(njs_value_t *date) week = 0; } -done: - return njs_make_date(tm, 0); } diff -r fa51408510ad -r 803a5061b362 src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Tue Jun 06 21:33:46 2023 -0700 +++ b/src/test/njs_unit_test.c Mon Jun 12 20:51:54 2023 -0700 @@ -16178,6 +16178,13 @@ static njs_unit_test_t njs_test[] = { njs_str("Date.parse('2011-06-24T06:01:02.625555Z5')"), njs_str("NaN") }, + { njs_str("var tzoffzet = new Date(0).getTimezoneOffset() * 60000;" + "Date.parse('1970-01-01T00:00:00') == tzoffzet"), + njs_str("true") }, + + { njs_str("Date.parse('1970-01-01')"), + njs_str("0") }, + { njs_str("var d = new Date(); var str = d.toISOString();" "var diff = Date.parse(str) - Date.parse(str.substring(0, str.length - 1));" "d.getTimezoneOffset() == -diff/1000/60"), From xeioex at nginx.com Tue Jun 13 05:05:15 2023 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Tue, 13 Jun 2023 05:05:15 +0000 Subject: [njs] Fixed Date.parse() with ISO-8601 format and UTC time offset. Message-ID: details: https://hg.nginx.org/njs/rev/ed4ff34dfc63 branches: changeset: 2154:ed4ff34dfc63 user: Dmitry Volyntsev date: Mon Jun 12 22:04:04 2023 -0700 description: Fixed Date.parse() with ISO-8601 format and UTC time offset. diffstat: src/njs_date.c | 65 +++++++++++++++++++++++++++++++++++++++-------- src/test/njs_unit_test.c | 48 +++++++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+), 11 deletions(-) diffs (162 lines): diff -r 803a5061b362 -r ed4ff34dfc63 src/njs_date.c --- a/src/njs_date.c Mon Jun 12 20:51:54 2023 -0700 +++ b/src/njs_date.c Mon Jun 12 22:04:04 2023 -0700 @@ -493,11 +493,44 @@ njs_date_parse(njs_vm_t *vm, njs_value_t } +static int64_t +njs_date_utc_offset_parse(const u_char *start, const u_char *end) +{ + int64_t utc_off, hour, min; + const u_char *p; + + if (njs_fast_path(start + 2 < end && (*start == '+' || *start == '-'))) { + p = njs_date_number_parse(&hour, start + 1, end, 2); + if (njs_slow_path(p == NULL || hour > 23)) { + return -1; + } + + if (p < end && *p == ':') { + p++; + } + + p = njs_date_number_parse(&min, p, end, 2); + if (njs_slow_path(p == NULL || min > 59)) { + return -1; + } + + utc_off = hour * 60 + min; + + if (*start == '-') { + utc_off = -utc_off; + } + + return utc_off; + } + + return -1; +} + static double njs_date_string_parse(njs_value_t *date) { size_t ms_length; - int64_t ext, skipped; + int64_t ext, utc_off; njs_str_t string; njs_bool_t sign, week, utc; const u_char *p, *next, *end; @@ -616,25 +649,37 @@ njs_date_string_parse(njs_value_t *date) p++; - ms_length = (end - p < 3) ? end - p : 3; + for (ms_length = 0; p + ms_length < end; ms_length++) { + if (p[ms_length] < '0' || p[ms_length] > '9') { + break; + } + } p = njs_date_number_parse(&tm[NJS_DATE_MSEC], p, end, ms_length); if (njs_slow_path(p == NULL)) { return NAN; } - if (end > p) { - p = njs_date_number_parse(&skipped, p, end, end - p); - if (njs_slow_path(p == NULL)) { - return NAN; - } - } - if (ms_length == 1) { tm[NJS_DATE_MSEC] *= 100; } else if (ms_length == 2) { tm[NJS_DATE_MSEC] *= 10; + + } else if (ms_length >= 4) { + for (ms_length -= 3; ms_length > 0; ms_length--) { + tm[NJS_DATE_MSEC] /= 10; + } + } + + if (p < end) { + utc_off = njs_date_utc_offset_parse(p, end); + if (njs_slow_path(utc_off == -1)) { + return NAN; + } + + utc = 1; + tm[NJS_DATE_MSEC] += -utc_off * 60000; } done: @@ -685,8 +730,6 @@ done: week = 0; } - - return njs_make_date(tm, 0); } diff -r 803a5061b362 -r ed4ff34dfc63 src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Mon Jun 12 20:51:54 2023 -0700 +++ b/src/test/njs_unit_test.c Mon Jun 12 22:04:04 2023 -0700 @@ -16172,6 +16172,54 @@ static njs_unit_test_t njs_test[] = { njs_str("Date.parse('2011-06-24T06:01:02.625Z')"), njs_str("1308895262625") }, + { njs_str("Date.parse('2011-06-24T06:01:02.625+00:00')"), + njs_str("1308895262625") }, + + { njs_str("Date.parse('2011-06-24T06:01:02.625+0000')"), + njs_str("1308895262625") }, + + { njs_str("Date.parse('2011-06-24T06:01:02.625+00:0')"), + njs_str("NaN") }, + + { njs_str("Date.parse('2011-06-24T06:01:02.625+00:')"), + njs_str("NaN") }, + + { njs_str("Date.parse('2011-06-24T06:01:02.625+00')"), + njs_str("NaN") }, + + { njs_str("Date.parse('2011-06-24T06:01:02.625+0')"), + njs_str("NaN") }, + + { njs_str("Date.parse('2011-06-24T06:01:02.625+')"), + njs_str("NaN") }, + + { njs_str("Date.parse('2011-06-24T06:01:02.625-01:15')"), + njs_str("1308899762625") }, + + { njs_str("Date.parse('2011-06-24T06:01:02.625-01:60')"), + njs_str("NaN") }, + + { njs_str("Date.parse('2011-06-24T06:01:02.625-25:59')"), + njs_str("NaN") }, + + { njs_str("Date.parse('2011-06-24T06:01:02.625+01:15')"), + njs_str("1308890762625") }, + + { njs_str("Date.parse('2011-06-24T06:01:02.625-23:59')"), + njs_str("1308981602625") }, + + { njs_str("Date.parse('2011-06-24T06:01:02.625+23:59')"), + njs_str("1308808922625") }, + + { njs_str("Date.parse('2011-06-24T06:01:02.6255Z')"), + njs_str("1308895262625") }, + + { njs_str("Date.parse('2011-06-24T06:01:02.62555Z')"), + njs_str("1308895262625") }, + + { njs_str("Date.parse('2011-06-24T06:01:02.625555Z')"), + njs_str("1308895262625") }, + { njs_str("Date.parse('2011-06-24T06:01:02.6255555Z')"), njs_str("1308895262625") }, From arut at nginx.com Tue Jun 13 06:14:29 2023 From: arut at nginx.com (Roman Arutyunyan) Date: Tue, 13 Jun 2023 10:14:29 +0400 Subject: [PATCH] QUIC: fixed rttvar on subsequent RTT samples (ticket #2505) In-Reply-To: References: Message-ID: Hi, > On 12 Jun 2023, at 23:39, Sergey Kandaurov wrote: > > # HG changeset patch > # User Sergey Kandaurov > # Date 1686598736 -14400 > # Mon Jun 12 23:38:56 2023 +0400 > # Node ID a32905d6fc108962a73b4affdb38eba5cc6fd549 > # Parent 262c0178256623c59a54bea81fcf3f92d12d75b6 > QUIC: fixed rttvar on subsequent RTT samples (ticket #2505). > > Previously, computing rttvar used an updated smoothed_rtt value as per > RFC 9002, section 5.3, which appears to be specified in a wrong order. > A technical errata ID 7539 is reported. > > diff --git a/src/event/quic/ngx_event_quic_ack.c b/src/event/quic/ngx_event_quic_ack.c > --- a/src/event/quic/ngx_event_quic_ack.c > +++ b/src/event/quic/ngx_event_quic_ack.c > @@ -207,9 +207,9 @@ ngx_quic_rtt_sample(ngx_connection_t *c, > adjusted_rtt -= ack_delay; > } > > - qc->avg_rtt += (adjusted_rtt >> 3) - (qc->avg_rtt >> 3); > rttvar_sample = ngx_abs((ngx_msec_int_t) (qc->avg_rtt - adjusted_rtt)); > qc->rttvar += (rttvar_sample >> 2) - (qc->rttvar >> 2); > + qc->avg_rtt += (adjusted_rtt >> 3) - (qc->avg_rtt >> 3); > } > > ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0, > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > https://mailman.nginx.org/mailman/listinfo/nginx-devel LGTM ---- Roman Arutyunyan arut at nginx.com -------------- next part -------------- An HTML attachment was scrubbed... URL: From pluknet at nginx.com Tue Jun 13 07:11:29 2023 From: pluknet at nginx.com (Sergey Kandaurov) Date: Tue, 13 Jun 2023 07:11:29 +0000 Subject: [nginx] QUIC: fixed rttvar on subsequent RTT samples (ticket #2505). Message-ID: details: https://hg.nginx.org/nginx/rev/a32905d6fc10 branches: changeset: 9122:a32905d6fc10 user: Sergey Kandaurov date: Mon Jun 12 23:38:56 2023 +0400 description: QUIC: fixed rttvar on subsequent RTT samples (ticket #2505). Previously, computing rttvar used an updated smoothed_rtt value as per RFC 9002, section 5.3, which appears to be specified in a wrong order. A technical errata ID 7539 is reported. diffstat: src/event/quic/ngx_event_quic_ack.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (14 lines): diff -r 262c01782566 -r a32905d6fc10 src/event/quic/ngx_event_quic_ack.c --- a/src/event/quic/ngx_event_quic_ack.c Thu Jun 08 16:56:46 2023 +0400 +++ b/src/event/quic/ngx_event_quic_ack.c Mon Jun 12 23:38:56 2023 +0400 @@ -207,9 +207,9 @@ ngx_quic_rtt_sample(ngx_connection_t *c, adjusted_rtt -= ack_delay; } - qc->avg_rtt += (adjusted_rtt >> 3) - (qc->avg_rtt >> 3); rttvar_sample = ngx_abs((ngx_msec_int_t) (qc->avg_rtt - adjusted_rtt)); qc->rttvar += (rttvar_sample >> 2) - (qc->rttvar >> 2); + qc->avg_rtt += (adjusted_rtt >> 3) - (qc->avg_rtt >> 3); } ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0, From mdounin at mdounin.ru Tue Jun 13 13:52:17 2023 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 13 Jun 2023 16:52:17 +0300 Subject: nginx 1.25.1 changes draft Message-ID: Hello! Changes with nginx 1.25.1 13 Jun 2023 *) Feature: the "http2" directive, which enables HTTP/2 on a per-server basis; the "http2" parameter of the "listen" directive is now deprecated. *) Change: HTTP/2 server push support has been removed. *) Change: the deprecated "ssl" directive is not supported anymore. *) Bugfix: in HTTP/3 when using OpenSSL. Изменения в nginx 1.25.1 13.06.2023 *) Добавление: директива http2, позволяющая включать HTTP/2 в отдельных блоках server; параметр "http2" директивы "listen" объявлен устаревшим. *) Изменение: поддержка HTTP/2 server push упразднена. *) Изменение: устаревшая директива ssl больше не поддерживается. *) Исправление: в HTTP/3 при использовании OpenSSL. -- Maxim Dounin http://mdounin.ru/ From yar at nginx.com Tue Jun 13 13:56:50 2023 From: yar at nginx.com (=?utf-8?q?Yaroslav_Zhuravlev?=) Date: Tue, 13 Jun 2023 14:56:50 +0100 Subject: [PATCH] Documented the http2 directive Message-ID: xml/en/docs/http/ngx_http_core_module.xml | 13 +++++++++---- xml/en/docs/http/ngx_http_grpc_module.xml | 6 ++++-- xml/en/docs/http/ngx_http_v2_module.xml | 22 ++++++++++++++++++++-- xml/ru/docs/http/ngx_http_core_module.xml | 8 ++++++-- xml/ru/docs/http/ngx_http_grpc_module.xml | 6 ++++-- xml/ru/docs/http/ngx_http_v2_module.xml | 22 ++++++++++++++++++++-- 6 files changed, 63 insertions(+), 14 deletions(-) -------------- next part -------------- A non-text attachment was scrubbed... Name: nginx.org.patch Type: text/x-patch Size: 5970 bytes Desc: not available URL: From yar at nginx.com Tue Jun 13 13:58:26 2023 From: yar at nginx.com (=?utf-8?q?Yaroslav_Zhuravlev?=) Date: Tue, 13 Jun 2023 14:58:26 +0100 Subject: [PATCH] Deprecated HTTP/2 Server Push directives Message-ID: <4bb6a5759758dab2351f.1686664706@ORK-ML-00007151> xml/en/docs/http/ngx_http_v2_module.xml | 20 +++++++++++++++++++- xml/ru/docs/http/ngx_http_v2_module.xml | 20 +++++++++++++++++++- 2 files changed, 38 insertions(+), 2 deletions(-) -------------- next part -------------- A non-text attachment was scrubbed... Name: nginx.org.patch Type: text/x-patch Size: 2969 bytes Desc: not available URL: From yar at nginx.com Tue Jun 13 14:00:15 2023 From: yar at nginx.com (=?utf-8?q?Yaroslav_Zhuravlev?=) Date: Tue, 13 Jun 2023 15:00:15 +0100 Subject: [PATCH] Documented removal of the ssl directive Message-ID: xml/en/docs/http/ngx_http_ssl_module.xml | 5 +++-- xml/en/docs/mail/ngx_mail_ssl_module.xml | 5 +++-- xml/ru/docs/http/ngx_http_ssl_module.xml | 5 +++-- xml/ru/docs/mail/ngx_mail_ssl_module.xml | 5 +++-- 4 files changed, 12 insertions(+), 8 deletions(-) -------------- next part -------------- A non-text attachment was scrubbed... Name: nginx.org.patch Type: text/x-patch Size: 3341 bytes Desc: not available URL: From yar at nginx.com Tue Jun 13 14:01:22 2023 From: yar at nginx.com (=?utf-8?q?Yaroslav_Zhuravlev?=) Date: Tue, 13 Jun 2023 15:01:22 +0100 Subject: [PATCH] Updated link to HTTP/2 RFC Message-ID: xml/en/docs/http/ngx_http_v2_module.xml | 8 ++++---- xml/ru/docs/http/ngx_http_v2_module.xml | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) -------------- next part -------------- A non-text attachment was scrubbed... Name: nginx.org.patch Type: text/x-patch Size: 3765 bytes Desc: not available URL: From pluknet at nginx.com Tue Jun 13 14:14:22 2023 From: pluknet at nginx.com (Sergey Kandaurov) Date: Tue, 13 Jun 2023 18:14:22 +0400 Subject: [PATCH] Documented the http2 directive In-Reply-To: References: Message-ID: <98437147-0A42-4F45-A81A-0D04E39F2558@nginx.com> > On 13 Jun 2023, at 17:56, Yaroslav Zhuravlev wrote: > > xml/en/docs/http/ngx_http_core_module.xml | 13 +++++++++---- > xml/en/docs/http/ngx_http_grpc_module.xml | 6 ++++-- > xml/en/docs/http/ngx_http_v2_module.xml | 22 ++++++++++++++++++++-- > xml/ru/docs/http/ngx_http_core_module.xml | 8 ++++++-- > xml/ru/docs/http/ngx_http_grpc_module.xml | 6 ++++-- > xml/ru/docs/http/ngx_http_v2_module.xml | 22 ++++++++++++++++++++-- > 6 files changed, 63 insertions(+), 14 deletions(-) > > > # HG changeset patch > # User Yaroslav Zhuravlev > # Date 1686664161 -3600 > # Tue Jun 13 14:49:21 2023 +0100 > # Node ID d0b3b7889bfa45ce03845acdc51919463f455874 > # Parent 2fa6471cd138071038f055031a7a379a7e9ab108 > Documented the http2 directive. > > diff --git a/xml/en/docs/http/ngx_http_core_module.xml b/xml/en/docs/http/ngx_http_core_module.xml > --- a/xml/en/docs/http/ngx_http_core_module.xml > +++ b/xml/en/docs/http/ngx_http_core_module.xml > @@ -10,7 +10,7 @@ > link="/en/docs/http/ngx_http_core_module.html" > lang="en" > - rev="105"> > + rev="106"> > >
> > @@ -1378,12 +1378,17 @@ > handles both HTTP and HTTPS requests. > > > - > -The http2 parameter (1.9.5) configures the port to accept > -HTTP/2 connections. > + this anchor looks unused > +The http2 parameter (1.9.5) configures the port > +to accept HTTP/2 connections. unnecessary line re-wrap > Normally, for this to work the ssl parameter should be > specified as well, but nginx can also be configured to accept HTTP/2 > connections without SSL. > + > +The parameter is deprecated, > +the http2 directive > +should be used instead. > + > [..] -- Sergey Kandaurov From pluknet at nginx.com Tue Jun 13 14:15:51 2023 From: pluknet at nginx.com (Sergey Kandaurov) Date: Tue, 13 Jun 2023 18:15:51 +0400 Subject: [PATCH] Updated link to HTTP/2 RFC In-Reply-To: References: Message-ID: > On 13 Jun 2023, at 18:01, Yaroslav Zhuravlev wrote: > > xml/en/docs/http/ngx_http_v2_module.xml | 8 ++++---- > xml/ru/docs/http/ngx_http_v2_module.xml | 10 +++++----- > 2 files changed, 9 insertions(+), 9 deletions(-) > > > # HG changeset patch > # User Yaroslav Zhuravlev > # Date 1686664851 -3600 > # Tue Jun 13 15:00:51 2023 +0100 > # Node ID e201839f8e3db178307ddad117d9ea2a0178078f > # Parent d3d92847093849fe5aabc0f691409eae116390bc > Updated link to HTTP/2 RFC. > > diff --git a/xml/en/docs/http/ngx_http_v2_module.xml b/xml/en/docs/http/ngx_http_v2_module.xml > --- a/xml/en/docs/http/ngx_http_v2_module.xml > +++ b/xml/en/docs/http/ngx_http_v2_module.xml > @@ -9,7 +9,7 @@ > link="/en/docs/http/ngx_http_v2_module.html" > lang="en" > - rev="17"> > + rev="18"> > >
> > @@ -75,7 +75,7 @@ > is set to the value “on”, > the ciphers > should be configured to comply with > -RFC 7540, Appendix A > +RFC 9113, Appendix A > black list and supported by clients. > > > @@ -290,7 +290,7 @@ > > > Pre-emptively sends > -(pushes) > +(pushes) > a request to the specified uri > along with the response to the original request. > Only relative URIs with absolute path will be processed, > @@ -331,7 +331,7 @@ > preload > links > specified in the
Link
response header fields into > -push > +push > requests. >
> > diff --git a/xml/ru/docs/http/ngx_http_v2_module.xml b/xml/ru/docs/http/ngx_http_v2_module.xml > --- a/xml/ru/docs/http/ngx_http_v2_module.xml > +++ b/xml/ru/docs/http/ngx_http_v2_module.xml > @@ -9,7 +9,7 @@ > link="/ru/docs/http/ngx_http_v2_module.html" > lang="ru" > - rev="17"> > + rev="18"> > >
> > @@ -75,7 +75,7 @@ > установлена в значение “on”, > шифры > должны быть настроены таким образом, чтобы соответствовать чёрному списку > -RFC 7540, Appendix A, > +RFC 9113, Appendix A, > а также поддерживаться клиентами. > > > @@ -290,8 +290,8 @@ > > > Заблаговременно отправляет > -(push) запрос > -к заданному uri > +(push) > +запрос к заданному uri unnecessary line re-wrap > вместе с ответом на оригинальный запрос. > Будут обработаны только относительные URI с абсолютными путями, > например: > @@ -331,7 +331,7 @@ > preload > links, > указанных в полях
Link
заголовка ответа, в > -push-запросы. > +push-запросы. >
-- Sergey Kandaurov From pluknet at nginx.com Tue Jun 13 14:21:37 2023 From: pluknet at nginx.com (Sergey Kandaurov) Date: Tue, 13 Jun 2023 18:21:37 +0400 Subject: nginx 1.25.1 changes draft In-Reply-To: References: Message-ID: > On 13 Jun 2023, at 17:52, Maxim Dounin wrote: > > Hello! > > Changes with nginx 1.25.1 13 Jun 2023 > > *) Feature: the "http2" directive, which enables HTTP/2 on a per-server > basis; the "http2" parameter of the "listen" directive is now > deprecated. > > *) Change: HTTP/2 server push support has been removed. > > *) Change: the deprecated "ssl" directive is not supported anymore. > > *) Bugfix: in HTTP/3 when using OpenSSL. > > > Изменения в nginx 1.25.1 13.06.2023 > > *) Добавление: директива http2, позволяющая включать HTTP/2 в отдельных > блоках server; параметр "http2" директивы "listen" объявлен looks like extra quotes in translation > устаревшим. > > *) Изменение: поддержка HTTP/2 server push упразднена. > > *) Изменение: устаревшая директива ssl больше не поддерживается. > > *) Исправление: в HTTP/3 при использовании OpenSSL. > Otherwise looks good. -- Sergey Kandaurov From mdounin at mdounin.ru Tue Jun 13 14:46:53 2023 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 13 Jun 2023 17:46:53 +0300 Subject: [PATCH] Documented the http2 directive In-Reply-To: References: Message-ID: Hello! On Tue, Jun 13, 2023 at 02:56:50PM +0100, Yaroslav Zhuravlev wrote: > @@ -55,7 +55,9 @@ > > > server { > - listen 443 ssl http2; > + listen 443 ssl; > + > + http2 on; > > ssl_certificate server.crt; > ssl_certificate_key server.key; > @@ -82,6 +84,22 @@ > >
> > + > +on | off > +off > +http > +server > +1.25.1 > + > + > +Enables > +the HTTP/2 > +protocol. > + This probably needs some more details. In particular: - For SNI-based virtual servers, this only fully works with OpenSSL 1.0.2h and up. For older OpenSSL versions (1.0.2 - 1.0.2g), HTTP/2 needs to be enabled in the default virtual server as well. - For non-SSL listening sockets, HTTP/2 needs to be enabled in the default virtual server as well. Do not insist on adding it right now though, a separate patch clarifying the details should be good enough. [...] -- Maxim Dounin http://mdounin.ru/ From yar at nginx.com Tue Jun 13 15:10:00 2023 From: yar at nginx.com (Yaroslav Zhuravlev) Date: Tue, 13 Jun 2023 16:10:00 +0100 Subject: [PATCH] Updated link to HTTP/2 RFC In-Reply-To: References: Message-ID: <47117EB0-125B-4A1B-AF71-73E04D0D2929@nginx.com> > On 13 Jun 2023, at 15:15, Sergey Kandaurov wrote: [...] >> >> Заблаговременно отправляет >> -(push) запрос >> -к заданному uri >> +(push) >> +запрос к заданному uri > > unnecessary line re-wrap Thank you, patch updated: # HG changeset patch # User Yaroslav Zhuravlev # Date 1686668773 -3600 # Tue Jun 13 16:06:13 2023 +0100 # Node ID 412c0e5eabcc4e1b988e3166b2b940415594df34 # Parent d1a663e44fa8923c268551302b67d798060de027 Updated link to HTTP/2 RFC. diff --git a/xml/en/docs/http/ngx_http_v2_module.xml b/xml/en/docs/http/ngx_http_v2_module.xml --- a/xml/en/docs/http/ngx_http_v2_module.xml +++ b/xml/en/docs/http/ngx_http_v2_module.xml @@ -9,7 +9,7 @@ + rev="18">
@@ -75,7 +75,7 @@ is set to the value “on”, the ciphers should be configured to comply with -RFC 7540, Appendix A +RFC 9113, Appendix A black list and supported by clients. @@ -290,7 +290,7 @@ Pre-emptively sends -(pushes) +(pushes) a request to the specified uri along with the response to the original request. Only relative URIs with absolute path will be processed, @@ -331,7 +331,7 @@ preload links specified in the
Link
response header fields into -push +push requests.
diff --git a/xml/ru/docs/http/ngx_http_v2_module.xml b/xml/ru/docs/http/ngx_http_v2_module.xml --- a/xml/ru/docs/http/ngx_http_v2_module.xml +++ b/xml/ru/docs/http/ngx_http_v2_module.xml @@ -9,7 +9,7 @@ + rev="18">
@@ -75,7 +75,7 @@ установлена в значение “on”, шифры должны быть настроены таким образом, чтобы соответствовать чёрному списку -RFC 7540, Appendix A, +RFC 9113, Appendix A, а также поддерживаться клиентами. @@ -290,7 +290,7 @@ Заблаговременно отправляет -(push) запрос +(push) запрос к заданному uri вместе с ответом на оригинальный запрос. Будут обработаны только относительные URI с абсолютными путями, @@ -331,7 +331,7 @@ preload links, указанных в полях
Link
заголовка ответа, в -push-запросы. +push-запросы.
From yar at nginx.com Tue Jun 13 15:15:18 2023 From: yar at nginx.com (Yaroslav Zhuravlev) Date: Tue, 13 Jun 2023 16:15:18 +0100 Subject: [PATCH] Documented the http2 directive In-Reply-To: References: Message-ID: > On 13 Jun 2023, at 15:46, Maxim Dounin wrote: [...] >> + >> +Enables >> +the HTTP/2 >> +protocol. >> + > > This probably needs some more details. > > In particular: > > - For SNI-based virtual servers, this only fully works with > OpenSSL 1.0.2h and up. For older OpenSSL versions (1.0.2 - 1.0.2g), > HTTP/2 needs to be enabled in the default virtual server as well. > > - For non-SSL listening sockets, HTTP/2 needs to be enabled in > the default virtual server as well. > > Do not insist on adding it right now though, a separate patch > clarifying the details should be good enough. > > [...] > Thank you, the patch was updated with Sergey comments, and I'll create a separate patch explaining these details. # HG changeset patch # User Yaroslav Zhuravlev # Date 1686668685 -3600 # Tue Jun 13 16:04:45 2023 +0100 # Node ID b42c78a25477b40c78c048cd3d8f44421e814fca # Parent 2fa6471cd138071038f055031a7a379a7e9ab108 Documented the http2 directive. diff --git a/xml/en/docs/http/ngx_http_core_module.xml b/xml/en/docs/http/ngx_http_core_module.xml --- a/xml/en/docs/http/ngx_http_core_module.xml +++ b/xml/en/docs/http/ngx_http_core_module.xml @@ -10,7 +10,7 @@ + rev="106">
@@ -1384,6 +1384,11 @@ Normally, for this to work the ssl parameter should be specified as well, but nginx can also be configured to accept HTTP/2 connections without SSL. + +The parameter is deprecated, +the http2 directive +should be used instead. + diff --git a/xml/en/docs/http/ngx_http_grpc_module.xml b/xml/en/docs/http/ngx_http_grpc_module.xml --- a/xml/en/docs/http/ngx_http_grpc_module.xml +++ b/xml/en/docs/http/ngx_http_grpc_module.xml @@ -10,7 +10,7 @@ + rev="10">
@@ -29,7 +29,9 @@ server { - listen 9000 http2; + listen 9000; + + http2 on; location / { grpc_pass 127.0.0.1:9000; diff --git a/xml/en/docs/http/ngx_http_v2_module.xml b/xml/en/docs/http/ngx_http_v2_module.xml --- a/xml/en/docs/http/ngx_http_v2_module.xml +++ b/xml/en/docs/http/ngx_http_v2_module.xml @@ -9,7 +9,7 @@ + rev="16">
@@ -55,7 +55,9 @@ server { - listen 443 ssl http2; + listen 443 ssl; + + http2 on; ssl_certificate server.crt; ssl_certificate_key server.key; @@ -82,6 +84,22 @@
+ +on | off +off +http +server +1.25.1 + + +Enables +the HTTP/2 +protocol. + + + + + size 64k diff --git a/xml/ru/docs/http/ngx_http_core_module.xml b/xml/ru/docs/http/ngx_http_core_module.xml --- a/xml/ru/docs/http/ngx_http_core_module.xml +++ b/xml/ru/docs/http/ngx_http_core_module.xml @@ -10,7 +10,7 @@ + rev="106">
@@ -1376,6 +1376,10 @@ Обычно, чтобы это работало, следует также указать параметр ssl, однако nginx можно также настроить и на приём HTTP/2-соединений без SSL. + +Параметр устарел, вместо него следует использовать +директиву http2. + diff --git a/xml/ru/docs/http/ngx_http_grpc_module.xml b/xml/ru/docs/http/ngx_http_grpc_module.xml --- a/xml/ru/docs/http/ngx_http_grpc_module.xml +++ b/xml/ru/docs/http/ngx_http_grpc_module.xml @@ -10,7 +10,7 @@ + rev="10">
@@ -29,7 +29,9 @@ server { - listen 9000 http2; + listen 9000; + + http2 on; location / { grpc_pass 127.0.0.1:9000; diff --git a/xml/ru/docs/http/ngx_http_v2_module.xml b/xml/ru/docs/http/ngx_http_v2_module.xml --- a/xml/ru/docs/http/ngx_http_v2_module.xml +++ b/xml/ru/docs/http/ngx_http_v2_module.xml @@ -9,7 +9,7 @@ + rev="16">
@@ -55,7 +55,9 @@ server { - listen 443 ssl http2; + listen 443 ssl; + + http2 on; ssl_certificate server.crt; ssl_certificate_key server.key; @@ -82,6 +84,22 @@
+ +on | off +off +http +server +1.25.1 + + +Разрешает +протокол +HTTP/2. + + + + + размер 64k [...] From mdounin at mdounin.ru Tue Jun 13 15:16:46 2023 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 13 Jun 2023 18:16:46 +0300 Subject: nginx 1.25.1 changes draft In-Reply-To: References: Message-ID: Hello! On Tue, Jun 13, 2023 at 06:21:37PM +0400, Sergey Kandaurov wrote: > > > On 13 Jun 2023, at 17:52, Maxim Dounin wrote: > > > > Hello! > > > > Changes with nginx 1.25.1 13 Jun 2023 > > > > *) Feature: the "http2" directive, which enables HTTP/2 on a per-server > > basis; the "http2" parameter of the "listen" directive is now > > deprecated. > > > > *) Change: HTTP/2 server push support has been removed. > > > > *) Change: the deprecated "ssl" directive is not supported anymore. > > > > *) Bugfix: in HTTP/3 when using OpenSSL. > > > > > > Изменения в nginx 1.25.1 13.06.2023 > > > > *) Добавление: директива http2, позволяющая включать HTTP/2 в отдельных > > блоках server; параметр "http2" директивы "listen" объявлен > > looks like extra quotes in translation Fixed, thnx. > > устаревшим. > > > > *) Изменение: поддержка HTTP/2 server push упразднена. > > > > *) Изменение: устаревшая директива ssl больше не поддерживается. > > > > *) Исправление: в HTTP/3 при использовании OpenSSL. > > > > Otherwise looks good. Pushed to: http://mdounin.ru/hg/nginx http://mdounin.ru/hg/nginx.org Release files: http://mdounin.ru/temp/nginx-1.25.1.tar.gz http://mdounin.ru/temp/nginx-1.25.1.tar.gz.asc http://mdounin.ru/temp/nginx-1.25.1.zip http://mdounin.ru/temp/nginx-1.25.1.zip.asc -- Maxim Dounin http://mdounin.ru/ From thresh at nginx.com Tue Jun 13 16:28:46 2023 From: thresh at nginx.com (Konstantin Pavlov) Date: Tue, 13 Jun 2023 16:28:46 +0000 Subject: [nginx] nginx-1.25.1-RELEASE Message-ID: details: https://hg.nginx.org/nginx/rev/f8134640e861 branches: changeset: 9123:f8134640e861 user: Maxim Dounin date: Tue Jun 13 18:08:09 2023 +0300 description: nginx-1.25.1-RELEASE diffstat: docs/xml/nginx/changes.xml | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 43 insertions(+), 0 deletions(-) diffs (53 lines): diff -r a32905d6fc10 -r f8134640e861 docs/xml/nginx/changes.xml --- a/docs/xml/nginx/changes.xml Mon Jun 12 23:38:56 2023 +0400 +++ b/docs/xml/nginx/changes.xml Tue Jun 13 18:08:09 2023 +0300 @@ -5,6 +5,49 @@ + + + + +директива http2, позволяющая включать HTTP/2 в отдельных блоках server; +параметр http2 директивы listen объявлен устаревшим. + + +the "http2" directive, which enables HTTP/2 on a per-server basis; +the "http2" parameter of the "listen" directive is now deprecated. + + + + + +поддержка HTTP/2 server push упразднена. + + +HTTP/2 server push support has been removed. + + + + + +устаревшая директива ssl больше не поддерживается. + + +the deprecated "ssl" directive is not supported anymore. + + + + + +в HTTP/3 при использовании OpenSSL. + + +in HTTP/3 when using OpenSSL. + + + + + + From thresh at nginx.com Tue Jun 13 16:28:49 2023 From: thresh at nginx.com (Konstantin Pavlov) Date: Tue, 13 Jun 2023 16:28:49 +0000 Subject: [nginx] release-1.25.1 tag Message-ID: details: https://hg.nginx.org/nginx/rev/5b8854a2f79c branches: changeset: 9124:5b8854a2f79c user: Maxim Dounin date: Tue Jun 13 18:08:10 2023 +0300 description: release-1.25.1 tag diffstat: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (8 lines): diff -r f8134640e861 -r 5b8854a2f79c .hgtags --- a/.hgtags Tue Jun 13 18:08:09 2023 +0300 +++ b/.hgtags Tue Jun 13 18:08:10 2023 +0300 @@ -473,3 +473,4 @@ aa901551a7ebad1e8b0f8c11cb44e3424ba29707 ff3afd1ce6a6b65057741df442adfaa71a0e2588 release-1.23.3 ac779115ed6ee4f3039e9aea414a54e560450ee2 release-1.23.4 12dcf92b0c2c68552398f19644ce3104459807d7 release-1.25.0 +f8134640e8615448205785cf00b0bc810489b495 release-1.25.1 From mdounin at mdounin.ru Thu Jun 15 00:22:18 2023 From: mdounin at mdounin.ru (=?iso-8859-1?q?Maxim_Dounin?=) Date: Thu, 15 Jun 2023 03:22:18 +0300 Subject: [PATCH] Tests: fixed warning on win32 in auth_basic.t Message-ID: <032ccd3118cbd5a4cc17.1686788538@mdounin.local> # HG changeset patch # User Maxim Dounin # Date 1686748038 -10800 # Wed Jun 14 16:07:18 2023 +0300 # Node ID 032ccd3118cbd5a4cc170a12667cc31ddd279c1f # Parent f61d1b4ac638e756c7540dff4d2d69a82d7274fb Tests: fixed warning on win32 in auth_basic.t. diff -r f61d1b4ac638 -r 032ccd3118cb auth_basic.t --- a/auth_basic.t Wed Jun 14 16:57:01 2023 +0400 +++ b/auth_basic.t Wed Jun 14 16:07:18 2023 +0300 @@ -64,8 +64,8 @@ EOF $t->write_file( 'htpasswd', - 'crypt:' . crypt('password', 'salt') . "\n" . - 'crypt1:' . crypt('password', '$1$salt$') . "\n" . + 'crypt:' . (crypt('password', 'salt') || '') . "\n" . + 'crypt1:' . (crypt('password', '$1$salt$') || '') . "\n" . 'crypt2:' . '$1$' . "\n" . 'apr1:' . '$apr1$salt$Xxd1irWT9ycqoYxGFn4cb.' . "\n" . 'apr12:' . '$apr1$' . "\n" . From xeioex at nginx.com Thu Jun 15 00:50:25 2023 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 15 Jun 2023 00:50:25 +0000 Subject: [njs] Types: added TS types for TextDecoder and TextEncoder. Message-ID: details: https://hg.nginx.org/njs/rev/5f91f2d50578 branches: changeset: 2155:5f91f2d50578 user: Jakub Jirutka date: Sun Jun 11 00:37:36 2023 +0200 description: Types: added TS types for TextDecoder and TextEncoder. diffstat: test/ts/test.ts | 32 ++++++++++++++ ts/index.d.ts | 1 + ts/njs_webapi.d.ts | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 149 insertions(+), 0 deletions(-) diffs (171 lines): diff -r ed4ff34dfc63 -r 5f91f2d50578 test/ts/test.ts --- a/test/ts/test.ts Mon Jun 12 22:04:04 2023 -0700 +++ b/test/ts/test.ts Sun Jun 11 00:37:36 2023 +0200 @@ -272,6 +272,38 @@ function timers() { // Warning: clearTimeout(123); } +function text_decoder() { + let b:boolean; + let s:string; + + const d = new TextDecoder("utf-8", {fatal: true}); + + s = d.encoding; + b = d.fatal; + b = d.ignoreBOM; + + s += d.decode(new Uint8Array([1, 2, 3]), {stream: true}); + s += d.decode(new Uint8Array([4, 5, 6]), {stream: true}); + s += d.decode(); + + s = new TextDecoder().decode(new Uint8Array([206,177,206,178])); +} + +function text_encoder() { + let n:number; + let s:string; + let uint8a:Uint8Array; + + const e = new TextEncoder(); + + s = e.encoding; + uint8a = e.encode("text to encode"); + + const res = e.encodeInto("text to encode", uint8a); + n = res.read; + n = res.written; +} + function global_functions() { const encodedData = btoa("text to encode"); const decodedData = atob(encodedData); diff -r ed4ff34dfc63 -r 5f91f2d50578 ts/index.d.ts --- a/ts/index.d.ts Mon Jun 12 22:04:04 2023 -0700 +++ b/ts/index.d.ts Sun Jun 11 00:37:36 2023 +0200 @@ -1,4 +1,5 @@ /// +/// /// /// /// diff -r ed4ff34dfc63 -r 5f91f2d50578 ts/njs_webapi.d.ts --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ts/njs_webapi.d.ts Sun Jun 11 00:37:36 2023 +0200 @@ -0,0 +1,116 @@ +/** + * This class represents a decoder for a specific text encoding. Currently, + * only `utf-8` is supported. A decoder takes a stream of bytes as input and + * emits a stream of code points. + * + * @since 0.4.3 + */ +declare class TextDecoder { + /** + * The name of the encoding used by this `TextDecoder`. + */ + readonly encoding: "utf-8"; + /** + * Whether the error mode is "fatal". + */ + readonly fatal: boolean; + /** + * Whether the byte order marker is ignored. + */ + readonly ignoreBOM: boolean; + + /** + * Creates a new `TextDecoder` object for the specified encoding. Currently, + * only `utf-8` is supported. + */ + constructor(encoding?: "utf-8" | "utf8", options?: TextDecoderOptions); + + /** + * Returns a string containing the text decoded with the method of the + * specific `TextDecoder` object. + * + * The method can be invoked zero or more times with `options`'s `stream` set + * to `true`, and then once without `options`'s stream (or set to `false`), to + * process a fragmented input. + * + * If the error mode is `fatal` and `encoding`'s decoder returns an error, it + * throws a `TypeError`. + * + * @example + * ``` + * new TextDecoder().decode(new Uint8Array([206,177,206,178])) //=> αβ + * ``` + * + * @example + * ``` + * const decoder = new TextDecoder("utf-8"); + * let buffer: ArrayBuffer; + * let str = ""; + * + * while (buffer = nextChunk()) { + * str += decoder.decode(buffer, { stream: true }); + * } + * str += decoder.decode(); // end-of-queue + * ``` + */ + decode(buffer?: ArrayBuffer, options?: TextDecodeOptions): string; +} + +interface TextDecoderOptions { + /** + * The flag indicating if `TextDecoder.decode()` must throw the `TypeError` + * exception when a coding error is found, by default is `false`. + */ + fatal?: boolean; +} + +interface TextDecodeOptions { + /** + * The flag indicating if additional data will follow in subsequent calls to + * `decode()`: `true` if processing the data in chunks, and `false` for the + * final chunk or if the data is not chunked. By default is `false`. + */ + stream?: boolean; +} + +/** + * The `TextEncoder` object takes a stream of code points as input and emits a + * stream of UTF-8 bytes. + * + * @since 0.4.3 + */ +declare class TextEncoder { + /** + * Always returns `utf-8`. + */ + readonly encoding: "utf-8"; + + /** + * Returns a newly constructed `TextEncoder` that will generate a byte stream + * with UTF-8 encoding. + */ + constructor(); + + /** + * Encodes given `input` string into a `Uint8Array` with UTF-8 encoded text. + */ + encode(input?: string): Uint8Array; + /** + * Encodes given `source` string to UTF-8, puts the result into `destination` + * `Uint8Array`, and returns an object indicating the progress of the + * encoding. + */ + encodeInto(source: string, destination: Uint8Array): TextEncoderEncodeIntoResult; +} + +interface TextEncoderEncodeIntoResult { + /** + * The number of UTF-16 units of code from the source string converted to + * UTF-8. + */ + read: number; + /** + * The number of bytes modified in the destination `Uint8Array`. + */ + written: number; +} From xeioex at nginx.com Thu Jun 15 00:54:38 2023 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 15 Jun 2023 00:54:38 +0000 Subject: [njs] Types: updated compilerOptions.lib in tsconfig.json. Message-ID: details: https://hg.nginx.org/njs/rev/c2bc1525be25 branches: changeset: 2156:c2bc1525be25 user: Jakub Jirutka date: Sun Jun 11 00:43:33 2023 +0200 description: Types: updated compilerOptions.lib in tsconfig.json. diffstat: test/ts/tsconfig.json | 40 +++++++++++++++++++++++++++++++++++++--- ts/tsconfig.json | 40 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 74 insertions(+), 6 deletions(-) diffs (102 lines): diff -r 5f91f2d50578 -r c2bc1525be25 test/ts/tsconfig.json --- a/test/ts/tsconfig.json Sun Jun 11 00:37:36 2023 +0200 +++ b/test/ts/tsconfig.json Sun Jun 11 00:43:33 2023 +0200 @@ -3,10 +3,44 @@ "target": "ES5", "module": "es2015", "lib": [ - "ES2015", + "ES5", + // "ES2015.Collection", + "ES2015.Core", + // "ES2015.Generator", + "ES2015.Iterable", // since 0.5.0 + "ES2015.Promise", // since 0.6.2 + // "ES2015.Proxy", + // "ES2015.Reflect", + "ES2015.Symbol", // since 0.7.6 + "ES2015.Symbol.WellKnown", "ES2016.Array.Include", - "ES2017.Object", - "ES2017.String" + // "ES2017.Intl", + "ES2017.Object", // since 0.2.7 + // "ES2017.SharedMemory", + "ES2017.String", + "ES2017.TypedArrays", // since 0.3.8 + // "ES2018.AsyncGenerator", + // "ES2018.AsyncIterable", + // "ES2018.Intl", + "ES2018.Promise", // since 0.3.8 + "ES2018.Regexp", // since 0.3.2 + // "ES2019.Array", + // "ES2019.Intl", + // "ES2019.Object", + "ES2019.String", // since 0.3.4 + "ES2019.Symbol", + // "ES2020.BigInt", + "ES2020.Date", + // "ES2020.Intl", + // "ES2020.Number", + "ES2020.Promise", // since 0.6.2 + // "ES2020.SharedMemory", + // "ES2020.String", + // "ES2020.Symbol.WellKnown", + // "ES2021.Intl", + "ES2021.Promise", // since 0.6.2 + "ES2021.String" // since 0.7.10 + // "ES2021.WeakRef", ], "noEmit": true, "downlevelIteration": true, diff -r 5f91f2d50578 -r c2bc1525be25 ts/tsconfig.json --- a/ts/tsconfig.json Sun Jun 11 00:37:36 2023 +0200 +++ b/ts/tsconfig.json Sun Jun 11 00:43:33 2023 +0200 @@ -3,10 +3,44 @@ "target": "es5", "module": "ES2015", "lib": [ - "ES2015", + "ES5", + // "ES2015.Collection", + "ES2015.Core", + // "ES2015.Generator", + "ES2015.Iterable", // since 0.5.0 + "ES2015.Promise", // since 0.6.2 + // "ES2015.Proxy", + // "ES2015.Reflect", + "ES2015.Symbol", // since 0.7.6 + "ES2015.Symbol.WellKnown", "ES2016.Array.Include", - "ES2017.Object", - "ES2017.String" + // "ES2017.Intl", + "ES2017.Object", // since 0.2.7 + // "ES2017.SharedMemory", + "ES2017.String", + "ES2017.TypedArrays", // since 0.3.8 + // "ES2018.AsyncGenerator", + // "ES2018.AsyncIterable", + // "ES2018.Intl", + "ES2018.Promise", // since 0.3.8 + "ES2018.Regexp", // since 0.3.2 + // "ES2019.Array", + // "ES2019.Intl", + // "ES2019.Object", + "ES2019.String", // since 0.3.4 + "ES2019.Symbol", + // "ES2020.BigInt", + "ES2020.Date", + // "ES2020.Intl", + // "ES2020.Number", + "ES2020.Promise", // since 0.6.2 + // "ES2020.SharedMemory", + // "ES2020.String", + // "ES2020.Symbol.WellKnown", + // "ES2021.Intl", + "ES2021.Promise", // since 0.6.2 + "ES2021.String" // since 0.7.10 + // "ES2021.WeakRef", ], "noEmit": true, "strict": true, From pluknet at nginx.com Thu Jun 15 12:53:07 2023 From: pluknet at nginx.com (Sergey Kandaurov) Date: Thu, 15 Jun 2023 16:53:07 +0400 Subject: [PATCH] Tests: fixed warning on win32 in auth_basic.t In-Reply-To: <032ccd3118cbd5a4cc17.1686788538@mdounin.local> References: <032ccd3118cbd5a4cc17.1686788538@mdounin.local> Message-ID: <57155B53-C8C0-4081-A78B-9EFF1413BD5B@nginx.com> > On 15 Jun 2023, at 04:22, Maxim Dounin wrote: > > # HG changeset patch > # User Maxim Dounin > # Date 1686748038 -10800 > # Wed Jun 14 16:07:18 2023 +0300 > # Node ID 032ccd3118cbd5a4cc170a12667cc31ddd279c1f > # Parent f61d1b4ac638e756c7540dff4d2d69a82d7274fb > Tests: fixed warning on win32 in auth_basic.t. > > diff -r f61d1b4ac638 -r 032ccd3118cb auth_basic.t > --- a/auth_basic.t Wed Jun 14 16:57:01 2023 +0400 > +++ b/auth_basic.t Wed Jun 14 16:07:18 2023 +0300 > @@ -64,8 +64,8 @@ EOF > > $t->write_file( > 'htpasswd', > - 'crypt:' . crypt('password', 'salt') . "\n" . > - 'crypt1:' . crypt('password', '$1$salt$') . "\n" . > + 'crypt:' . (crypt('password', 'salt') || '') . "\n" . > + 'crypt1:' . (crypt('password', '$1$salt$') || '') . "\n" . > 'crypt2:' . '$1$' . "\n" . > 'apr1:' . '$apr1$salt$Xxd1irWT9ycqoYxGFn4cb.' . "\n" . > 'apr12:' . '$apr1$' . "\n" . No objections, including that it may not be available per perlport. I assume crypt returns undef due to missing functionality? Just for the record: on what Perl version such warnings observed? None seen on two different native Perl versions and one from msys. -- Sergey Kandaurov From mdounin at mdounin.ru Fri Jun 16 00:51:01 2023 From: mdounin at mdounin.ru (Maxim Dounin) Date: Fri, 16 Jun 2023 03:51:01 +0300 Subject: [PATCH] Tests: fixed warning on win32 in auth_basic.t In-Reply-To: <57155B53-C8C0-4081-A78B-9EFF1413BD5B@nginx.com> References: <032ccd3118cbd5a4cc17.1686788538@mdounin.local> <57155B53-C8C0-4081-A78B-9EFF1413BD5B@nginx.com> Message-ID: Hello! On Thu, Jun 15, 2023 at 04:53:07PM +0400, Sergey Kandaurov wrote: > > > On 15 Jun 2023, at 04:22, Maxim Dounin wrote: > > > > # HG changeset patch > > # User Maxim Dounin > > # Date 1686748038 -10800 > > # Wed Jun 14 16:07:18 2023 +0300 > > # Node ID 032ccd3118cbd5a4cc170a12667cc31ddd279c1f > > # Parent f61d1b4ac638e756c7540dff4d2d69a82d7274fb > > Tests: fixed warning on win32 in auth_basic.t. > > > > diff -r f61d1b4ac638 -r 032ccd3118cb auth_basic.t > > --- a/auth_basic.t Wed Jun 14 16:57:01 2023 +0400 > > +++ b/auth_basic.t Wed Jun 14 16:07:18 2023 +0300 > > @@ -64,8 +64,8 @@ EOF > > > > $t->write_file( > > 'htpasswd', > > - 'crypt:' . crypt('password', 'salt') . "\n" . > > - 'crypt1:' . crypt('password', '$1$salt$') . "\n" . > > + 'crypt:' . (crypt('password', 'salt') || '') . "\n" . > > + 'crypt1:' . (crypt('password', '$1$salt$') || '') . "\n" . > > 'crypt2:' . '$1$' . "\n" . > > 'apr1:' . '$apr1$salt$Xxd1irWT9ycqoYxGFn4cb.' . "\n" . > > 'apr12:' . '$apr1$' . "\n" . > > No objections, including that it may not be available per perlport. > I assume crypt returns undef due to missing functionality? > > Just for the record: on what Perl version such warnings observed? > None seen on two different native Perl versions and one from msys. I'm seeing the warning with Perl 5.32.1 as provided by Strawberry Perl: crypt(..., '$1$salt$') returns undef. >From the des_fcrypt() function I would expect this to happen on all modern native win32 builds (https://github.com/Perl/perl5/blob/b263f63493f4649c2ac69e2dd054bc5b1ed87f6e/win32/fcrypt.c#L488): if (!good_for_salt(salt[0]) || !good_for_salt(salt[1])) { errno = EINVAL; return NULL; } Where good_for_salt() only permits [./0-9A-Za-z], and therefore does not like attempts to use modular crypt(). This was introduced in perl 5.25.7 in 2016 (https://github.com/Perl/perl5/commit/d691474c4cf3d3119367a72ebb28a990d039baf3). Given the perlport clause that crypt() might not be available on win32 at all and the fact that crypt() passwords are not checked on win32 anyway, I've added "|| ''" for both calls. Pushed to http://mdounin.ru/hg/nginx-tests, thanks for the review. -- Maxim Dounin http://mdounin.ru/ From pluknet at nginx.com Fri Jun 16 11:31:00 2023 From: pluknet at nginx.com (Sergey Kandaurov) Date: Fri, 16 Jun 2023 15:31:00 +0400 Subject: [PATCH 1 of 3] QUIC: a new constant for AEAD tag length In-Reply-To: <1a9d3535b6bff6855132.1686294772@arut-laptop> References: <1a9d3535b6bff6855132.1686294772@arut-laptop> Message-ID: > On 9 Jun 2023, at 11:12, Roman Arutyunyan wrote: > > # HG changeset patch > # User Roman Arutyunyan > # Date 1686291954 -14400 > # Fri Jun 09 10:25:54 2023 +0400 > # Node ID 1a9d3535b6bff6855132b2685d1ca8d6b7a3af6b > # Parent 262c0178256623c59a54bea81fcf3f92d12d75b6 > QUIC: a new constant for AEAD tag length. > > Previously used constant EVP_GCM_TLS_TAG_LEN had misleading name since it was > used not only with GCM, but also with CHACHAPOLY. Now a new constant > NGX_QUIC_TAG_LEN introduced. Luckily all AEAD algorithms used by QUIC have > the same tag length of 16. Long overdue, thanks. And looks good. -- Sergey Kandaurov From pluknet at nginx.com Fri Jun 16 11:46:37 2023 From: pluknet at nginx.com (Sergey Kandaurov) Date: Fri, 16 Jun 2023 15:46:37 +0400 Subject: [PATCH 2 of 3] QUIC: common cipher control constants instead of GCM-related In-Reply-To: <74fa16d2a34a63a83fa7.1686294773@arut-laptop> References: <74fa16d2a34a63a83fa7.1686294773@arut-laptop> Message-ID: <24D1506B-270F-4935-801E-1BFD05D71240@nginx.com> > On 9 Jun 2023, at 11:12, Roman Arutyunyan wrote: > > # HG changeset patch > # User Roman Arutyunyan > # Date 1686291802 -14400 > # Fri Jun 09 10:23:22 2023 +0400 > # Node ID 74fa16d2a34a63a83fa76b46a56d8d68d44fa1bf > # Parent 1a9d3535b6bff6855132b2685d1ca8d6b7a3af6b > QUIC: common cipher control constants instead of GCM-related. > > The constants are used for both GCM and CHACHAPOLY. Looks good. Although EVP_CTRL_GCM_* is a synonym for EVP_CTRL_AEAD_*, there's no point to keep using them after ChaCha20Poly1305. Well, historically GCM variants were a source of truth in OpenSSL as well, which CCM macros used to point to :-). https://git.openssl.org/?p=openssl.git;h=2391681082 https://git.openssl.org/?p=openssl.git;h=e640fa0200 -- Sergey Kandaurov From pluknet at nginx.com Fri Jun 16 15:43:25 2023 From: pluknet at nginx.com (Sergey Kandaurov) Date: Fri, 16 Jun 2023 19:43:25 +0400 Subject: [PATCH 3 of 3] QUIC: TLS_AES_128_CCM_SHA256 cipher suite support In-Reply-To: <91c420191eaa6b8d8bd3.1686294774@arut-laptop> References: <91c420191eaa6b8d8bd3.1686294774@arut-laptop> Message-ID: <856D8499-52D2-49FF-B728-8CCAA3E55012@nginx.com> > On 9 Jun 2023, at 11:12, Roman Arutyunyan wrote: > > # HG changeset patch > # User Roman Arutyunyan > # Date 1686292815 -14400 > # Fri Jun 09 10:40:15 2023 +0400 > # Node ID 91c420191eaa6b8d8bd3dc1447d5e0880f41108f > # Parent 74fa16d2a34a63a83fa76b46a56d8d68d44fa1bf > QUIC: TLS_AES_128_CCM_SHA256 cipher suite support. > > diff --git a/src/event/quic/ngx_event_quic_protection.c b/src/event/quic/ngx_event_quic_protection.c > --- a/src/event/quic/ngx_event_quic_protection.c > +++ b/src/event/quic/ngx_event_quic_protection.c > @@ -94,6 +94,15 @@ ngx_quic_ciphers(ngx_uint_t id, ngx_quic > len = 32; > break; > > +#ifndef OPENSSL_IS_BORINGSSL > + case TLS1_3_CK_AES_128_CCM_SHA256: > + ciphers->c = EVP_aes_128_ccm(); > + ciphers->hp = EVP_aes_128_ctr(); > + ciphers->d = EVP_sha256(); > + len = 16; > + break; > +#endif > + For the record, I discussed with Roman whether to wrap this instead with TLS1_3_CK_AES_128_CCM_SHA256 and think that's not going to work. If ever this macro is added to BoringSSL, this may not work due to AEAD API divergence, see TLS1_3_CK_CHACHA20_POLY1305_SHA256 precedent. Using OPENSSL_IS_BORINGSSL looks more future promising. > default: > return NGX_ERROR; > } > @@ -393,18 +402,49 @@ ngx_quic_tls_open(const ngx_quic_cipher_ > return NGX_ERROR; > } > > + if (EVP_CIPHER_mode(cipher) == EVP_CIPH_CCM_MODE > + && EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, NGX_QUIC_TAG_LEN, > + NULL) > + == 0) bad ident, should be aligned to EVP_CIPHER_CTX_ctrl > + { > + EVP_CIPHER_CTX_free(ctx); > + ngx_ssl_error(NGX_LOG_INFO, log, 0, > + "EVP_CIPHER_CTX_ctrl(EVP_CTRL_AEAD_SET_TAG) failed"); > + return NGX_ERROR; > + } > + This control becomes redundant here, documentation says wrt CCM: This call is made to set the expected CCM tag value when decrypting or the length of the tag (with the "tag" parameter set to NULL) when encrypting. So, setting just the expected CCM tag is enough if further tune up the below SET_TAG, such that it comes before any EVP_DecryptUpdate(). > if (EVP_DecryptInit_ex(ctx, NULL, NULL, s->key.data, nonce) != 1) { > EVP_CIPHER_CTX_free(ctx); > ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_DecryptInit_ex() failed"); > return NGX_ERROR; > } > > + if (EVP_CIPHER_mode(cipher) == EVP_CIPH_CCM_MODE > + && EVP_DecryptUpdate(ctx, NULL, &len, NULL, in->len - NGX_QUIC_TAG_LEN) > + != 1) > + { > + EVP_CIPHER_CTX_free(ctx); > + ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_DecryptUpdate() failed"); > + return NGX_ERROR; > + } > + > if (EVP_DecryptUpdate(ctx, NULL, &len, ad->data, ad->len) != 1) { > EVP_CIPHER_CTX_free(ctx); > ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_DecryptUpdate() failed"); > return NGX_ERROR; > } > > + tag = in->data + in->len - NGX_QUIC_TAG_LEN; > + > + if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, NGX_QUIC_TAG_LEN, tag) > + == 0) bad ident > + { > + EVP_CIPHER_CTX_free(ctx); > + ngx_ssl_error(NGX_LOG_INFO, log, 0, > + "EVP_CIPHER_CTX_ctrl(EVP_CTRL_AEAD_SET_TAG) failed"); > + return NGX_ERROR; > + } > + So this SET_TAG control should be lifted up to avoid the above call. Any way, calling EVP_CIPHER_CTX_ctrl during decryption looks ugly (even though it doesn't seem to contradict documentation which claims that tag can be set *after* passing AD; that could be due to documentation bug). > if (EVP_DecryptUpdate(ctx, out->data, &len, in->data, > in->len - NGX_QUIC_TAG_LEN) > != 1) > @@ -415,16 +455,6 @@ ngx_quic_tls_open(const ngx_quic_cipher_ > } > > out->len = len; > - tag = in->data + in->len - NGX_QUIC_TAG_LEN; > - > - if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, NGX_QUIC_TAG_LEN, tag) > - == 0) > - { > - EVP_CIPHER_CTX_free(ctx); > - ngx_ssl_error(NGX_LOG_INFO, log, 0, > - "EVP_CIPHER_CTX_ctrl(EVP_CTRL_AEAD_SET_TAG) failed"); > - return NGX_ERROR; > - } > > if (EVP_DecryptFinal_ex(ctx, out->data + len, &len) <= 0) { > EVP_CIPHER_CTX_free(ctx); > @@ -491,12 +521,31 @@ ngx_quic_tls_seal(const ngx_quic_cipher_ > return NGX_ERROR; > } > > + if (EVP_CIPHER_mode(cipher) == EVP_CIPH_CCM_MODE > + && EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, NGX_QUIC_TAG_LEN, > + NULL) > + == 0) > + { > + EVP_CIPHER_CTX_free(ctx); > + ngx_ssl_error(NGX_LOG_INFO, log, 0, > + "EVP_CIPHER_CTX_ctrl(EVP_CTRL_AEAD_SET_TAG) failed"); > + return NGX_ERROR; > + } > + Another refinement is to set tag before ivlen, for symmetry with _tls_open(). This makes the following update on top of your change: diff --git a/src/event/quic/ngx_event_quic_protection.c b/src/event/quic/ngx_event_quic_protection.c --- a/src/event/quic/ngx_event_quic_protection.c +++ b/src/event/quic/ngx_event_quic_protection.c @@ -393,6 +393,17 @@ ngx_quic_tls_open(const ngx_quic_cipher_ return NGX_ERROR; } + tag = in->data + in->len - NGX_QUIC_TAG_LEN; + + if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, NGX_QUIC_TAG_LEN, tag) + == 0) + { + EVP_CIPHER_CTX_free(ctx); + ngx_ssl_error(NGX_LOG_INFO, log, 0, + "EVP_CIPHER_CTX_ctrl(EVP_CTRL_AEAD_SET_TAG) failed"); + return NGX_ERROR; + } + if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, s->iv.len, NULL) == 0) { @@ -402,17 +413,6 @@ ngx_quic_tls_open(const ngx_quic_cipher_ return NGX_ERROR; } - if (EVP_CIPHER_mode(cipher) == EVP_CIPH_CCM_MODE - && EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, NGX_QUIC_TAG_LEN, - NULL) - == 0) - { - EVP_CIPHER_CTX_free(ctx); - ngx_ssl_error(NGX_LOG_INFO, log, 0, - "EVP_CIPHER_CTX_ctrl(EVP_CTRL_AEAD_SET_TAG) failed"); - return NGX_ERROR; - } - if (EVP_DecryptInit_ex(ctx, NULL, NULL, s->key.data, nonce) != 1) { EVP_CIPHER_CTX_free(ctx); ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_DecryptInit_ex() failed"); @@ -434,17 +434,6 @@ ngx_quic_tls_open(const ngx_quic_cipher_ return NGX_ERROR; } - tag = in->data + in->len - NGX_QUIC_TAG_LEN; - - if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, NGX_QUIC_TAG_LEN, tag) - == 0) - { - EVP_CIPHER_CTX_free(ctx); - ngx_ssl_error(NGX_LOG_INFO, log, 0, - "EVP_CIPHER_CTX_ctrl(EVP_CTRL_AEAD_SET_TAG) failed"); - return NGX_ERROR; - } - if (EVP_DecryptUpdate(ctx, out->data, &len, in->data, in->len - NGX_QUIC_TAG_LEN) != 1) @@ -512,15 +501,6 @@ ngx_quic_tls_seal(const ngx_quic_cipher_ return NGX_ERROR; } - if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, s->iv.len, NULL) - == 0) - { - EVP_CIPHER_CTX_free(ctx); - ngx_ssl_error(NGX_LOG_INFO, log, 0, - "EVP_CIPHER_CTX_ctrl(EVP_CTRL_AEAD_SET_IVLEN) failed"); - return NGX_ERROR; - } - if (EVP_CIPHER_mode(cipher) == EVP_CIPH_CCM_MODE && EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, NGX_QUIC_TAG_LEN, NULL) @@ -532,6 +512,15 @@ ngx_quic_tls_seal(const ngx_quic_cipher_ return NGX_ERROR; } + if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, s->iv.len, NULL) + == 0) + { + EVP_CIPHER_CTX_free(ctx); + ngx_ssl_error(NGX_LOG_INFO, log, 0, + "EVP_CIPHER_CTX_ctrl(EVP_CTRL_AEAD_SET_IVLEN) failed"); + return NGX_ERROR; + } + if (EVP_EncryptInit_ex(ctx, NULL, NULL, s->key.data, nonce) != 1) { EVP_CIPHER_CTX_free(ctx); ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_EncryptInit_ex() failed"); For further symmetry, we can cut tag length off the incoming length. While here, found an occurrence of in->len which would be fine to fix. diff --git a/src/event/quic/ngx_event_quic_protection.c b/src/event/quic/ngx_event_quic_protection.c --- a/src/event/quic/ngx_event_quic_protection.c +++ b/src/event/quic/ngx_event_quic_protection.c @@ -393,7 +393,8 @@ ngx_quic_tls_open(const ngx_quic_cipher_ return NGX_ERROR; } - tag = in->data + in->len - NGX_QUIC_TAG_LEN; + in->len -= NGX_QUIC_TAG_LEN; + tag = in->data + in->len; if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, NGX_QUIC_TAG_LEN, tag) == 0) @@ -420,8 +421,7 @@ ngx_quic_tls_open(const ngx_quic_cipher_ } if (EVP_CIPHER_mode(cipher) == EVP_CIPH_CCM_MODE - && EVP_DecryptUpdate(ctx, NULL, &len, NULL, in->len - NGX_QUIC_TAG_LEN) - != 1) + && EVP_DecryptUpdate(ctx, NULL, &len, NULL, in->len) != 1) { EVP_CIPHER_CTX_free(ctx); ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_DecryptUpdate() failed"); @@ -434,10 +434,7 @@ ngx_quic_tls_open(const ngx_quic_cipher_ return NGX_ERROR; } - if (EVP_DecryptUpdate(ctx, out->data, &len, in->data, - in->len - NGX_QUIC_TAG_LEN) - != 1) - { + if (EVP_DecryptUpdate(ctx, out->data, &len, in->data, in->len) != 1) { EVP_CIPHER_CTX_free(ctx); ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_DecryptUpdate() failed"); return NGX_ERROR; @@ -558,7 +555,7 @@ ngx_quic_tls_seal(const ngx_quic_cipher_ out->len += len; if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, NGX_QUIC_TAG_LEN, - out->data + in->len) + out->data + out->len) == 0) { EVP_CIPHER_CTX_free(ctx); > if (EVP_EncryptInit_ex(ctx, NULL, NULL, s->key.data, nonce) != 1) { > EVP_CIPHER_CTX_free(ctx); > ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_EncryptInit_ex() failed"); > return NGX_ERROR; > } > > + if (EVP_CIPHER_mode(cipher) == EVP_CIPH_CCM_MODE > + && EVP_EncryptUpdate(ctx, NULL, &len, NULL, in->len) != 1) > + { > + EVP_CIPHER_CTX_free(ctx); > + ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_EncryptUpdate() failed"); > + return NGX_ERROR; > + } > + > if (EVP_EncryptUpdate(ctx, NULL, &len, ad->data, ad->len) != 1) { > EVP_CIPHER_CTX_free(ctx); > ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_EncryptUpdate() failed"); > diff --git a/src/event/quic/ngx_event_quic_protection.h b/src/event/quic/ngx_event_quic_protection.h > --- a/src/event/quic/ngx_event_quic_protection.h > +++ b/src/event/quic/ngx_event_quic_protection.h > @@ -16,7 +16,7 @@ > > #define NGX_QUIC_ENCRYPTION_LAST ((ssl_encryption_application) + 1) > > -/* RFC 5116, 5.1 and RFC 8439, 2.3/2.5 for all supported ciphers */ > +/* RFC 5116, 5.1/5.3 and RFC 8439, 2.3/2.5 for all supported ciphers */ > #define NGX_QUIC_IV_LEN 12 > #define NGX_QUIC_TAG_LEN 16 > Otherwise, looks fine. On a related note, it may have sense to finally stop wrapping TLS1_3_CK_* macros, they are in BoringSSL for roughly a year, which looks enough. # HG changeset patch # User Sergey Kandaurov # Date 1686921209 -14400 # Fri Jun 16 17:13:29 2023 +0400 # Node ID 4d13f40bafe2158fd21275dac0782189a6192061 # Parent b1e7e783cfd8908d7894d6094ff00f5d5bdee657 QUIC: removed TLS1_3_CK_* macros wrap up. They were preserved in 172705615d04 to ease building with older BoringSSL. diff --git a/src/event/quic/ngx_event_quic_protection.c b/src/event/quic/ngx_event_quic_protection.c --- a/src/event/quic/ngx_event_quic_protection.c +++ b/src/event/quic/ngx_event_quic_protection.c @@ -15,13 +15,6 @@ #define NGX_QUIC_AES_128_KEY_LEN 16 -#ifndef TLS1_3_CK_AES_128_GCM_SHA256 -#define TLS1_3_CK_AES_128_GCM_SHA256 0x03001301 -#define TLS1_3_CK_AES_256_GCM_SHA384 0x03001302 -#define TLS1_3_CK_CHACHA20_POLY1305_SHA256 \ - 0x03001303 -#endif - static ngx_int_t ngx_hkdf_expand(u_char *out_key, size_t out_len, const EVP_MD *digest, const u_char *prk, size_t prk_len, -- Sergey Kandaurov From pluknet at nginx.com Fri Jun 16 23:44:38 2023 From: pluknet at nginx.com (Sergey Kandaurov) Date: Sat, 17 Jun 2023 03:44:38 +0400 Subject: [PATCH 0 of 3] QUIC ciphers cleanup and CCM support In-Reply-To: References: Message-ID: <4C4C6638-6914-4518-80B6-2FE097BEB192@nginx.com> > On 9 Jun 2023, at 11:12, Roman Arutyunyan wrote: > > Patches 1 & 2 do minor cleanup in encryption code. > > Patch 3 adds TLS_AES_128_CCM_SHA256 support to QUIC, which currently is the > only cipher suite not supported by nginx QUIC implementation. It's disabled > by default in OpenSSL and can be enabled by the following directive: > > ssl_conf_command Ciphersuites TLS_AES_128_CCM_SHA256; Note that it is disabled in Crome and Firefox, further limiting its use. https://www.ssllabs.com/ssltest/viewClient.html?name=Firefox&version=73 https://www.ssllabs.com/ssltest/viewClient.html?name=Chrome&version=80 (same for FF 114 and Chrome 114 latest versions). It appears to be enabled though in RHEL and derivatives: https://www.redhat.com/en/blog/transport-layer-security-version-13-red-hat-enterprise-linux-8 /etc/crypto-policies/back-ends/opensslcnf.config: Ciphersuites = TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:TLS_AES_128_CCM_SHA256 -- Sergey Kandaurov From thresh at nginx.com Sat Jun 17 01:53:27 2023 From: thresh at nginx.com (=?iso-8859-1?q?Konstantin_Pavlov?=) Date: Fri, 16 Jun 2023 18:53:27 -0700 Subject: [PATCH] Linux packages: actualized supported Alpine Linux versions Message-ID: # HG changeset patch # User Konstantin Pavlov # Date 1686966791 25200 # Fri Jun 16 18:53:11 2023 -0700 # Node ID c80a7cb452e83963d5f798a5c7787ac600978dd3 # Parent c1b9ab38ff090483026eabf934d4b06107aced55 Linux packages: actualized supported Alpine Linux versions. diff -r c1b9ab38ff09 -r c80a7cb452e8 xml/en/linux_packages.xml --- a/xml/en/linux_packages.xml Tue Jun 13 19:24:58 2023 +0100 +++ b/xml/en/linux_packages.xml Fri Jun 16 18:53:11 2023 -0700 @@ -7,7 +7,7 @@
+ rev="89">
@@ -134,11 +134,6 @@ versions: -3.14 -x86_64, aarch64/arm64 - - - 3.15 x86_64, aarch64/arm64 @@ -153,6 +148,11 @@ versions: x86_64, aarch64/arm64 + +3.18 +x86_64, aarch64/arm64 + + diff -r c1b9ab38ff09 -r c80a7cb452e8 xml/ru/linux_packages.xml --- a/xml/ru/linux_packages.xml Tue Jun 13 19:24:58 2023 +0100 +++ b/xml/ru/linux_packages.xml Fri Jun 16 18:53:11 2023 -0700 @@ -7,7 +7,7 @@
+ rev="89">
@@ -134,11 +134,6 @@ -3.14 -x86_64, aarch64/arm64 - - - 3.15 x86_64, aarch64/arm64 @@ -153,6 +148,11 @@ x86_64, aarch64/arm64 + +3.18 +x86_64, aarch64/arm64 + + From maxim at nginx.com Sat Jun 17 01:55:14 2023 From: maxim at nginx.com (Maxim Konovalov) Date: Fri, 16 Jun 2023 18:55:14 -0700 Subject: [PATCH] Linux packages: actualized supported Alpine Linux versions In-Reply-To: References: Message-ID: <4be07ddf-ed19-33a2-7fd9-a7a080fddd5a@nginx.com> On 16.06.2023 18:53, Konstantin Pavlov wrote: > # HG changeset patch > # User Konstantin Pavlov > # Date 1686966791 25200 > # Fri Jun 16 18:53:11 2023 -0700 > # Node ID c80a7cb452e83963d5f798a5c7787ac600978dd3 > # Parent c1b9ab38ff090483026eabf934d4b06107aced55 > Linux packages: actualized supported Alpine Linux versions. > [...] Looks good. -- Maxim Konovalov From pluknet at nginx.com Mon Jun 19 12:35:02 2023 From: pluknet at nginx.com (Sergey Kandaurov) Date: Mon, 19 Jun 2023 16:35:02 +0400 Subject: [PATCH] QUIC: use AEAD cipher to encrypt address validation tokens In-Reply-To: <931f7f2b2aab96ca6783.1686116661@arut-laptop> References: <931f7f2b2aab96ca6783.1686116661@arut-laptop> Message-ID: > On 7 Jun 2023, at 09:44, Roman Arutyunyan wrote: > > # HG changeset patch > # User Roman Arutyunyan > # Date 1686116578 -14400 > # Wed Jun 07 09:42:58 2023 +0400 > # Node ID 931f7f2b2aab96ca6783d42a6dc4d1150b0d45ee > # Parent b4a57278bf24dd28d39afea0eb09732c05bf1606 > QUIC: use AEAD cipher to encrypt address validation tokens. > > Previously used AES256-CBC is now substituted with AES256-GCM. Although there > seem to be no tangible consequences of token integrity loss. > For the record. With the currently used AES-CBC it should not be feasible to generate a valid token for an attacker: to pass token validation, attacker's address is required to match the checksum value stored in the encrypted token, which effectively would mean to gain token encryption keys. What remains is breaking integrity by corrupting certain token parts. > diff --git a/src/event/quic/ngx_event_quic_tokens.c b/src/event/quic/ngx_event_quic_tokens.c > --- a/src/event/quic/ngx_event_quic_tokens.c > +++ b/src/event/quic/ngx_event_quic_tokens.c > @@ -69,11 +69,10 @@ ngx_quic_new_token(ngx_log_t *log, struc > > len = p - in; > > - cipher = EVP_aes_256_cbc(); > - iv_len = NGX_QUIC_AES_256_CBC_IV_LEN; > + cipher = EVP_aes_256_gcm(); > + iv_len = NGX_QUIC_AES_256_GCM_IV_LEN; > > - if ((size_t) (iv_len + len + NGX_QUIC_AES_256_CBC_BLOCK_SIZE) > token->len) > - { > + if ((size_t) (iv_len + len + NGX_QUIC_AES_256_GCM_TAG_LEN) > token->len) { > ngx_log_error(NGX_LOG_ALERT, log, 0, "quic token buffer is too small"); > return NGX_ERROR; > } > @@ -108,6 +107,17 @@ ngx_quic_new_token(ngx_log_t *log, struc > > token->len += len; > > + if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, > + NGX_QUIC_AES_256_GCM_TAG_LEN, > + token->data + token->len) > + == 0) > + { > + EVP_CIPHER_CTX_free(ctx); > + return NGX_ERROR; > + } > + > + token->len += NGX_QUIC_AES_256_GCM_TAG_LEN; > + > EVP_CIPHER_CTX_free(ctx); > > #ifdef NGX_QUIC_DEBUG_PACKETS > @@ -184,17 +194,19 @@ ngx_quic_validate_token(ngx_connection_t > > /* Retry token or NEW_TOKEN in a previous connection */ > > - cipher = EVP_aes_256_cbc(); > + cipher = EVP_aes_256_gcm(); > iv = pkt->token.data; > - iv_len = NGX_QUIC_AES_256_CBC_IV_LEN; > + iv_len = NGX_QUIC_AES_256_GCM_IV_LEN; > > /* sanity checks */ > > - if (pkt->token.len < (size_t) iv_len + NGX_QUIC_AES_256_CBC_BLOCK_SIZE) { > + if (pkt->token.len < (size_t) iv_len + NGX_QUIC_AES_256_GCM_TAG_LEN) { > goto garbage; > } > > - if (pkt->token.len > (size_t) iv_len + NGX_QUIC_MAX_TOKEN_SIZE) { > + if (pkt->token.len > (size_t) iv_len + NGX_QUIC_MAX_TOKEN_SIZE > + + NGX_QUIC_AES_256_GCM_TAG_LEN) > + { > goto garbage; > } > > @@ -209,15 +221,23 @@ ngx_quic_validate_token(ngx_connection_t > } > > p = pkt->token.data + iv_len; > - len = pkt->token.len - iv_len; > + len = pkt->token.len - iv_len - NGX_QUIC_AES_256_GCM_TAG_LEN; > > - if (EVP_DecryptUpdate(ctx, tdec, &len, p, len) != 1) { > + if (EVP_DecryptUpdate(ctx, tdec, &tlen, p, len) != 1) { > EVP_CIPHER_CTX_free(ctx); > goto garbage; > } > - total = len; > + total = tlen; > > - if (EVP_DecryptFinal_ex(ctx, tdec + len, &tlen) <= 0) { > + if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, > + NGX_QUIC_AES_256_GCM_TAG_LEN, p + len) > + == 0) > + { > + EVP_CIPHER_CTX_free(ctx); > + goto garbage; > + } > + > + if (EVP_DecryptFinal_ex(ctx, tdec + tlen, &tlen) <= 0) { > EVP_CIPHER_CTX_free(ctx); > goto garbage; > } > diff --git a/src/event/quic/ngx_event_quic_tokens.h b/src/event/quic/ngx_event_quic_tokens.h > --- a/src/event/quic/ngx_event_quic_tokens.h > +++ b/src/event/quic/ngx_event_quic_tokens.h > @@ -15,13 +15,12 @@ > #define NGX_QUIC_MAX_TOKEN_SIZE 64 > /* SHA-1(addr)=20 + sizeof(time_t) + retry(1) + odcid.len(1) + odcid */ > > -/* RFC 3602, 2.1 and 2.4 for AES-CBC block size and IV length */ > -#define NGX_QUIC_AES_256_CBC_IV_LEN 16 > -#define NGX_QUIC_AES_256_CBC_BLOCK_SIZE 16 > +#define NGX_QUIC_AES_256_GCM_IV_LEN 12 > +#define NGX_QUIC_AES_256_GCM_TAG_LEN 16 JFTR: although NGX_QUIC_TAG_LEN / NGX_QUIC_IV_LEN could be reused, I think it's fine to take separate tag/iv macros, since token encryption algorithm isn't related to TLS cipher suites. > > -#define NGX_QUIC_TOKEN_BUF_SIZE (NGX_QUIC_AES_256_CBC_IV_LEN \ > +#define NGX_QUIC_TOKEN_BUF_SIZE (NGX_QUIC_AES_256_GCM_IV_LEN \ > + NGX_QUIC_MAX_TOKEN_SIZE \ > - + NGX_QUIC_AES_256_CBC_BLOCK_SIZE) > + + NGX_QUIC_AES_256_GCM_TAG_LEN) > > > ngx_int_t ngx_quic_new_sr_token(ngx_connection_t *c, ngx_str_t *cid, Patch looks good. -- Sergey Kandaurov From arut at nginx.com Tue Jun 20 13:14:03 2023 From: arut at nginx.com (Roman Arutyunyan) Date: Tue, 20 Jun 2023 17:14:03 +0400 Subject: [PATCH] Configure: dump unsupported repository error and exit In-Reply-To: References: Message-ID: <20230620131403.fhjyxyd5fp4sdn4v@N00W24XTQX> Hi, On Tue, May 23, 2023 at 08:29:03PM +0400, Sergey Kandaurov wrote: > > > On 23 May 2023, at 19:48, Roman Arutyunyan wrote: > > > > # HG changeset patch > > # User Roman Arutyunyan > > # Date 1684856745 -14400 > > # Tue May 23 19:45:45 2023 +0400 > > # Branch quic > > # Node ID bd25277d0ed77a90766bc2f4153538c86621cdfc > > # Parent a83071314a22652d4a552e72e13d18aa4c01d79e > > Configure: dump unsupported repository error and exit. > > > > diff --git a/auto/configure b/auto/configure > > --- a/auto/configure > > +++ b/auto/configure > > @@ -4,6 +4,13 @@ > > # Copyright (C) Nginx, Inc. > > > > > > +cat << END > > + > > +$0: this repository is no longer supported, see README > > + > > +END > > +exit 1 > > + > > LC_ALL=C > > export LC_ALL > > > > Something similar to what we use for invalid options might be enough. > Also, using "error" might help emphasize this is an error: > > diff --git a/auto/configure b/auto/configure > --- a/auto/configure > +++ b/auto/configure > @@ -4,6 +4,9 @@ > # Copyright (C) Nginx, Inc. > > > +echo "$0: error: this repository is no longer supported, see README" > +exit 1 > + > LC_ALL=C > export LC_ALL Usually two empty lines are added as well (see auto/lib/perl/conf for example): diff --git a/auto/configure b/auto/configure --- a/auto/configure +++ b/auto/configure @@ -4,6 +4,12 @@ # Copyright (C) Nginx, Inc. +echo +echo "$0: error: this repository is no longer supported, see README" +echo + +exit 1 + LC_ALL=C export LC_ALL > > > Personally, I think this makes sense, in order to help break pipelines. > > -- > Sergey Kandaurov > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > https://mailman.nginx.org/mailman/listinfo/nginx-devel -- Roman Arutyunyan From pluknet at nginx.com Tue Jun 20 13:23:35 2023 From: pluknet at nginx.com (Sergey Kandaurov) Date: Tue, 20 Jun 2023 17:23:35 +0400 Subject: [PATCH] Configure: dump unsupported repository error and exit In-Reply-To: <20230620131403.fhjyxyd5fp4sdn4v@N00W24XTQX> References: <20230620131403.fhjyxyd5fp4sdn4v@N00W24XTQX> Message-ID: <6A756B27-9220-498E-947D-2A589BCEC684@nginx.com> > On 20 Jun 2023, at 17:14, Roman Arutyunyan wrote: > > Hi, > > On Tue, May 23, 2023 at 08:29:03PM +0400, Sergey Kandaurov wrote: >> >>> On 23 May 2023, at 19:48, Roman Arutyunyan wrote: >>> >>> # HG changeset patch >>> # User Roman Arutyunyan >>> # Date 1684856745 -14400 >>> # Tue May 23 19:45:45 2023 +0400 >>> # Branch quic >>> # Node ID bd25277d0ed77a90766bc2f4153538c86621cdfc >>> # Parent a83071314a22652d4a552e72e13d18aa4c01d79e >>> Configure: dump unsupported repository error and exit. >>> >>> diff --git a/auto/configure b/auto/configure >>> --- a/auto/configure >>> +++ b/auto/configure >>> @@ -4,6 +4,13 @@ >>> # Copyright (C) Nginx, Inc. >>> >>> >>> +cat << END >>> + >>> +$0: this repository is no longer supported, see README >>> + >>> +END >>> +exit 1 >>> + >>> LC_ALL=C >>> export LC_ALL >>> >> >> Something similar to what we use for invalid options might be enough. >> Also, using "error" might help emphasize this is an error: >> >> diff --git a/auto/configure b/auto/configure >> --- a/auto/configure >> +++ b/auto/configure >> @@ -4,6 +4,9 @@ >> # Copyright (C) Nginx, Inc. >> >> >> +echo "$0: error: this repository is no longer supported, see README" >> +exit 1 >> + >> LC_ALL=C >> export LC_ALL > > Usually two empty lines are added as well (see auto/lib/perl/conf for example): > > diff --git a/auto/configure b/auto/configure > --- a/auto/configure > +++ b/auto/configure > @@ -4,6 +4,12 @@ > # Copyright (C) Nginx, Inc. > > > +echo > +echo "$0: error: this repository is no longer supported, see README" > +echo > + > +exit 1 > + > LC_ALL=C > export LC_ALL > Agree, I feels better. > >> >> >> Personally, I think this makes sense, in order to help break pipelines. >> -- Sergey Kandaurov From pluknet at nginx.com Tue Jun 20 13:43:03 2023 From: pluknet at nginx.com (=?iso-8859-1?q?Sergey_Kandaurov?=) Date: Tue, 20 Jun 2023 17:43:03 +0400 Subject: [PATCH] HTTP/3: fixed $body_bytes_sent Message-ID: # HG changeset patch # User Sergey Kandaurov # Date 1687268079 -14400 # Tue Jun 20 17:34:39 2023 +0400 # Node ID a95bffe430283bf25341ad9745ffe1199e7c2190 # Parent bf4bd5af4d7fdadab83616be9218604b658e3d84 HTTP/3: fixed $body_bytes_sent. diff --git a/src/http/v3/ngx_http_v3_filter_module.c b/src/http/v3/ngx_http_v3_filter_module.c --- a/src/http/v3/ngx_http_v3_filter_module.c +++ b/src/http/v3/ngx_http_v3_filter_module.c @@ -540,6 +540,8 @@ ngx_http_v3_header_filter(ngx_http_reque *ll = hl; ll = &cl->next; + r->header_size = n + (b->last - b->pos); + if (r->headers_out.content_length_n >= 0 && !r->header_only && !r->expect_trailers) { From arut at nginx.com Tue Jun 20 13:51:21 2023 From: arut at nginx.com (Roman Arutyunyan) Date: Tue, 20 Jun 2023 13:51:21 +0000 Subject: [nginx] Version bump. Message-ID: details: https://hg.nginx.org/nginx/rev/31c8c1a713bc branches: changeset: 9125:31c8c1a713bc user: Roman Arutyunyan date: Tue Jun 20 17:01:00 2023 +0400 description: Version bump. diffstat: src/core/nginx.h | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diffs (14 lines): diff -r 5b8854a2f79c -r 31c8c1a713bc src/core/nginx.h --- a/src/core/nginx.h Tue Jun 13 18:08:10 2023 +0300 +++ b/src/core/nginx.h Tue Jun 20 17:01:00 2023 +0400 @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1025001 -#define NGINX_VERSION "1.25.1" +#define nginx_version 1025002 +#define NGINX_VERSION "1.25.2" #define NGINX_VER "nginx/" NGINX_VERSION #ifdef NGX_BUILD From arut at nginx.com Tue Jun 20 13:51:24 2023 From: arut at nginx.com (Roman Arutyunyan) Date: Tue, 20 Jun 2023 13:51:24 +0000 Subject: [nginx] QUIC: a new constant for AEAD tag length. Message-ID: details: https://hg.nginx.org/nginx/rev/29a6c0e11f75 branches: changeset: 9126:29a6c0e11f75 user: Roman Arutyunyan date: Fri Jun 09 10:25:54 2023 +0400 description: QUIC: a new constant for AEAD tag length. Previously used constant EVP_GCM_TLS_TAG_LEN had misleading name since it was used not only with GCM, but also with CHACHAPOLY. Now a new constant NGX_QUIC_TAG_LEN introduced. Luckily all AEAD algorithms used by QUIC have the same tag length of 16. diffstat: src/event/quic/ngx_event_quic_openssl_compat.c | 6 +++--- src/event/quic/ngx_event_quic_protection.c | 18 +++++++++--------- src/event/quic/ngx_event_quic_protection.h | 3 ++- src/event/quic/ngx_event_quic_transport.c | 6 +++--- 4 files changed, 17 insertions(+), 16 deletions(-) diffs (152 lines): diff -r 31c8c1a713bc -r 29a6c0e11f75 src/event/quic/ngx_event_quic_openssl_compat.c --- a/src/event/quic/ngx_event_quic_openssl_compat.c Tue Jun 20 17:01:00 2023 +0400 +++ b/src/event/quic/ngx_event_quic_openssl_compat.c Fri Jun 09 10:25:54 2023 +0400 @@ -445,7 +445,7 @@ SSL_provide_quic_data(SSL *ssl, enum ssl u_char in[NGX_QUIC_COMPAT_RECORD_SIZE + 1]; u_char out[NGX_QUIC_COMPAT_RECORD_SIZE + 1 + SSL3_RT_HEADER_LENGTH - + EVP_GCM_TLS_TAG_LEN]; + + NGX_QUIC_TAG_LEN]; c = ngx_ssl_get_connection(ssl); @@ -528,7 +528,7 @@ ngx_quic_compat_create_header(ngx_quic_c } else { type = SSL3_RT_APPLICATION_DATA; - len += EVP_GCM_TLS_TAG_LEN; + len += NGX_QUIC_TAG_LEN; } out[0] = type; @@ -552,7 +552,7 @@ ngx_quic_compat_create_record(ngx_quic_c ad.data = res->data; ad.len = ngx_quic_compat_create_header(rec, ad.data, 0); - out.len = rec->payload.len + EVP_GCM_TLS_TAG_LEN; + out.len = rec->payload.len + NGX_QUIC_TAG_LEN; out.data = res->data + ad.len; #ifdef NGX_QUIC_DEBUG_CRYPTO diff -r 31c8c1a713bc -r 29a6c0e11f75 src/event/quic/ngx_event_quic_protection.c --- a/src/event/quic/ngx_event_quic_protection.c Tue Jun 20 17:01:00 2023 +0400 +++ b/src/event/quic/ngx_event_quic_protection.c Fri Jun 09 10:25:54 2023 +0400 @@ -406,7 +406,7 @@ ngx_quic_tls_open(const ngx_quic_cipher_ } if (EVP_DecryptUpdate(ctx, out->data, &len, in->data, - in->len - EVP_GCM_TLS_TAG_LEN) + in->len - NGX_QUIC_TAG_LEN) != 1) { EVP_CIPHER_CTX_free(ctx); @@ -415,9 +415,9 @@ ngx_quic_tls_open(const ngx_quic_cipher_ } out->len = len; - tag = in->data + in->len - EVP_GCM_TLS_TAG_LEN; + tag = in->data + in->len - NGX_QUIC_TAG_LEN; - if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, EVP_GCM_TLS_TAG_LEN, tag) + if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, NGX_QUIC_TAG_LEN, tag) == 0) { EVP_CIPHER_CTX_free(ctx); @@ -519,7 +519,7 @@ ngx_quic_tls_seal(const ngx_quic_cipher_ out->len += len; - if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, EVP_GCM_TLS_TAG_LEN, + if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, NGX_QUIC_TAG_LEN, out->data + in->len) == 0) { @@ -531,7 +531,7 @@ ngx_quic_tls_seal(const ngx_quic_cipher_ EVP_CIPHER_CTX_free(ctx); - out->len += EVP_GCM_TLS_TAG_LEN; + out->len += NGX_QUIC_TAG_LEN; #endif return NGX_OK; } @@ -738,7 +738,7 @@ ngx_quic_create_packet(ngx_quic_header_t ad.data = res->data; ad.len = ngx_quic_create_header(pkt, ad.data, &pnp); - out.len = pkt->payload.len + EVP_GCM_TLS_TAG_LEN; + out.len = pkt->payload.len + NGX_QUIC_TAG_LEN; out.data = res->data + ad.len; #ifdef NGX_QUIC_DEBUG_CRYPTO @@ -802,7 +802,7 @@ ngx_quic_create_retry_packet(ngx_quic_he ad.len = ngx_quic_create_retry_itag(pkt, ad.data, &start); itag.data = ad.data + ad.len; - itag.len = EVP_GCM_TLS_TAG_LEN; + itag.len = NGX_QUIC_TAG_LEN; #ifdef NGX_QUIC_DEBUG_CRYPTO ngx_log_debug2(NGX_LOG_DEBUG_EVENT, pkt->log, 0, @@ -979,7 +979,7 @@ ngx_quic_decrypt(ngx_quic_header_t *pkt, * AES and ChaCha20 algorithms sample 16 bytes */ - if (len < EVP_GCM_TLS_TAG_LEN + 4) { + if (len < NGX_QUIC_TAG_LEN + 4) { return NGX_DECLINED; } @@ -1039,7 +1039,7 @@ ngx_quic_decrypt(ngx_quic_header_t *pkt, "quic ad len:%uz %xV", ad.len, &ad); #endif - pkt->payload.len = in.len - EVP_GCM_TLS_TAG_LEN; + pkt->payload.len = in.len - NGX_QUIC_TAG_LEN; pkt->payload.data = pkt->plaintext + ad.len; rc = ngx_quic_tls_open(ciphers.c, secret, &pkt->payload, diff -r 31c8c1a713bc -r 29a6c0e11f75 src/event/quic/ngx_event_quic_protection.h --- a/src/event/quic/ngx_event_quic_protection.h Tue Jun 20 17:01:00 2023 +0400 +++ b/src/event/quic/ngx_event_quic_protection.h Fri Jun 09 10:25:54 2023 +0400 @@ -16,8 +16,9 @@ #define NGX_QUIC_ENCRYPTION_LAST ((ssl_encryption_application) + 1) -/* RFC 5116, 5.1 and RFC 8439, 2.3 for all supported ciphers */ +/* RFC 5116, 5.1 and RFC 8439, 2.3/2.5 for all supported ciphers */ #define NGX_QUIC_IV_LEN 12 +#define NGX_QUIC_TAG_LEN 16 /* largest hash used in TLS is SHA-384 */ #define NGX_QUIC_MAX_MD_SIZE 48 diff -r 31c8c1a713bc -r 29a6c0e11f75 src/event/quic/ngx_event_quic_transport.c --- a/src/event/quic/ngx_event_quic_transport.c Tue Jun 20 17:01:00 2023 +0400 +++ b/src/event/quic/ngx_event_quic_transport.c Fri Jun 09 10:25:54 2023 +0400 @@ -578,7 +578,7 @@ ngx_quic_payload_size(ngx_quic_header_t if (ngx_quic_short_pkt(pkt->flags)) { - len = 1 + pkt->dcid.len + pkt->num_len + EVP_GCM_TLS_TAG_LEN; + len = 1 + pkt->dcid.len + pkt->num_len + NGX_QUIC_TAG_LEN; if (len > pkt_len) { return 0; } @@ -596,7 +596,7 @@ ngx_quic_payload_size(ngx_quic_header_t /* (pkt_len - len) is 'remainder' packet length (see RFC 9000, 17.2) */ len += ngx_quic_varint_len(pkt_len - len) - + pkt->num_len + EVP_GCM_TLS_TAG_LEN; + + pkt->num_len + NGX_QUIC_TAG_LEN; if (len > pkt_len) { return 0; @@ -622,7 +622,7 @@ ngx_quic_create_long_header(ngx_quic_hea size_t rem_len; u_char *p, *start; - rem_len = pkt->num_len + pkt->payload.len + EVP_GCM_TLS_TAG_LEN; + rem_len = pkt->num_len + pkt->payload.len + NGX_QUIC_TAG_LEN; if (out == NULL) { return 5 + 2 + pkt->dcid.len + pkt->scid.len From arut at nginx.com Tue Jun 20 13:51:27 2023 From: arut at nginx.com (Roman Arutyunyan) Date: Tue, 20 Jun 2023 13:51:27 +0000 Subject: [nginx] QUIC: common cipher control constants instead of GCM-related. Message-ID: details: https://hg.nginx.org/nginx/rev/a7b850a5d98d branches: changeset: 9127:a7b850a5d98d user: Roman Arutyunyan date: Fri Jun 09 10:23:22 2023 +0400 description: QUIC: common cipher control constants instead of GCM-related. The constants are used for both GCM and CHACHAPOLY. diffstat: src/event/quic/ngx_event_quic_protection.c | 16 ++++++++-------- 1 files changed, 8 insertions(+), 8 deletions(-) diffs (64 lines): diff -r 29a6c0e11f75 -r a7b850a5d98d src/event/quic/ngx_event_quic_protection.c --- a/src/event/quic/ngx_event_quic_protection.c Fri Jun 09 10:25:54 2023 +0400 +++ b/src/event/quic/ngx_event_quic_protection.c Fri Jun 09 10:23:22 2023 +0400 @@ -384,12 +384,12 @@ ngx_quic_tls_open(const ngx_quic_cipher_ return NGX_ERROR; } - if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, s->iv.len, NULL) + if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, s->iv.len, NULL) == 0) { EVP_CIPHER_CTX_free(ctx); ngx_ssl_error(NGX_LOG_INFO, log, 0, - "EVP_CIPHER_CTX_ctrl(EVP_CTRL_GCM_SET_IVLEN) failed"); + "EVP_CIPHER_CTX_ctrl(EVP_CTRL_AEAD_SET_IVLEN) failed"); return NGX_ERROR; } @@ -417,12 +417,12 @@ ngx_quic_tls_open(const ngx_quic_cipher_ out->len = len; tag = in->data + in->len - NGX_QUIC_TAG_LEN; - if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, NGX_QUIC_TAG_LEN, tag) + if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, NGX_QUIC_TAG_LEN, tag) == 0) { EVP_CIPHER_CTX_free(ctx); ngx_ssl_error(NGX_LOG_INFO, log, 0, - "EVP_CIPHER_CTX_ctrl(EVP_CTRL_GCM_SET_TAG) failed"); + "EVP_CIPHER_CTX_ctrl(EVP_CTRL_AEAD_SET_TAG) failed"); return NGX_ERROR; } @@ -482,12 +482,12 @@ ngx_quic_tls_seal(const ngx_quic_cipher_ return NGX_ERROR; } - if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, s->iv.len, NULL) + if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, s->iv.len, NULL) == 0) { EVP_CIPHER_CTX_free(ctx); ngx_ssl_error(NGX_LOG_INFO, log, 0, - "EVP_CIPHER_CTX_ctrl(EVP_CTRL_GCM_SET_IVLEN) failed"); + "EVP_CIPHER_CTX_ctrl(EVP_CTRL_AEAD_SET_IVLEN) failed"); return NGX_ERROR; } @@ -519,13 +519,13 @@ ngx_quic_tls_seal(const ngx_quic_cipher_ out->len += len; - if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, NGX_QUIC_TAG_LEN, + if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, NGX_QUIC_TAG_LEN, out->data + in->len) == 0) { EVP_CIPHER_CTX_free(ctx); ngx_ssl_error(NGX_LOG_INFO, log, 0, - "EVP_CIPHER_CTX_ctrl(EVP_CTRL_GCM_GET_TAG) failed"); + "EVP_CIPHER_CTX_ctrl(EVP_CTRL_AEAD_GET_TAG) failed"); return NGX_ERROR; } From arut at nginx.com Tue Jun 20 13:51:30 2023 From: arut at nginx.com (Roman Arutyunyan) Date: Tue, 20 Jun 2023 13:51:30 +0000 Subject: [nginx] QUIC: TLS_AES_128_CCM_SHA256 cipher suite support. Message-ID: details: https://hg.nginx.org/nginx/rev/756ab66de10e branches: changeset: 9128:756ab66de10e user: Roman Arutyunyan date: Tue Jun 20 16:10:49 2023 +0400 description: QUIC: TLS_AES_128_CCM_SHA256 cipher suite support. diffstat: src/event/quic/ngx_event_quic_protection.c | 58 ++++++++++++++++++++++++----- src/event/quic/ngx_event_quic_protection.h | 2 +- 2 files changed, 49 insertions(+), 11 deletions(-) diffs (115 lines): diff -r a7b850a5d98d -r 756ab66de10e src/event/quic/ngx_event_quic_protection.c --- a/src/event/quic/ngx_event_quic_protection.c Fri Jun 09 10:23:22 2023 +0400 +++ b/src/event/quic/ngx_event_quic_protection.c Tue Jun 20 16:10:49 2023 +0400 @@ -94,6 +94,15 @@ ngx_quic_ciphers(ngx_uint_t id, ngx_quic len = 32; break; +#ifndef OPENSSL_IS_BORINGSSL + case TLS1_3_CK_AES_128_CCM_SHA256: + ciphers->c = EVP_aes_128_ccm(); + ciphers->hp = EVP_aes_128_ctr(); + ciphers->d = EVP_sha256(); + len = 16; + break; +#endif + default: return NGX_ERROR; } @@ -384,6 +393,17 @@ ngx_quic_tls_open(const ngx_quic_cipher_ return NGX_ERROR; } + tag = in->data + in->len - NGX_QUIC_TAG_LEN; + + if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, NGX_QUIC_TAG_LEN, tag) + == 0) + { + EVP_CIPHER_CTX_free(ctx); + ngx_ssl_error(NGX_LOG_INFO, log, 0, + "EVP_CIPHER_CTX_ctrl(EVP_CTRL_AEAD_SET_TAG) failed"); + return NGX_ERROR; + } + if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, s->iv.len, NULL) == 0) { @@ -399,6 +419,15 @@ ngx_quic_tls_open(const ngx_quic_cipher_ return NGX_ERROR; } + if (EVP_CIPHER_mode(cipher) == EVP_CIPH_CCM_MODE + && EVP_DecryptUpdate(ctx, NULL, &len, NULL, in->len - NGX_QUIC_TAG_LEN) + != 1) + { + EVP_CIPHER_CTX_free(ctx); + ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_DecryptUpdate() failed"); + return NGX_ERROR; + } + if (EVP_DecryptUpdate(ctx, NULL, &len, ad->data, ad->len) != 1) { EVP_CIPHER_CTX_free(ctx); ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_DecryptUpdate() failed"); @@ -415,16 +444,6 @@ ngx_quic_tls_open(const ngx_quic_cipher_ } out->len = len; - tag = in->data + in->len - NGX_QUIC_TAG_LEN; - - if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, NGX_QUIC_TAG_LEN, tag) - == 0) - { - EVP_CIPHER_CTX_free(ctx); - ngx_ssl_error(NGX_LOG_INFO, log, 0, - "EVP_CIPHER_CTX_ctrl(EVP_CTRL_AEAD_SET_TAG) failed"); - return NGX_ERROR; - } if (EVP_DecryptFinal_ex(ctx, out->data + len, &len) <= 0) { EVP_CIPHER_CTX_free(ctx); @@ -482,6 +501,17 @@ ngx_quic_tls_seal(const ngx_quic_cipher_ return NGX_ERROR; } + if (EVP_CIPHER_mode(cipher) == EVP_CIPH_CCM_MODE + && EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, NGX_QUIC_TAG_LEN, + NULL) + == 0) + { + EVP_CIPHER_CTX_free(ctx); + ngx_ssl_error(NGX_LOG_INFO, log, 0, + "EVP_CIPHER_CTX_ctrl(EVP_CTRL_AEAD_SET_TAG) failed"); + return NGX_ERROR; + } + if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, s->iv.len, NULL) == 0) { @@ -497,6 +527,14 @@ ngx_quic_tls_seal(const ngx_quic_cipher_ return NGX_ERROR; } + if (EVP_CIPHER_mode(cipher) == EVP_CIPH_CCM_MODE + && EVP_EncryptUpdate(ctx, NULL, &len, NULL, in->len) != 1) + { + EVP_CIPHER_CTX_free(ctx); + ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_EncryptUpdate() failed"); + return NGX_ERROR; + } + if (EVP_EncryptUpdate(ctx, NULL, &len, ad->data, ad->len) != 1) { EVP_CIPHER_CTX_free(ctx); ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_EncryptUpdate() failed"); diff -r a7b850a5d98d -r 756ab66de10e src/event/quic/ngx_event_quic_protection.h --- a/src/event/quic/ngx_event_quic_protection.h Fri Jun 09 10:23:22 2023 +0400 +++ b/src/event/quic/ngx_event_quic_protection.h Tue Jun 20 16:10:49 2023 +0400 @@ -16,7 +16,7 @@ #define NGX_QUIC_ENCRYPTION_LAST ((ssl_encryption_application) + 1) -/* RFC 5116, 5.1 and RFC 8439, 2.3/2.5 for all supported ciphers */ +/* RFC 5116, 5.1/5.3 and RFC 8439, 2.3/2.5 for all supported ciphers */ #define NGX_QUIC_IV_LEN 12 #define NGX_QUIC_TAG_LEN 16 From pluknet at nginx.com Tue Jun 20 15:30:18 2023 From: pluknet at nginx.com (Sergey Kandaurov) Date: Tue, 20 Jun 2023 15:30:18 +0000 Subject: [nginx] QUIC: unified ngx_quic_tls_open() and ngx_quic_tls_seal(). Message-ID: details: https://hg.nginx.org/nginx/rev/7379cb29cd72 branches: changeset: 9129:7379cb29cd72 user: Sergey Kandaurov date: Tue Jun 20 17:59:01 2023 +0400 description: QUIC: unified ngx_quic_tls_open() and ngx_quic_tls_seal(). diffstat: src/event/quic/ngx_event_quic_protection.c | 18 +++++++----------- 1 files changed, 7 insertions(+), 11 deletions(-) diffs (64 lines): diff -r 756ab66de10e -r 7379cb29cd72 src/event/quic/ngx_event_quic_protection.c --- a/src/event/quic/ngx_event_quic_protection.c Tue Jun 20 16:10:49 2023 +0400 +++ b/src/event/quic/ngx_event_quic_protection.c Tue Jun 20 17:59:01 2023 +0400 @@ -378,7 +378,6 @@ ngx_quic_tls_open(const ngx_quic_cipher_ EVP_AEAD_CTX_free(ctx); #else int len; - u_char *tag; EVP_CIPHER_CTX *ctx; ctx = EVP_CIPHER_CTX_new(); @@ -393,9 +392,10 @@ ngx_quic_tls_open(const ngx_quic_cipher_ return NGX_ERROR; } - tag = in->data + in->len - NGX_QUIC_TAG_LEN; + in->len -= NGX_QUIC_TAG_LEN; - if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, NGX_QUIC_TAG_LEN, tag) + if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, NGX_QUIC_TAG_LEN, + in->data + in->len) == 0) { EVP_CIPHER_CTX_free(ctx); @@ -420,8 +420,7 @@ ngx_quic_tls_open(const ngx_quic_cipher_ } if (EVP_CIPHER_mode(cipher) == EVP_CIPH_CCM_MODE - && EVP_DecryptUpdate(ctx, NULL, &len, NULL, in->len - NGX_QUIC_TAG_LEN) - != 1) + && EVP_DecryptUpdate(ctx, NULL, &len, NULL, in->len) != 1) { EVP_CIPHER_CTX_free(ctx); ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_DecryptUpdate() failed"); @@ -434,10 +433,7 @@ ngx_quic_tls_open(const ngx_quic_cipher_ return NGX_ERROR; } - if (EVP_DecryptUpdate(ctx, out->data, &len, in->data, - in->len - NGX_QUIC_TAG_LEN) - != 1) - { + if (EVP_DecryptUpdate(ctx, out->data, &len, in->data, in->len) != 1) { EVP_CIPHER_CTX_free(ctx); ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_DecryptUpdate() failed"); return NGX_ERROR; @@ -445,7 +441,7 @@ ngx_quic_tls_open(const ngx_quic_cipher_ out->len = len; - if (EVP_DecryptFinal_ex(ctx, out->data + len, &len) <= 0) { + if (EVP_DecryptFinal_ex(ctx, out->data + out->len, &len) <= 0) { EVP_CIPHER_CTX_free(ctx); ngx_ssl_error(NGX_LOG_INFO, log, 0, "EVP_DecryptFinal_ex failed"); return NGX_ERROR; @@ -558,7 +554,7 @@ ngx_quic_tls_seal(const ngx_quic_cipher_ out->len += len; if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, NGX_QUIC_TAG_LEN, - out->data + in->len) + out->data + out->len) == 0) { EVP_CIPHER_CTX_free(ctx); From pluknet at nginx.com Tue Jun 20 15:30:21 2023 From: pluknet at nginx.com (Sergey Kandaurov) Date: Tue, 20 Jun 2023 15:30:21 +0000 Subject: [nginx] QUIC: style. Message-ID: details: https://hg.nginx.org/nginx/rev/0f23488a9f5a branches: changeset: 9130:0f23488a9f5a user: Sergey Kandaurov date: Tue Jun 20 17:59:02 2023 +0400 description: QUIC: style. diffstat: src/event/quic/ngx_event_quic_protection.c | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diffs (27 lines): diff -r 7379cb29cd72 -r 0f23488a9f5a src/event/quic/ngx_event_quic_protection.c --- a/src/event/quic/ngx_event_quic_protection.c Tue Jun 20 17:59:01 2023 +0400 +++ b/src/event/quic/ngx_event_quic_protection.c Tue Jun 20 17:59:02 2023 +0400 @@ -352,8 +352,7 @@ failed: static ngx_int_t ngx_quic_tls_open(const ngx_quic_cipher_t *cipher, ngx_quic_secret_t *s, - ngx_str_t *out, u_char *nonce, ngx_str_t *in, ngx_str_t *ad, - ngx_log_t *log) + ngx_str_t *out, u_char *nonce, ngx_str_t *in, ngx_str_t *ad, ngx_log_t *log) { #ifdef OPENSSL_IS_BORINGSSL @@ -563,10 +562,11 @@ ngx_quic_tls_seal(const ngx_quic_cipher_ return NGX_ERROR; } - EVP_CIPHER_CTX_free(ctx); + out->len += NGX_QUIC_TAG_LEN; - out->len += NGX_QUIC_TAG_LEN; + EVP_CIPHER_CTX_free(ctx); #endif + return NGX_OK; } From pluknet at nginx.com Tue Jun 20 15:30:23 2023 From: pluknet at nginx.com (Sergey Kandaurov) Date: Tue, 20 Jun 2023 15:30:23 +0000 Subject: [nginx] QUIC: removed TLS1_3_CK_* macros wrap up. Message-ID: details: https://hg.nginx.org/nginx/rev/f73dfa6c0696 branches: changeset: 9131:f73dfa6c0696 user: Sergey Kandaurov date: Fri Jun 16 17:13:29 2023 +0400 description: QUIC: removed TLS1_3_CK_* macros wrap up. They were preserved in 172705615d04 to ease transition from older BoringSSL. diffstat: src/event/quic/ngx_event_quic_protection.c | 7 ------- 1 files changed, 0 insertions(+), 7 deletions(-) diffs (17 lines): diff -r 0f23488a9f5a -r f73dfa6c0696 src/event/quic/ngx_event_quic_protection.c --- a/src/event/quic/ngx_event_quic_protection.c Tue Jun 20 17:59:02 2023 +0400 +++ b/src/event/quic/ngx_event_quic_protection.c Fri Jun 16 17:13:29 2023 +0400 @@ -15,13 +15,6 @@ #define NGX_QUIC_AES_128_KEY_LEN 16 -#ifndef TLS1_3_CK_AES_128_GCM_SHA256 -#define TLS1_3_CK_AES_128_GCM_SHA256 0x03001301 -#define TLS1_3_CK_AES_256_GCM_SHA384 0x03001302 -#define TLS1_3_CK_CHACHA20_POLY1305_SHA256 \ - 0x03001303 -#endif - static ngx_int_t ngx_hkdf_expand(u_char *out_key, size_t out_len, const EVP_MD *digest, const u_char *prk, size_t prk_len, From arut at nginx.com Tue Jun 20 15:46:09 2023 From: arut at nginx.com (Roman Arutyunyan) Date: Tue, 20 Jun 2023 15:46:09 +0000 Subject: [nginx] QUIC: use AEAD to encrypt address validation tokens. Message-ID: details: https://hg.nginx.org/nginx/rev/77c1418916f7 branches: changeset: 9132:77c1418916f7 user: Roman Arutyunyan date: Thu Jun 08 14:58:01 2023 +0400 description: QUIC: use AEAD to encrypt address validation tokens. Previously used AES256-CBC is now substituted with AES256-GCM. Although there seem to be no tangible consequences of token integrity loss. diffstat: src/event/quic/ngx_event_quic_tokens.c | 44 ++++++++++++++++++++++++--------- src/event/quic/ngx_event_quic_tokens.h | 9 +++--- 2 files changed, 36 insertions(+), 17 deletions(-) diffs (109 lines): diff -r f73dfa6c0696 -r 77c1418916f7 src/event/quic/ngx_event_quic_tokens.c --- a/src/event/quic/ngx_event_quic_tokens.c Fri Jun 16 17:13:29 2023 +0400 +++ b/src/event/quic/ngx_event_quic_tokens.c Thu Jun 08 14:58:01 2023 +0400 @@ -69,11 +69,10 @@ ngx_quic_new_token(ngx_log_t *log, struc len = p - in; - cipher = EVP_aes_256_cbc(); - iv_len = NGX_QUIC_AES_256_CBC_IV_LEN; + cipher = EVP_aes_256_gcm(); + iv_len = NGX_QUIC_AES_256_GCM_IV_LEN; - if ((size_t) (iv_len + len + NGX_QUIC_AES_256_CBC_BLOCK_SIZE) > token->len) - { + if ((size_t) (iv_len + len + NGX_QUIC_AES_256_GCM_TAG_LEN) > token->len) { ngx_log_error(NGX_LOG_ALERT, log, 0, "quic token buffer is too small"); return NGX_ERROR; } @@ -108,6 +107,17 @@ ngx_quic_new_token(ngx_log_t *log, struc token->len += len; + if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, + NGX_QUIC_AES_256_GCM_TAG_LEN, + token->data + token->len) + == 0) + { + EVP_CIPHER_CTX_free(ctx); + return NGX_ERROR; + } + + token->len += NGX_QUIC_AES_256_GCM_TAG_LEN; + EVP_CIPHER_CTX_free(ctx); #ifdef NGX_QUIC_DEBUG_PACKETS @@ -184,17 +194,19 @@ ngx_quic_validate_token(ngx_connection_t /* Retry token or NEW_TOKEN in a previous connection */ - cipher = EVP_aes_256_cbc(); + cipher = EVP_aes_256_gcm(); iv = pkt->token.data; - iv_len = NGX_QUIC_AES_256_CBC_IV_LEN; + iv_len = NGX_QUIC_AES_256_GCM_IV_LEN; /* sanity checks */ - if (pkt->token.len < (size_t) iv_len + NGX_QUIC_AES_256_CBC_BLOCK_SIZE) { + if (pkt->token.len < (size_t) iv_len + NGX_QUIC_AES_256_GCM_TAG_LEN) { goto garbage; } - if (pkt->token.len > (size_t) iv_len + NGX_QUIC_MAX_TOKEN_SIZE) { + if (pkt->token.len > (size_t) iv_len + NGX_QUIC_MAX_TOKEN_SIZE + + NGX_QUIC_AES_256_GCM_TAG_LEN) + { goto garbage; } @@ -209,15 +221,23 @@ ngx_quic_validate_token(ngx_connection_t } p = pkt->token.data + iv_len; - len = pkt->token.len - iv_len; + len = pkt->token.len - iv_len - NGX_QUIC_AES_256_GCM_TAG_LEN; - if (EVP_DecryptUpdate(ctx, tdec, &len, p, len) != 1) { + if (EVP_DecryptUpdate(ctx, tdec, &tlen, p, len) != 1) { EVP_CIPHER_CTX_free(ctx); goto garbage; } - total = len; + total = tlen; - if (EVP_DecryptFinal_ex(ctx, tdec + len, &tlen) <= 0) { + if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, + NGX_QUIC_AES_256_GCM_TAG_LEN, p + len) + == 0) + { + EVP_CIPHER_CTX_free(ctx); + goto garbage; + } + + if (EVP_DecryptFinal_ex(ctx, tdec + tlen, &tlen) <= 0) { EVP_CIPHER_CTX_free(ctx); goto garbage; } diff -r f73dfa6c0696 -r 77c1418916f7 src/event/quic/ngx_event_quic_tokens.h --- a/src/event/quic/ngx_event_quic_tokens.h Fri Jun 16 17:13:29 2023 +0400 +++ b/src/event/quic/ngx_event_quic_tokens.h Thu Jun 08 14:58:01 2023 +0400 @@ -15,13 +15,12 @@ #define NGX_QUIC_MAX_TOKEN_SIZE 64 /* SHA-1(addr)=20 + sizeof(time_t) + retry(1) + odcid.len(1) + odcid */ -/* RFC 3602, 2.1 and 2.4 for AES-CBC block size and IV length */ -#define NGX_QUIC_AES_256_CBC_IV_LEN 16 -#define NGX_QUIC_AES_256_CBC_BLOCK_SIZE 16 +#define NGX_QUIC_AES_256_GCM_IV_LEN 12 +#define NGX_QUIC_AES_256_GCM_TAG_LEN 16 -#define NGX_QUIC_TOKEN_BUF_SIZE (NGX_QUIC_AES_256_CBC_IV_LEN \ +#define NGX_QUIC_TOKEN_BUF_SIZE (NGX_QUIC_AES_256_GCM_IV_LEN \ + NGX_QUIC_MAX_TOKEN_SIZE \ - + NGX_QUIC_AES_256_CBC_BLOCK_SIZE) + + NGX_QUIC_AES_256_GCM_TAG_LEN) ngx_int_t ngx_quic_new_sr_token(ngx_connection_t *c, ngx_str_t *cid, From xeioex at nginx.com Thu Jun 22 22:40:00 2023 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 22 Jun 2023 22:40:00 +0000 Subject: [njs] Added public API to throw standard exceptions. Message-ID: details: https://hg.nginx.org/njs/rev/09441c1c24ea branches: changeset: 2157:09441c1c24ea user: Dmitry Volyntsev date: Wed Jun 21 16:17:42 2023 -0700 description: Added public API to throw standard exceptions. diffstat: src/njs.h | 26 +++++++++++++++++++------- src/njs_error.c | 18 +++++++++--------- src/njs_error.h | 6 +++--- src/njs_parser.c | 2 +- src/njs_promise.c | 10 ++++++---- src/njs_vm.c | 9 +++++++-- src/njs_vm.h | 1 + 7 files changed, 46 insertions(+), 26 deletions(-) diffs (226 lines): diff -r c2bc1525be25 -r 09441c1c24ea src/njs.h --- a/src/njs.h Sun Jun 11 00:43:33 2023 +0200 +++ b/src/njs.h Wed Jun 21 16:17:42 2023 -0700 @@ -72,12 +72,23 @@ extern const njs_value_t njs_ ((n < nargs) ? njs_argument(args, n) \ : (njs_value_assign(lvalue, &njs_value_undefined), lvalue)) -#define njs_vm_log(vm, fmt, ...) njs_vm_logger(vm, NJS_LOG_LEVEL_INFO, fmt, \ - ##__VA_ARGS__) -#define njs_vm_warn(vm, fmt, ...) njs_vm_logger(vm, NJS_LOG_LEVEL_WARN, fmt, \ - ##__VA_ARGS__) -#define njs_vm_err(vm, fmt, ...) njs_vm_logger(vm, NJS_LOG_LEVEL_ERROR, fmt, \ - ##__VA_ARGS__) +#define njs_vm_log(vm, fmt, ...) \ + njs_vm_logger(vm, NJS_LOG_LEVEL_INFO, fmt, ##__VA_ARGS__) +#define njs_vm_warn(vm, fmt, ...) \ + njs_vm_logger(vm, NJS_LOG_LEVEL_WARN, fmt, ##__VA_ARGS__) +#define njs_vm_err(vm, fmt, ...) \ + njs_vm_logger(vm, NJS_LOG_LEVEL_ERROR, fmt, ##__VA_ARGS__) + +#define njs_vm_error(vm, fmt, ...) \ + njs_vm_error2(vm, 0, fmt, ##__VA_ARGS__) +#define njs_vm_internal_error(vm, fmt, ...) \ + njs_vm_error2(vm, 2, fmt, ##__VA_ARGS__) +#define njs_vm_range_error(vm, fmt, ...) \ + njs_vm_error2(vm, 3, fmt, ##__VA_ARGS__) +#define njs_vm_syntax_error(vm, fmt, ...) \ + njs_vm_error2(vm, 5, fmt, ##__VA_ARGS__) +#define njs_vm_type_error(vm, fmt, ...) \ + njs_vm_error2(vm, 6, fmt, ##__VA_ARGS__) #define njs_deprecated(vm, text) \ do { \ @@ -419,7 +430,8 @@ NJS_EXPORT njs_function_t *njs_vm_functi NJS_EXPORT njs_bool_t njs_vm_constructor(njs_vm_t *vm); NJS_EXPORT void njs_vm_throw(njs_vm_t *vm, const njs_value_t *value); -NJS_EXPORT void njs_vm_error(njs_vm_t *vm, const char *fmt, ...); +NJS_EXPORT void njs_vm_error2(njs_vm_t *vm, unsigned type, const char *fmt, + ...); NJS_EXPORT void njs_vm_exception_get(njs_vm_t *vm, njs_value_t *retval); NJS_EXPORT njs_mp_t *njs_vm_memory_pool(njs_vm_t *vm); NJS_EXPORT njs_external_ptr_t njs_vm_external_ptr(njs_vm_t *vm); diff -r c2bc1525be25 -r 09441c1c24ea src/njs_error.c --- a/src/njs_error.c Sun Jun 11 00:43:33 2023 +0200 +++ b/src/njs_error.c Wed Jun 21 16:17:42 2023 -0700 @@ -28,7 +28,7 @@ static const njs_value_t njs_error_erro void -njs_error_new(njs_vm_t *vm, njs_value_t *dst, njs_object_type_t type, +njs_error_new(njs_vm_t *vm, njs_value_t *dst, njs_object_t *proto, u_char *start, size_t size) { ssize_t length; @@ -46,7 +46,7 @@ njs_error_new(njs_vm_t *vm, njs_value_t return; } - error = njs_error_alloc(vm, type, NULL, &string, NULL); + error = njs_error_alloc(vm, proto, NULL, &string, NULL); if (njs_slow_path(error == NULL)) { return; } @@ -55,7 +55,7 @@ njs_error_new(njs_vm_t *vm, njs_value_t } void -njs_throw_error_va(njs_vm_t *vm, njs_object_type_t type, const char *fmt, +njs_throw_error_va(njs_vm_t *vm, njs_object_t *proto, const char *fmt, va_list args) { u_char buf[NJS_MAX_ERROR_STR], *p; @@ -66,7 +66,7 @@ njs_throw_error_va(njs_vm_t *vm, njs_obj p = njs_vsprintf(buf, buf + sizeof(buf), fmt, args); } - njs_error_new(vm, &vm->exception, type, buf, p - buf); + njs_error_new(vm, &vm->exception, proto, buf, p - buf); } @@ -76,7 +76,7 @@ njs_throw_error(njs_vm_t *vm, njs_object va_list args; va_start(args, fmt); - njs_throw_error_va(vm, type, fmt, args); + njs_throw_error_va(vm, &vm->prototypes[type].object, fmt, args); va_end(args); } @@ -96,7 +96,7 @@ njs_error_fmt_new(njs_vm_t *vm, njs_valu va_end(args); } - njs_error_new(vm, dst, type, buf, p - buf); + njs_error_new(vm, dst, &vm->prototypes[type].object, buf, p - buf); } @@ -202,7 +202,7 @@ njs_error_stack(njs_vm_t *vm, njs_value_ njs_object_t * -njs_error_alloc(njs_vm_t *vm, njs_object_type_t type, const njs_value_t *name, +njs_error_alloc(njs_vm_t *vm, njs_object_t *proto, const njs_value_t *name, const njs_value_t *message, const njs_value_t *errors) { njs_int_t ret; @@ -223,7 +223,7 @@ njs_error_alloc(njs_vm_t *vm, njs_object error->fast_array = 0; error->error_data = 1; error->stack_attached = 0; - error->__proto__ = &vm->prototypes[type].object; + error->__proto__ = proto; error->slots = NULL; lhq.replace = 0; @@ -339,7 +339,7 @@ njs_error_constructor(njs_vm_t *vm, njs_ } } - error = njs_error_alloc(vm, type, NULL, + error = njs_error_alloc(vm, &vm->prototypes[type].object, NULL, njs_is_defined(value) ? value : NULL, njs_is_defined(&list) ? &list : NULL); if (njs_slow_path(error == NULL)) { diff -r c2bc1525be25 -r 09441c1c24ea src/njs_error.h --- a/src/njs_error.h Sun Jun 11 00:43:33 2023 +0200 +++ b/src/njs_error.h Wed Jun 21 16:17:42 2023 -0700 @@ -25,19 +25,19 @@ #define njs_uri_error(vm, fmt, ...) \ njs_throw_error(vm, NJS_OBJ_TYPE_URI_ERROR, fmt, ##__VA_ARGS__) -void njs_error_new(njs_vm_t *vm, njs_value_t *dst, njs_object_type_t type, +void njs_error_new(njs_vm_t *vm, njs_value_t *dst, njs_object_t *proto, u_char *start, size_t size); void njs_noinline njs_error_fmt_new(njs_vm_t *vm, njs_value_t *dst, njs_object_type_t type, const char *fmt, ...); void njs_throw_error(njs_vm_t *vm, njs_object_type_t type, const char *fmt, ...); -void njs_throw_error_va(njs_vm_t *vm, njs_object_type_t type, const char *fmt, +void njs_throw_error_va(njs_vm_t *vm, njs_object_t *proto, const char *fmt, va_list args); void njs_memory_error(njs_vm_t *vm); void njs_memory_error_set(njs_vm_t *vm, njs_value_t *value); -njs_object_t *njs_error_alloc(njs_vm_t *vm, njs_object_type_t type, +njs_object_t *njs_error_alloc(njs_vm_t *vm, njs_object_t *proto, const njs_value_t *name, const njs_value_t *message, const njs_value_t *errors); njs_int_t njs_error_to_string(njs_vm_t *vm, njs_value_t *retval, diff -r c2bc1525be25 -r 09441c1c24ea src/njs_parser.c --- a/src/njs_parser.c Sun Jun 11 00:43:33 2023 +0200 +++ b/src/njs_parser.c Wed Jun 21 16:17:42 2023 -0700 @@ -9205,7 +9205,7 @@ njs_parser_error(njs_vm_t *vm, njs_objec p = njs_sprintf(p, end, " in %uD", line); } - njs_error_new(vm, &error, type, msg, p - msg); + njs_error_new(vm, &error, &vm->prototypes[type].object, msg, p - msg); njs_set_number(&value, line); njs_value_property_set(vm, &error, njs_value_arg(&line_number), &value); diff -r c2bc1525be25 -r 09441c1c24ea src/njs_promise.c --- a/src/njs_promise.c Sun Jun 11 00:43:33 2023 +0200 +++ b/src/njs_promise.c Wed Jun 21 16:17:42 2023 -0700 @@ -1351,8 +1351,9 @@ njs_promise_perform_all(njs_vm_t *vm, nj njs_set_array(&argument, pargs->args.data); if (handler == njs_promise_perform_any_handler) { - error = njs_error_alloc(vm, NJS_OBJ_TYPE_AGGREGATE_ERROR, - NULL, &string_any_rejected, &argument); + error = njs_error_alloc(vm, + &vm->prototypes[NJS_OBJ_TYPE_AGGREGATE_ERROR].object, + NULL, &string_any_rejected, &argument); if (njs_slow_path(error == NULL)) { return NJS_ERROR; } @@ -1728,8 +1729,9 @@ njs_promise_any_reject_element_functions if (--(*context->remaining_elements) == 0) { njs_mp_free(vm->mem_pool, context->remaining_elements); - error = njs_error_alloc(vm, NJS_OBJ_TYPE_AGGREGATE_ERROR, - NULL, &string_any_rejected, &arr_value); + error = njs_error_alloc(vm, + &vm->prototypes[NJS_OBJ_TYPE_AGGREGATE_ERROR].object, + NULL, &string_any_rejected, &arr_value); if (njs_slow_path(error == NULL)) { return NJS_ERROR; } diff -r c2bc1525be25 -r 09441c1c24ea src/njs_vm.c --- a/src/njs_vm.c Sun Jun 11 00:43:33 2023 +0200 +++ b/src/njs_vm.c Wed Jun 21 16:17:42 2023 -0700 @@ -733,12 +733,17 @@ njs_vm_throw(njs_vm_t *vm, const njs_val void -njs_vm_error(njs_vm_t *vm, const char *fmt, ...) +njs_vm_error2(njs_vm_t *vm, unsigned type, const char *fmt, ...) { va_list args; + if (type > (NJS_OBJ_TYPE_ERROR_MAX - NJS_OBJ_TYPE_ERROR)) { + return; + } + va_start(args, fmt); - njs_throw_error_va(vm, NJS_OBJ_TYPE_ERROR, fmt, args); + type += NJS_OBJ_TYPE_ERROR; + njs_throw_error_va(vm, &vm->prototypes[type].object, fmt, args); va_end(args); } diff -r c2bc1525be25 -r 09441c1c24ea src/njs_vm.h --- a/src/njs_vm.h Sun Jun 11 00:43:33 2023 +0200 +++ b/src/njs_vm.h Wed Jun 21 16:17:42 2023 -0700 @@ -76,6 +76,7 @@ typedef enum { NJS_OBJ_TYPE_URI_ERROR, NJS_OBJ_TYPE_MEMORY_ERROR, NJS_OBJ_TYPE_AGGREGATE_ERROR, +#define NJS_OBJ_TYPE_ERROR_MAX (NJS_OBJ_TYPE_AGGREGATE_ERROR) NJS_OBJ_TYPE_MAX, } njs_object_type_t; From xeioex at nginx.com Thu Jun 22 22:40:02 2023 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 22 Jun 2023 22:40:02 +0000 Subject: [njs] FS: added back custom exception types using new public API. Message-ID: details: https://hg.nginx.org/njs/rev/aaab085e499f branches: changeset: 2158:aaab085e499f user: Dmitry Volyntsev date: Wed Jun 21 16:29:45 2023 -0700 description: FS: added back custom exception types using new public API. In 18385a4a90ad, when rewriting FS module using public API all the exceptions types were squashed into a single Error type. This patch reintroduces the standard exception types back using new API. diffstat: external/njs_fs_module.c | 95 ++++++++++++++++++++++++----------------------- src/test/njs_unit_test.c | 68 +++++++++++++++++----------------- test/fs/methods.t.js | 8 ++-- test/fs/promises_07.t.js | 2 +- 4 files changed, 88 insertions(+), 85 deletions(-) diffs (602 lines): diff -r 09441c1c24ea -r aaab085e499f external/njs_fs_module.c --- a/external/njs_fs_module.c Wed Jun 21 16:17:42 2023 -0700 +++ b/external/njs_fs_module.c Wed Jun 21 16:29:45 2023 -0700 @@ -1433,7 +1433,7 @@ njs_fs_access(njs_vm_t *vm, njs_value_t if (calltype == NJS_FS_CALLBACK) { callback = njs_arg(args, nargs, njs_min(nargs - 1, 3)); if (!njs_value_is_function(callback)) { - njs_vm_error(vm, "\"callback\" must be a function"); + njs_vm_type_error(vm, "\"callback\" must be a function"); return NJS_ERROR; } @@ -1449,7 +1449,7 @@ njs_fs_access(njs_vm_t *vm, njs_value_t md = F_OK; } else { - njs_vm_error(vm, "\"mode\" must be a number"); + njs_vm_type_error(vm, "\"mode\" must be a number"); return NJS_ERROR; } @@ -1587,7 +1587,7 @@ njs_fs_mkdir(njs_vm_t *vm, njs_value_t * if (njs_slow_path(calltype == NJS_FS_CALLBACK)) { callback = njs_arg(args, nargs, njs_min(nargs - 1, 3)); if (!njs_value_is_function(callback)) { - njs_vm_error(vm, "\"callback\" must be a function"); + njs_vm_type_error(vm, "\"callback\" must be a function"); return NJS_ERROR; } @@ -1604,8 +1604,8 @@ njs_fs_mkdir(njs_vm_t *vm, njs_value_t * } else if (!njs_value_is_undefined(options)) { if (!njs_value_is_object(options)) { - njs_vm_error(vm, "Unknown options type" - "(a number or object required)"); + njs_vm_type_error(vm, "Unknown options type" + "(a number or object required)"); return NJS_ERROR; } @@ -1669,7 +1669,8 @@ njs_fs_read(njs_vm_t *vm, njs_value_t *a } if (njs_slow_path(offset < 0 || (size_t) offset > data.length)) { - njs_vm_error(vm, "offset is out of range (must be <= %z)", data.length); + njs_vm_range_error(vm, "offset is out of range (must be <= %z)", + data.length); return NJS_ERROR; } @@ -1685,8 +1686,8 @@ njs_fs_read(njs_vm_t *vm, njs_value_t *a } if (njs_slow_path(length < 0 || (size_t) length > data.length)) { - njs_vm_error(vm, "length is out of range (must be <= %z)", - data.length); + njs_vm_range_error(vm, "length is out of range (must be <= %z)", + data.length); return NJS_ERROR; } @@ -1760,7 +1761,7 @@ njs_fs_read_file(njs_vm_t *vm, njs_value if (calltype == NJS_FS_CALLBACK) { callback = njs_arg(args, nargs, njs_min(nargs - 1, 3)); if (!njs_value_is_function(callback)) { - njs_vm_error(vm, "\"callback\" must be a function"); + njs_vm_type_error(vm, "\"callback\" must be a function"); return NJS_ERROR; } @@ -1777,8 +1778,8 @@ njs_fs_read_file(njs_vm_t *vm, njs_value } else if (!njs_value_is_undefined(options)) { if (!njs_value_is_object(options)) { - njs_vm_error(vm, "Unknown options type " - "(a string or object required)"); + njs_vm_type_error(vm, "Unknown options type " + "(a string or object required)"); return NJS_ERROR; } @@ -1880,7 +1881,7 @@ njs_fs_readdir(njs_vm_t *vm, njs_value_t if (njs_slow_path(calltype == NJS_FS_CALLBACK)) { callback = njs_arg(args, nargs, njs_min(nargs - 1, 3)); if (!njs_value_is_function(callback)) { - njs_vm_error(vm, "\"callback\" must be a function"); + njs_vm_type_error(vm, "\"callback\" must be a function"); return NJS_ERROR; } if (options == callback) { @@ -1896,8 +1897,8 @@ njs_fs_readdir(njs_vm_t *vm, njs_value_t } else if (!njs_value_is_undefined(options)) { if (!njs_value_is_object(options)) { - njs_vm_error(vm, "Unknown options type " - "(a string or object required)"); + njs_vm_type_error(vm, "Unknown options type " + "(a string or object required)"); return NJS_ERROR; } @@ -2022,7 +2023,7 @@ njs_fs_realpath(njs_vm_t *vm, njs_value_ if (calltype == NJS_FS_CALLBACK) { callback = njs_arg(args, nargs, njs_min(nargs - 1, 3)); if (!njs_value_is_function(callback)) { - njs_vm_error(vm, "\"callback\" must be a function"); + njs_vm_type_error(vm, "\"callback\" must be a function"); return NJS_ERROR; } @@ -2038,8 +2039,8 @@ njs_fs_realpath(njs_vm_t *vm, njs_value_ } else if (!njs_value_is_undefined(options)) { if (!njs_value_is_object(options)) { - njs_vm_error(vm, "Unknown options type " - "(a string or object required)"); + njs_vm_type_error(vm, "Unknown options type " + "(a string or object required)"); return NJS_ERROR; } @@ -2101,7 +2102,7 @@ njs_fs_rename(njs_vm_t *vm, njs_value_t if (calltype == NJS_FS_CALLBACK) { callback = njs_arg(args, nargs, 3); if (!njs_value_is_function(callback)) { - njs_vm_error(vm, "\"callback\" must be a function"); + njs_vm_type_error(vm, "\"callback\" must be a function"); return NJS_ERROR; } } @@ -2152,7 +2153,7 @@ njs_fs_rmdir(njs_vm_t *vm, njs_value_t * if (njs_slow_path(calltype == NJS_FS_CALLBACK)) { callback = njs_arg(args, nargs, njs_min(nargs - 1, 3)); if (!njs_value_is_function(callback)) { - njs_vm_error(vm, "\"callback\" must be a function"); + njs_vm_type_error(vm, "\"callback\" must be a function"); return NJS_ERROR; } if (options == callback) { @@ -2164,8 +2165,8 @@ njs_fs_rmdir(njs_vm_t *vm, njs_value_t * if (njs_slow_path(!njs_value_is_undefined(options))) { if (!njs_value_is_object(options)) { - njs_vm_error(vm, "Unknown options type " - "(an object required)"); + njs_vm_type_error(vm, "Unknown options type " + "(an object required)"); return NJS_ERROR; } @@ -2229,7 +2230,7 @@ njs_fs_stat(njs_vm_t *vm, njs_value_t *a if (njs_slow_path(calltype == NJS_FS_CALLBACK)) { callback = njs_arg(args, nargs, njs_min(nargs - 1, 3)); if (!njs_value_is_function(callback)) { - njs_vm_error(vm, "\"callback\" must be a function"); + njs_vm_type_error(vm, "\"callback\" must be a function"); return NJS_ERROR; } @@ -2242,14 +2243,14 @@ njs_fs_stat(njs_vm_t *vm, njs_value_t *a if (!njs_value_is_undefined(options)) { if (!njs_value_is_object(options)) { - njs_vm_error(vm, "Unknown options type " - "(an object required)"); + njs_vm_type_error(vm, "Unknown options type " + "(an object required)"); return NJS_ERROR; } value = njs_vm_object_prop(vm, options, &string_bigint, &result); if (value != NULL && njs_value_bool(value)) { - njs_vm_error(vm, "\"bigint\" is not supported"); + njs_vm_type_error(vm, "\"bigint\" is not supported"); return NJS_ERROR; } @@ -2328,7 +2329,7 @@ njs_fs_symlink(njs_vm_t *vm, njs_value_t if (calltype == NJS_FS_CALLBACK) { callback = njs_arg(args, nargs, njs_min(nargs - 1, 4)); if (!njs_value_is_function(callback)) { - njs_vm_error(vm, "\"callback\" must be a function"); + njs_vm_type_error(vm, "\"callback\" must be a function"); return NJS_ERROR; } @@ -2340,7 +2341,7 @@ njs_fs_symlink(njs_vm_t *vm, njs_value_t if (njs_slow_path(!njs_value_is_undefined(type) && !njs_value_is_string(type))) { - njs_vm_error(vm, "\"type\" must be a string"); + njs_vm_type_error(vm, "\"type\" must be a string"); return NJS_ERROR; } @@ -2380,7 +2381,7 @@ njs_fs_unlink(njs_vm_t *vm, njs_value_t if (calltype == NJS_FS_CALLBACK) { callback = njs_arg(args, nargs, 2); if (!njs_value_is_function(callback)) { - njs_vm_error(vm, "\"callback\" must be a function"); + njs_vm_type_error(vm, "\"callback\" must be a function"); return NJS_ERROR; } } @@ -2474,8 +2475,8 @@ njs_fs_write(njs_vm_t *vm, njs_value_t * } if (njs_slow_path(offset < 0 || (size_t) offset > data.length)) { - njs_vm_error(vm, "offset is out of range (must be <= %z)", - data.length); + njs_vm_range_error(vm, "offset is out of range (must be <= %z)", + data.length); return NJS_ERROR; } @@ -2491,8 +2492,8 @@ njs_fs_write(njs_vm_t *vm, njs_value_t * } if (njs_slow_path(length < 0 || (size_t) length > data.length)) { - njs_vm_error(vm, "length is out of range (must be <= %z)", - data.length); + njs_vm_range_error(vm, "length is out of range (must be <= %z)", + data.length); return NJS_ERROR; } @@ -2577,7 +2578,7 @@ njs_fs_write_file(njs_vm_t *vm, njs_valu if (calltype == NJS_FS_CALLBACK) { callback = njs_arg(args, nargs, njs_min(nargs - 1, 4)); if (!njs_value_is_function(callback)) { - njs_vm_error(vm, "\"callback\" must be a function"); + njs_vm_type_error(vm, "\"callback\" must be a function"); return NJS_ERROR; } @@ -2595,8 +2596,8 @@ njs_fs_write_file(njs_vm_t *vm, njs_valu } else if (!njs_value_is_undefined(options)) { if (!njs_value_is_object(options)) { - njs_vm_error(vm, "Unknown options type " - "(a string or object required)"); + njs_vm_type_error(vm, "Unknown options type " + "(a string or object required)"); return NJS_ERROR; } @@ -2781,7 +2782,7 @@ njs_fs_make_path(njs_vm_t *vm, char *pat } if (njs_slow_path((p - path) > NJS_MAX_PATH)) { - njs_vm_error(vm, "too large path"); + njs_vm_internal_error(vm, "too large path"); return NJS_ERROR; } @@ -3064,18 +3065,19 @@ njs_fs_path(njs_vm_t *vm, char storage[N } } else { - njs_vm_error(vm, "\"%s\" must be a string or Buffer", prop_name); + njs_vm_type_error(vm, "\"%s\" must be a string or Buffer", prop_name); return NULL; } if (njs_slow_path(str.length > NJS_MAX_PATH - 1)) { - njs_vm_error(vm, "\"%s\" is too long >= %d", prop_name, NJS_MAX_PATH); + njs_vm_internal_error(vm, "\"%s\" is too long >= %d", prop_name, + NJS_MAX_PATH); return NULL; } if (njs_slow_path(memchr(str.start, '\0', str.length) != 0)) { - njs_vm_error(vm, "\"%s\" must be a Buffer without null bytes", - prop_name); + njs_vm_type_error(vm, "\"%s\" must be a Buffer without null bytes", + prop_name); return NULL; } @@ -3110,7 +3112,7 @@ njs_fs_flags(njs_vm_t *vm, njs_value_t * } } - njs_vm_error(vm, "Unknown file open flags: \"%V\"", &flags); + njs_vm_type_error(vm, "Unknown file open flags: \"%V\"", &flags); return -1; } @@ -3301,7 +3303,7 @@ njs_fs_result(njs_vm_t *vm, njs_opaque_v return NJS_OK; default: - njs_vm_error(vm, "invalid calltype"); + njs_vm_internal_error(vm, "invalid calltype"); return NJS_ERROR; } @@ -3339,7 +3341,7 @@ njs_fs_dirent_constructor(njs_vm_t *vm, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval) { if (njs_slow_path(!njs_vm_constructor(vm))) { - njs_vm_error(vm, "the Dirent constructor must be called with new"); + njs_vm_type_error(vm, "the Dirent constructor must be called with new"); return NJS_ERROR; } @@ -3365,7 +3367,8 @@ njs_fs_dirent_test(njs_vm_t *vm, njs_val if (njs_slow_path(njs_value_is_number(type) && (njs_value_number(type) == NJS_DT_INVALID))) { - njs_vm_error(vm, "dentry type is not supported on this platform"); + njs_vm_internal_error(vm, "dentry type is not supported on this " + "platform"); return NJS_ERROR; } @@ -3603,7 +3606,7 @@ njs_fs_filehandle_close(njs_vm_t *vm, nj fh = njs_vm_external(vm, njs_fs_filehandle_proto_id, njs_argument(args, 0)); if (njs_slow_path(fh == NULL)) { - njs_vm_error(vm, "\"this\" is not a filehandle object"); + njs_vm_type_error(vm, "\"this\" is not a filehandle object"); return NJS_ERROR; } @@ -3629,7 +3632,7 @@ njs_fs_filehandle_value_of(njs_vm_t *vm, fh = njs_vm_external(vm, njs_fs_filehandle_proto_id, njs_argument(args, 0)); if (njs_slow_path(fh == NULL)) { - njs_vm_error(vm, "\"this\" is not a filehandle object"); + njs_vm_type_error(vm, "\"this\" is not a filehandle object"); return NJS_ERROR; } diff -r 09441c1c24ea -r aaab085e499f src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Wed Jun 21 16:17:42 2023 -0700 +++ b/src/test/njs_unit_test.c Wed Jun 21 16:29:45 2023 -0700 @@ -20043,32 +20043,32 @@ static njs_unit_test_t njs_fs_module_te { njs_str("var fs = require('fs');" "fs.readFile()"), - njs_str("Error: \"path\" must be a string or Buffer") }, + njs_str("TypeError: \"path\" must be a string or Buffer") }, { njs_str("var fs = require('fs');" "var path = Buffer.from('/broken'); path[3] = 0;" "fs.readFile(path)"), - njs_str("Error: \"path\" must be a Buffer without null bytes") }, + njs_str("TypeError: \"path\" must be a Buffer without null bytes") }, { njs_str("var fs = require('fs');" "fs.readFile('/njs_unknown_path')"), - njs_str("Error: \"callback\" must be a function") }, + njs_str("TypeError: \"callback\" must be a function") }, { njs_str("var fs = require('fs');" "fs.readFile('/njs_unknown_path', 'utf8')"), - njs_str("Error: \"callback\" must be a function") }, + njs_str("TypeError: \"callback\" must be a function") }, { njs_str("var fs = require('fs');" "fs.readFile('/njs_unknown_path', {flag:'xx'})"), - njs_str("Error: \"callback\" must be a function") }, + njs_str("TypeError: \"callback\" must be a function") }, { njs_str("var fs = require('fs');" "fs.readFile('/njs_unknown_path', {flag:'xx'}, 1)"), - njs_str("Error: \"callback\" must be a function") }, + njs_str("TypeError: \"callback\" must be a function") }, { njs_str("var fs = require('fs');" "fs.readFile('/njs_unknown_path', {flag:'xx'}, function () {})"), - njs_str("Error: Unknown file open flags: \"xx\"") }, + njs_str("TypeError: Unknown file open flags: \"xx\"") }, { njs_str("var fs = require('fs');" "fs.readFile('/njs_unknown_path', {encoding:'ascii'}, function () {})"), @@ -20082,15 +20082,15 @@ static njs_unit_test_t njs_fs_module_te { njs_str("var fs = require('fs');" "fs.readFileSync()"), - njs_str("Error: \"path\" must be a string or Buffer") }, + njs_str("TypeError: \"path\" must be a string or Buffer") }, { njs_str("var fs = require('fs');" "fs.readFileSync({})"), - njs_str("Error: \"path\" must be a string or Buffer") }, + njs_str("TypeError: \"path\" must be a string or Buffer") }, { njs_str("var fs = require('fs');" "fs.readFileSync('/njs_unknown_path', {flag:'xx'})"), - njs_str("Error: Unknown file open flags: \"xx\"") }, + njs_str("TypeError: Unknown file open flags: \"xx\"") }, { njs_str("var fs = require('fs');" "fs.readFileSync(Buffer.from('/njs_unknown_path'), {encoding:'ascii'})"), @@ -20102,38 +20102,38 @@ static njs_unit_test_t njs_fs_module_te { njs_str("var fs = require('fs');" "fs.readFileSync('/njs_unknown_path', true)"), - njs_str("Error: Unknown options type (a string or object required)") }, + njs_str("TypeError: Unknown options type (a string or object required)") }, /* require('fs').writeFile() */ { njs_str("var fs = require('fs');" "fs.writeFile()"), - njs_str("Error: \"path\" must be a string or Buffer") }, + njs_str("TypeError: \"path\" must be a string or Buffer") }, { njs_str("var fs = require('fs');" "fs.writeFile({}, '', function () {})"), - njs_str("Error: \"path\" must be a string or Buffer") }, + njs_str("TypeError: \"path\" must be a string or Buffer") }, { njs_str("var fs = require('fs');" "fs.writeFile('/njs_unknown_path')"), - njs_str("Error: \"callback\" must be a function") }, + njs_str("TypeError: \"callback\" must be a function") }, { njs_str("var fs = require('fs');" "fs.writeFile('/njs_unknown_path', '')"), - njs_str("Error: \"callback\" must be a function") }, + njs_str("TypeError: \"callback\" must be a function") }, { njs_str("var fs = require('fs');" "fs.writeFile('/njs_unknown_path', '', undefined)"), - njs_str("Error: \"callback\" must be a function") }, + njs_str("TypeError: \"callback\" must be a function") }, { njs_str("var fs = require('fs');" "fs.writeFile('/njs_unknown_path', '', 'utf8')"), - njs_str("Error: \"callback\" must be a function") }, + njs_str("TypeError: \"callback\" must be a function") }, { njs_str("var fs = require('fs');" "fs.writeFile('/njs_unknown_path', '', {flag:'xx'}, function () {})"), - njs_str("Error: Unknown file open flags: \"xx\"") }, + njs_str("TypeError: Unknown file open flags: \"xx\"") }, { njs_str("var fs = require('fs');" "fs.writeFile('/njs_unknown_path', '', {encoding:'ascii'}, function () {})"), @@ -20145,21 +20145,21 @@ static njs_unit_test_t njs_fs_module_te { njs_str("var fs = require('fs');" "fs.writeFile('/njs_unknown_path', '', true, function () {})"), - njs_str("Error: Unknown options type (a string or object required)") }, + njs_str("TypeError: Unknown options type (a string or object required)") }, /* require('fs').writeFileSync() */ { njs_str("var fs = require('fs');" "fs.writeFileSync()"), - njs_str("Error: \"path\" must be a string or Buffer") }, + njs_str("TypeError: \"path\" must be a string or Buffer") }, { njs_str("var fs = require('fs');" "fs.writeFileSync({}, '')"), - njs_str("Error: \"path\" must be a string or Buffer") }, + njs_str("TypeError: \"path\" must be a string or Buffer") }, { njs_str("var fs = require('fs');" "fs.writeFileSync('/njs_unknown_path', '', {flag:'xx'})"), - njs_str("Error: Unknown file open flags: \"xx\"") }, + njs_str("TypeError: Unknown file open flags: \"xx\"") }, { njs_str("var fs = require('fs');" "fs.writeFileSync('/njs_unknown_path', '', {encoding:'ascii'})"), @@ -20171,17 +20171,17 @@ static njs_unit_test_t njs_fs_module_te { njs_str("var fs = require('fs');" "fs.writeFileSync('/njs_unknown_path', '', true)"), - njs_str("Error: Unknown options type (a string or object required)") }, + njs_str("TypeError: Unknown options type (a string or object required)") }, /* require('fs').renameSync() */ { njs_str("var fs = require('fs');" "fs.renameSync()"), - njs_str("Error: \"oldPath\" must be a string or Buffer") }, + njs_str("TypeError: \"oldPath\" must be a string or Buffer") }, { njs_str("var fs = require('fs');" "fs.renameSync('/njs_unknown_path')"), - njs_str("Error: \"newPath\" must be a string or Buffer") }, + njs_str("TypeError: \"newPath\" must be a string or Buffer") }, { njs_str("var fs = require('fs');" "[undefined, null, false, NaN, Symbol(), {}, Object('/njs_unknown_path')]" @@ -20201,29 +20201,29 @@ static njs_unit_test_t njs_fs_module_te { njs_str("var fs = require('fs');" "fs.access()"), - njs_str("Error: \"path\" must be a string or Buffer") }, + njs_str("TypeError: \"path\" must be a string or Buffer") }, { njs_str("var fs = require('fs');" "fs.access('/njs_unknown_path')"), - njs_str("Error: \"callback\" must be a function") }, + njs_str("TypeError: \"callback\" must be a function") }, { njs_str("var fs = require('fs');" "fs.access('/njs_unknown_path', fs.constants.F_OK)"), - njs_str("Error: \"callback\" must be a function") }, + njs_str("TypeError: \"callback\" must be a function") }, { njs_str("var fs = require('fs');" "fs.access('/njs_unknown_path', 'fail', function () {})"), - njs_str("Error: \"mode\" must be a number") }, + njs_str("TypeError: \"mode\" must be a number") }, /* require('fs').accessSync() */ { njs_str("var fs = require('fs');" "fs.accessSync()"), - njs_str("Error: \"path\" must be a string or Buffer") }, + njs_str("TypeError: \"path\" must be a string or Buffer") }, { njs_str("var fs = require('fs');" "fs.accessSync('/njs_unknown_path', 'fail')"), - njs_str("Error: \"mode\" must be a number") }, + njs_str("TypeError: \"mode\" must be a number") }, { njs_str("var " "fs = require('fs')," @@ -20308,7 +20308,7 @@ static njs_unit_test_t njs_fs_module_te { njs_str("var fs = require('fs');" "fs.Dirent('file', 123)"), - njs_str("Error: the Dirent constructor must be called with new") }, + njs_str("TypeError: the Dirent constructor must be called with new") }, { njs_str("var fs = require('fs');" "var e = new fs.Dirent('file', 123); [e.name, e.type]"), @@ -22848,12 +22848,12 @@ static njs_unit_test_t njs_shared_test[ njs_str("37") }, { njs_str("var fs = require('fs'); fs.readFileSync()"), - njs_str("Error: \"path\" must be a string or Buffer\n" + njs_str("TypeError: \"path\" must be a string or Buffer\n" " at fs.readFileSync (native)\n" " at main (:1)\n") }, { njs_str("import fs from 'fs'; fs.readFileSync()"), - njs_str("Error: \"path\" must be a string or Buffer\n" + njs_str("TypeError: \"path\" must be a string or Buffer\n" " at fs.readFileSync (native)\n" " at main (:1)\n") }, diff -r 09441c1c24ea -r aaab085e499f test/fs/methods.t.js --- a/test/fs/methods.t.js Wed Jun 21 16:17:42 2023 -0700 +++ b/test/fs/methods.t.js Wed Jun 21 16:29:45 2023 -0700 @@ -898,7 +898,7 @@ let read_tests = () => [ content: "ABC", read: [ [0, 5], ], check: (err, params) => { - if (err.message.indexOf('is out of range') == -1) { + if (!(err instanceof RangeError)) { throw Error(`${err.message} unexpected exception`); } @@ -910,7 +910,7 @@ let read_tests = () => [ content: "ABC", read: [ [2, 3], ], check: (err, params) => { - if (err.message.indexOf('is out of range') == -1) { + if (!(err instanceof RangeError)) { throw Error(`${err.message} unexpected exception`); } @@ -1104,7 +1104,7 @@ let write_tests = () => [ args: ["@", 'w'], write: [ [Buffer.from("__ABC__"), 8] ], check: (err, params) => { - if (err.message.indexOf('is out of range') == -1) { + if (!(err instanceof RangeError)) { throw Error(`${err.message} unexpected exception`); } @@ -1116,7 +1116,7 @@ let write_tests = () => [ args: ["@", 'w'], write: [ [Buffer.from("__ABC__"), 7, 1] ], check: (err, params) => { - if (err.message.indexOf('is out of range') == -1) { + if (!(err instanceof RangeError)) { throw Error(`${err.message} unexpected exception`); } diff -r 09441c1c24ea -r aaab085e499f test/fs/promises_07.t.js --- a/test/fs/promises_07.t.js Wed Jun 21 16:17:42 2023 -0700 +++ b/test/fs/promises_07.t.js Wed Jun 21 16:29:45 2023 -0700 @@ -26,7 +26,7 @@ var match = (entry) => { return false; } } catch (e) { - if (e.message == 'dentry type is not supported on this platform') { + if (e instanceof InternalError) { return true; } From xeioex at nginx.com Thu Jun 22 22:40:04 2023 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 22 Jun 2023 22:40:04 +0000 Subject: [njs] Crypto: added back custom exception types using new public API. Message-ID: details: https://hg.nginx.org/njs/rev/11fc41439e9f branches: changeset: 2159:11fc41439e9f user: Dmitry Volyntsev date: Wed Jun 21 16:29:48 2023 -0700 description: Crypto: added back custom exception types using new public API. In b2cbf06ba017, when rewriting crypto module using public API all the exceptions types were squashed into a single Error type. This patch reintroduces the standard exception types back using new API. diffstat: external/njs_crypto_module.c | 22 +++++++++++----------- src/test/njs_unit_test.c | 30 +++++++++++++++--------------- 2 files changed, 26 insertions(+), 26 deletions(-) diffs (196 lines): diff -r aaab085e499f -r 11fc41439e9f external/njs_crypto_module.c --- a/external/njs_crypto_module.c Wed Jun 21 16:29:45 2023 -0700 +++ b/external/njs_crypto_module.c Wed Jun 21 16:29:48 2023 -0700 @@ -335,7 +335,7 @@ njs_hash_prototype_update(njs_vm_t *vm, if (!hmac) { dgst = njs_vm_external(vm, njs_crypto_hash_proto_id, this); if (njs_slow_path(dgst == NULL)) { - njs_vm_error(vm, "\"this\" is not a hash object"); + njs_vm_type_error(vm, "\"this\" is not a hash object"); return NJS_ERROR; } @@ -349,7 +349,7 @@ njs_hash_prototype_update(njs_vm_t *vm, } else { ctx = njs_vm_external(vm, njs_crypto_hmac_proto_id, this); if (njs_slow_path(ctx == NULL)) { - njs_vm_error(vm, "\"this\" is not a hmac object"); + njs_vm_type_error(vm, "\"this\" is not a hmac object"); return NJS_ERROR; } @@ -383,7 +383,7 @@ njs_hash_prototype_update(njs_vm_t *vm, } } else { - njs_vm_error(vm, "data is not a string or Buffer-like object"); + njs_vm_type_error(vm, "data is not a string or Buffer-like object"); return NJS_ERROR; } @@ -418,7 +418,7 @@ njs_hash_prototype_digest(njs_vm_t *vm, if (!hmac) { dgst = njs_vm_external(vm, njs_crypto_hash_proto_id, this); if (njs_slow_path(dgst == NULL)) { - njs_vm_error(vm, "\"this\" is not a hash object"); + njs_vm_type_error(vm, "\"this\" is not a hash object"); return NJS_ERROR; } @@ -431,7 +431,7 @@ njs_hash_prototype_digest(njs_vm_t *vm, } else { ctx = njs_vm_external(vm, njs_crypto_hmac_proto_id, this); if (njs_slow_path(ctx == NULL)) { - njs_vm_error(vm, "\"this\" is not a hmac object"); + njs_vm_type_error(vm, "\"this\" is not a hmac object"); return NJS_ERROR; } @@ -484,7 +484,7 @@ njs_hash_prototype_copy(njs_vm_t *vm, nj dgst = njs_vm_external(vm, njs_crypto_hash_proto_id, njs_argument(args, 0)); if (njs_slow_path(dgst == NULL)) { - njs_vm_error(vm, "\"this\" is not a hash object"); + njs_vm_type_error(vm, "\"this\" is not a hash object"); return NJS_ERROR; } @@ -547,7 +547,7 @@ njs_crypto_create_hmac(njs_vm_t *vm, njs } } else { - njs_vm_error(vm, "key is not a string or Buffer-like object"); + njs_vm_type_error(vm, "key is not a string or Buffer-like object"); return NJS_ERROR; } @@ -597,7 +597,7 @@ njs_crypto_algorithm(njs_vm_t *vm, njs_v njs_hash_alg_t *e; if (njs_slow_path(!njs_value_is_string(value))) { - njs_vm_error(vm, "algorithm must be a string"); + njs_vm_type_error(vm, "algorithm must be a string"); return NULL; } @@ -609,7 +609,7 @@ njs_crypto_algorithm(njs_vm_t *vm, njs_v } } - njs_vm_error(vm, "not supported algorithm: \"%V\"", &name); + njs_vm_type_error(vm, "not supported algorithm: \"%V\"", &name); return NULL; } @@ -623,7 +623,7 @@ njs_crypto_encoding(njs_vm_t *vm, njs_va if (njs_slow_path(!njs_value_is_string(value))) { if (!njs_value_is_undefined(value)) { - njs_vm_error(vm, "encoding must be a string"); + njs_vm_type_error(vm, "encoding must be a string"); return NULL; } @@ -638,7 +638,7 @@ njs_crypto_encoding(njs_vm_t *vm, njs_va } } - njs_vm_error(vm, "Unknown digest encoding: \"%V\"", &name); + njs_vm_type_error(vm, "Unknown digest encoding: \"%V\"", &name); return NULL; } diff -r aaab085e499f -r 11fc41439e9f src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Wed Jun 21 16:29:45 2023 -0700 +++ b/src/test/njs_unit_test.c Wed Jun 21 16:29:48 2023 -0700 @@ -20444,25 +20444,25 @@ static njs_unit_test_t njs_crypto_modul "'d9f5aeb06abebb3be3f38adec9a2e3b94228d52193be923eb4e24c9b56ee0930']]") }, { njs_str("var h = require('crypto').createHash()"), - njs_str("Error: algorithm must be a string") }, + njs_str("TypeError: algorithm must be a string") }, { njs_str("var h = require('crypto').createHash([])"), - njs_str("Error: algorithm must be a string") }, + njs_str("TypeError: algorithm must be a string") }, { njs_str("var h = require('crypto').createHash('sha512')"), - njs_str("Error: not supported algorithm: \"sha512\"") }, + njs_str("TypeError: not supported algorithm: \"sha512\"") }, { njs_str("var h = require('crypto').createHash('sha1');" "h.update()"), - njs_str("Error: data is not a string or Buffer-like object") }, + njs_str("TypeError: data is not a string or Buffer-like object") }, { njs_str("var h = require('crypto').createHash('sha1');" "h.update({})"), - njs_str("Error: data is not a string or Buffer-like object") }, + njs_str("TypeError: data is not a string or Buffer-like object") }, { njs_str("var h = require('crypto').createHash('sha1');" "h.update('A').digest('latin1')"), - njs_str("Error: Unknown digest encoding: \"latin1\"") }, + njs_str("TypeError: Unknown digest encoding: \"latin1\"") }, { njs_str("require('crypto').createHash('sha1').digest() instanceof Buffer"), njs_str("true") }, @@ -20562,16 +20562,16 @@ static njs_unit_test_t njs_crypto_modul njs_str("5647b6c429701ff512f0f18232b4507065d2376ca8899a816a0a6e721bf8ddcc") }, { njs_str("var h = require('crypto').createHmac()"), - njs_str("Error: algorithm must be a string") }, + njs_str("TypeError: algorithm must be a string") }, { njs_str("var h = require('crypto').createHmac([])"), - njs_str("Error: algorithm must be a string") }, + njs_str("TypeError: algorithm must be a string") }, { njs_str("var h = require('crypto').createHmac('sha512', '')"), - njs_str("Error: not supported algorithm: \"sha512\"") }, + njs_str("TypeError: not supported algorithm: \"sha512\"") }, { njs_str("var h = require('crypto').createHmac('sha1', [])"), - njs_str("Error: key is not a string or Buffer-like object") }, + njs_str("TypeError: key is not a string or Buffer-like object") }, { njs_str("var h = require('crypto').createHmac('sha1', 'secret key');" "h.update('A').digest('hex'); h.digest('hex')"), @@ -20586,7 +20586,7 @@ static njs_unit_test_t njs_crypto_modul { njs_str("var cr = require('crypto'); var h = cr.createHash('sha1');" "h.update.call(cr.createHmac('sha1', 's'), '')"), - njs_str("Error: \"this\" is not a hash object") }, + njs_str("TypeError: \"this\" is not a hash object") }, }; static njs_unit_test_t njs_querystring_module_test[] = @@ -23279,24 +23279,24 @@ static njs_unit_test_t njs_backtraces_t " at main (:1)\n") }, { njs_str("require('crypto').createHash('sha')"), - njs_str("Error: not supported algorithm: \"sha\"\n" + njs_str("TypeError: not supported algorithm: \"sha\"\n" " at crypto.createHash (native)\n" " at main (:1)\n") }, { njs_str("var h = require('crypto').createHash('sha1');" "h.update([])"), - njs_str("Error: data is not a string or Buffer-like object\n" + njs_str("TypeError: data is not a string or Buffer-like object\n" " at Hash.update (native)\n" " at main (:1)\n") }, { njs_str("require('crypto').createHmac('sha1', [])"), - njs_str("Error: key is not a string or Buffer-like object\n" + njs_str("TypeError: key is not a string or Buffer-like object\n" " at crypto.createHmac (native)\n" " at main (:1)\n") }, { njs_str("var h = require('crypto').createHmac('sha1', 'secret');" "h.update([])"), - njs_str("Error: data is not a string or Buffer-like object\n" + njs_str("TypeError: data is not a string or Buffer-like object\n" " at Hmac.update (native)\n" " at main (:1)\n") }, From xeioex at nginx.com Thu Jun 22 22:40:06 2023 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 22 Jun 2023 22:40:06 +0000 Subject: [njs] QueryString: added back custom exception types using new public API. Message-ID: details: https://hg.nginx.org/njs/rev/e9c41ee90ac2 branches: changeset: 2160:e9c41ee90ac2 user: Dmitry Volyntsev date: Wed Jun 21 16:29:51 2023 -0700 description: QueryString: added back custom exception types using new public API. In fd956d2a25a3, when rewriting querystring module using public API all the exceptions types were squashed into a single Error type. This patch reintroduces the standard exception types back using new API. diffstat: external/njs_query_string_module.c | 12 +++++++----- src/test/njs_unit_test.c | 8 ++++---- 2 files changed, 11 insertions(+), 9 deletions(-) diffs (83 lines): diff -r 11fc41439e9f -r e9c41ee90ac2 external/njs_query_string_module.c --- a/external/njs_query_string_module.c Wed Jun 21 16:29:48 2023 -0700 +++ b/external/njs_query_string_module.c Wed Jun 21 16:29:51 2023 -0700 @@ -422,7 +422,7 @@ njs_query_string_parse(njs_vm_t *vm, njs if (val != NULL) { if (!njs_value_is_valid_number(val)) { - njs_vm_error(vm, "is not a number"); + njs_vm_type_error(vm, "is not a number"); return NJS_ERROR; } @@ -437,7 +437,8 @@ njs_query_string_parse(njs_vm_t *vm, njs if (val != NULL) { if (njs_slow_path(!njs_value_is_function(val))) { - njs_vm_error(vm, "option decodeURIComponent is not a function"); + njs_vm_type_error(vm, "option decodeURIComponent is not " + "a function"); return NJS_ERROR; } @@ -449,7 +450,7 @@ njs_query_string_parse(njs_vm_t *vm, njs val = njs_vm_object_prop(vm, this, &njs_unescape_str, &value); if (val == NULL || !njs_value_is_function(val)) { - njs_vm_error(vm, "QueryString.unescape is not a function"); + njs_vm_type_error(vm, "QueryString.unescape is not a function"); return NJS_ERROR; } @@ -728,7 +729,8 @@ njs_query_string_stringify(njs_vm_t *vm, if (val != NULL) { if (njs_slow_path(!njs_value_is_function(val))) { - njs_vm_error(vm, "option encodeURIComponent is not a function"); + njs_vm_type_error(vm, "option encodeURIComponent is not " + "a function"); return NJS_ERROR; } @@ -740,7 +742,7 @@ njs_query_string_stringify(njs_vm_t *vm, val = njs_vm_object_prop(vm, this, &njs_escape_str, &value); if (val == NULL || !njs_value_is_function(val)) { - njs_vm_error(vm, "QueryString.escape is not a function"); + njs_vm_type_error(vm, "QueryString.escape is not a function"); return NJS_ERROR; } diff -r 11fc41439e9f -r e9c41ee90ac2 src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Wed Jun 21 16:29:48 2023 -0700 +++ b/src/test/njs_unit_test.c Wed Jun 21 16:29:51 2023 -0700 @@ -20723,12 +20723,12 @@ static njs_unit_test_t njs_querystring_ { njs_str("var qs = require('querystring');" "qs.parse('baz=fuz&muz=tax', null, null, {decodeURIComponent: 123});"), - njs_str("Error: option decodeURIComponent is not a function") }, + njs_str("TypeError: option decodeURIComponent is not a function") }, { njs_str("var qs = require('querystring');" "qs.unescape = 123;" "qs.parse('baz=fuz&muz=tax');"), - njs_str("Error: QueryString.unescape is not a function") }, + njs_str("TypeError: QueryString.unescape is not a function") }, { njs_str("var qs = require('querystring'); var out = [];" "qs.unescape = (key) => {out.push(key)};" @@ -20841,12 +20841,12 @@ static njs_unit_test_t njs_querystring_ { njs_str("var qs = require('querystring');" "qs.stringify({'baz': 'fuz', 'muz': 'tax'}, null, null, {encodeURIComponent: 123});" "out.join('; ')"), - njs_str("Error: option encodeURIComponent is not a function") }, + njs_str("TypeError: option encodeURIComponent is not a function") }, { njs_str("var qs = require('querystring');" "qs.escape = 123;" "qs.stringify({'baz': 'fuz', 'muz': 'tax'})"), - njs_str("Error: QueryString.escape is not a function") }, + njs_str("TypeError: QueryString.escape is not a function") }, { njs_str("var qs = require('querystring'); var out = [];" "qs.escape = (key) => {out.push(key)};" From xeioex at nginx.com Thu Jun 22 22:40:08 2023 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 22 Jun 2023 22:40:08 +0000 Subject: [njs] WebCrypto: added back custom exception types using new public API. Message-ID: details: https://hg.nginx.org/njs/rev/86f99fb4e9bd branches: changeset: 2161:86f99fb4e9bd user: Dmitry Volyntsev date: Wed Jun 21 16:30:00 2023 -0700 description: WebCrypto: added back custom exception types using new public API. In f1432043a6a4, when rewriting webcrypto module using public API all the exceptions types were squashed into a single Error type. This patch reintroduces the standard exception types back using new API. diffstat: external/njs_webcrypto_module.c | 226 ++++++++++++++++++++------------------- test/harness/runTsuite.js | 2 +- 2 files changed, 118 insertions(+), 110 deletions(-) diffs (761 lines): diff -r e9c41ee90ac2 -r 86f99fb4e9bd external/njs_webcrypto_module.c --- a/external/njs_webcrypto_module.c Wed Jun 21 16:29:51 2023 -0700 +++ b/external/njs_webcrypto_module.c Wed Jun 21 16:30:00 2023 -0700 @@ -710,22 +710,22 @@ njs_ext_cipher(njs_vm_t *vm, njs_value_t key = njs_vm_external(vm, njs_webcrypto_crypto_key_proto_id, njs_arg(args, nargs, 2)); if (njs_slow_path(key == NULL)) { - njs_vm_error(vm, "\"key\" is not a CryptoKey object"); + njs_vm_type_error(vm, "\"key\" is not a CryptoKey object"); goto fail; } mask = encrypt ? NJS_KEY_USAGE_ENCRYPT : NJS_KEY_USAGE_DECRYPT; if (njs_slow_path(!(key->usage & mask))) { - njs_vm_error(vm, "provide key does not support %s operation", - encrypt ? "encrypt" : "decrypt"); + njs_vm_type_error(vm, "provide key does not support %s operation", + encrypt ? "encrypt" : "decrypt"); goto fail; } if (njs_slow_path(key->alg != alg)) { - njs_vm_error(vm, "cannot %s using \"%V\" with \"%V\" key", - encrypt ? "encrypt" : "decrypt", - njs_algorithm_string(key->alg), - njs_algorithm_string(alg)); + njs_vm_type_error(vm, "cannot %s using \"%V\" with \"%V\" key", + encrypt ? "encrypt" : "decrypt", + njs_algorithm_string(key->alg), + njs_algorithm_string(alg)); goto fail; } @@ -869,13 +869,13 @@ njs_cipher_aes_gcm(njs_vm_t *vm, njs_str break; default: - njs_vm_error(vm, "AES-GCM Invalid key length"); + njs_vm_type_error(vm, "AES-GCM Invalid key length"); return NJS_ERROR; } value = njs_vm_object_prop(vm, options, &string_iv, &lvalue); if (value == NULL) { - njs_vm_error(vm, "AES-GCM algorithm.iv is not provided"); + njs_vm_type_error(vm, "AES-GCM algorithm.iv is not provided"); return NJS_ERROR; } @@ -902,14 +902,14 @@ njs_cipher_aes_gcm(njs_vm_t *vm, njs_str && taglen != 120 && taglen != 128)) { - njs_vm_error(vm, "AES-GCM Invalid tagLength"); + njs_vm_type_error(vm, "AES-GCM Invalid tagLength"); return NJS_ERROR; } taglen /= 8; if (njs_slow_path(!encrypt && (data->length < (size_t) taglen))) { - njs_vm_error(vm, "AES-GCM data is too short"); + njs_vm_type_error(vm, "AES-GCM data is too short"); return NJS_ERROR; } @@ -1160,13 +1160,13 @@ njs_cipher_aes_ctr(njs_vm_t *vm, njs_str break; default: - njs_vm_error(vm, "AES-CTR Invalid key length"); + njs_vm_type_error(vm, "AES-CTR Invalid key length"); return NJS_ERROR; } value = njs_vm_object_prop(vm, options, &string_counter, &lvalue); if (value == NULL) { - njs_vm_error(vm, "AES-CTR algorithm.counter is not provided"); + njs_vm_type_error(vm, "AES-CTR algorithm.counter is not provided"); return NJS_ERROR; } @@ -1176,13 +1176,14 @@ njs_cipher_aes_ctr(njs_vm_t *vm, njs_str } if (njs_slow_path(iv.length != 16)) { - njs_vm_error(vm, "AES-CTR algorithm.counter must be 16 bytes long"); + njs_vm_type_error(vm, "AES-CTR algorithm.counter must be 16 bytes " + "long"); return NJS_ERROR; } value = njs_vm_object_prop(vm, options, &string_length, &lvalue); if (value == NULL) { - njs_vm_error(vm, "AES-CTR algorithm.length is not provided"); + njs_vm_type_error(vm, "AES-CTR algorithm.length is not provided"); return NJS_ERROR; } @@ -1192,7 +1193,8 @@ njs_cipher_aes_ctr(njs_vm_t *vm, njs_str } if (njs_slow_path(length == 0 || length > 128)) { - njs_vm_error(vm, "AES-CTR algorithm.length must be between 1 and 128"); + njs_vm_type_error(vm, "AES-CTR algorithm.length must be between " + "1 and 128"); return NJS_ERROR; } @@ -1235,7 +1237,7 @@ njs_cipher_aes_ctr(njs_vm_t *vm, njs_str ret = BN_cmp(blocks, total); if (njs_slow_path(ret > 0)) { - njs_vm_error(vm, "AES-CTR repeated counter"); + njs_vm_type_error(vm, "AES-CTR repeated counter"); ret = NJS_ERROR; goto fail; } @@ -1357,13 +1359,13 @@ njs_cipher_aes_cbc(njs_vm_t *vm, njs_str break; default: - njs_vm_error(vm, "AES-CBC Invalid key length"); + njs_vm_type_error(vm, "AES-CBC Invalid key length"); return NJS_ERROR; } value = njs_vm_object_prop(vm, options, &string_iv, &lvalue); if (value == NULL) { - njs_vm_error(vm, "AES-CBC algorithm.iv is not provided"); + njs_vm_type_error(vm, "AES-CBC algorithm.iv is not provided"); return NJS_ERROR; } @@ -1373,7 +1375,7 @@ njs_cipher_aes_cbc(njs_vm_t *vm, njs_str } if (njs_slow_path(iv.length != 16)) { - njs_vm_error(vm, "AES-CBC algorithm.iv must be 16 bytes long"); + njs_vm_type_error(vm, "AES-CBC algorithm.iv must be 16 bytes long"); return NJS_ERROR; } @@ -1465,22 +1467,22 @@ njs_ext_derive(njs_vm_t *vm, njs_value_t key = njs_vm_external(vm, njs_webcrypto_crypto_key_proto_id, njs_arg(args, nargs, 2)); if (njs_slow_path(key == NULL)) { - njs_vm_error(vm, "\"baseKey\" is not a CryptoKey object"); + njs_vm_type_error(vm, "\"baseKey\" is not a CryptoKey object"); goto fail; } mask = derive_key ? NJS_KEY_USAGE_DERIVE_KEY : NJS_KEY_USAGE_DERIVE_BITS; if (njs_slow_path(!(key->usage & mask))) { - njs_vm_error(vm, "provide key does not support \"%s\" operation", - derive_key ? "deriveKey" : "deriveBits"); + njs_vm_type_error(vm, "provide key does not support \"%s\" operation", + derive_key ? "deriveKey" : "deriveBits"); goto fail; } if (njs_slow_path(key->alg != alg)) { - njs_vm_error(vm, "cannot derive %s using \"%V\" with \"%V\" key", - derive_key ? "key" : "bits", - njs_algorithm_string(key->alg), - njs_algorithm_string(alg)); + njs_vm_type_error(vm, "cannot derive %s using \"%V\" with \"%V\" key", + derive_key ? "key" : "bits", + njs_algorithm_string(key->alg), + njs_algorithm_string(alg)); goto fail; } @@ -1494,7 +1496,7 @@ njs_ext_derive(njs_vm_t *vm, njs_value_t value = njs_vm_object_prop(vm, dobject, &string_length, &lvalue); if (value == NULL) { - njs_vm_error(vm, "derivedKeyAlgorithm.length is not provided"); + njs_vm_type_error(vm, "derivedKeyAlgorithm.length is not provided"); goto fail; } @@ -1518,16 +1520,16 @@ njs_ext_derive(njs_vm_t *vm, njs_value_t case NJS_ALGORITHM_AES_CBC: if (length != 16 && length != 32) { - njs_vm_error(vm, "deriveKey \"%V\" length must be 128 or 256", - njs_algorithm_string(dalg)); + njs_vm_type_error(vm, "deriveKey \"%V\" length must be " + "128 or 256", njs_algorithm_string(dalg)); goto fail; } break; default: - njs_vm_error(vm, "not implemented deriveKey: \"%V\"", - njs_algorithm_string(dalg)); + njs_vm_internal_error(vm, "not implemented deriveKey: \"%V\"", + njs_algorithm_string(dalg)); goto fail; } @@ -1537,8 +1539,8 @@ njs_ext_derive(njs_vm_t *vm, njs_value_t } if (njs_slow_path(usage & ~dalg->usage)) { - njs_vm_error(vm, "unsupported key usage for \"%V\" key", - njs_algorithm_string(alg)); + njs_vm_type_error(vm, "unsupported key usage for \"%V\" key", + njs_algorithm_string(alg)); goto fail; } @@ -1568,7 +1570,7 @@ njs_ext_derive(njs_vm_t *vm, njs_value_t value = njs_vm_object_prop(vm, aobject, &string_salt, &lvalue); if (value == NULL) { - njs_vm_error(vm, "PBKDF2 algorithm.salt is not provided"); + njs_vm_type_error(vm, "PBKDF2 algorithm.salt is not provided"); goto fail; } @@ -1578,14 +1580,15 @@ njs_ext_derive(njs_vm_t *vm, njs_value_t } if (njs_slow_path(salt.length < 16)) { - njs_vm_error(vm, "PBKDF2 algorithm.salt must be " - "at least 16 bytes long"); + njs_vm_type_error(vm, "PBKDF2 algorithm.salt must be " + "at least 16 bytes long"); goto fail; } value = njs_vm_object_prop(vm, aobject, &string_iterations, &lvalue); if (value == NULL) { - njs_vm_error(vm, "PBKDF2 algorithm.iterations is not provided"); + njs_vm_type_error(vm, "PBKDF2 algorithm.iterations is not " + "provided"); goto fail; } @@ -1614,7 +1617,7 @@ njs_ext_derive(njs_vm_t *vm, njs_value_t value = njs_vm_object_prop(vm, aobject, &string_salt, &lvalue); if (value == NULL) { - njs_vm_error(vm, "HKDF algorithm.salt is not provided"); + njs_vm_type_error(vm, "HKDF algorithm.salt is not provided"); goto fail; } @@ -1625,7 +1628,7 @@ njs_ext_derive(njs_vm_t *vm, njs_value_t value = njs_vm_object_prop(vm, aobject, &string_info, &lvalue); if (value == NULL) { - njs_vm_error(vm, "HKDF algorithm.info is not provided"); + njs_vm_type_error(vm, "HKDF algorithm.info is not provided"); goto fail; } @@ -1698,8 +1701,8 @@ free: case NJS_ALGORITHM_ECDH: default: - njs_vm_error(vm, "not implemented deriveKey " - "algorithm: \"%V\"", njs_algorithm_string(alg)); + njs_vm_internal_error(vm, "not implemented deriveKey " + "algorithm: \"%V\"", njs_algorithm_string(alg)); goto fail; } @@ -1975,7 +1978,7 @@ njs_export_jwk_ec(njs_vm_t *vm, njs_webc cname->start, cname->length); if (cname->length == 0) { - njs_vm_error(vm, "Unsupported JWK EC curve: %s", OBJ_nid2sn(nid)); + njs_vm_type_error(vm, "Unsupported JWK EC curve: %s", OBJ_nid2sn(nid)); goto fail; } @@ -2049,8 +2052,8 @@ njs_export_raw_ec(njs_vm_t *vm, njs_webc njs_assert(key->u.a.pkey != NULL); if (key->u.a.privat) { - njs_vm_error(vm, "private key of \"%V\" cannot be exported " - "in \"raw\" format", njs_algorithm_string(key->alg)); + njs_vm_type_error(vm, "private key of \"%V\" cannot be exported " + "in \"raw\" format", njs_algorithm_string(key->alg)); return NJS_ERROR; } @@ -2111,7 +2114,7 @@ njs_export_jwk_asymmetric(njs_vm_t *vm, break; default: - njs_vm_error(vm, "provided key cannot be exported as JWK"); + njs_vm_type_error(vm, "provided key cannot be exported as JWK"); return NJS_ERROR; } @@ -2235,19 +2238,19 @@ njs_ext_export_key(njs_vm_t *vm, njs_val key = njs_vm_external(vm, njs_webcrypto_crypto_key_proto_id, njs_arg(args, nargs, 2)); if (njs_slow_path(key == NULL)) { - njs_vm_error(vm, "\"key\" is not a CryptoKey object"); + njs_vm_type_error(vm, "\"key\" is not a CryptoKey object"); goto fail; } if (njs_slow_path(!(fmt & key->alg->fmt))) { - njs_vm_error(vm, "unsupported key fmt \"%V\" for \"%V\" key", - njs_format_string(fmt), - njs_algorithm_string(key->alg)); + njs_vm_type_error(vm, "unsupported key fmt \"%V\" for \"%V\" key", + njs_format_string(fmt), + njs_algorithm_string(key->alg)); goto fail; } if (njs_slow_path(!key->extractable)) { - njs_vm_error(vm, "provided key cannot be extracted"); + njs_vm_type_error(vm, "provided key cannot be extracted"); goto fail; } @@ -2284,8 +2287,8 @@ njs_ext_export_key(njs_vm_t *vm, njs_val case NJS_KEY_FORMAT_PKCS8: if (!key->u.a.privat) { - njs_vm_error(vm, "public key of \"%V\" cannot be exported " - "as PKCS8", njs_algorithm_string(key->alg)); + njs_vm_type_error(vm, "public key of \"%V\" cannot be exported " + "as PKCS8", njs_algorithm_string(key->alg)); goto fail; } @@ -2327,8 +2330,8 @@ njs_ext_export_key(njs_vm_t *vm, njs_val case NJS_KEY_FORMAT_SPKI: if (key->u.a.privat) { - njs_vm_error(vm, "private key of \"%V\" cannot be exported " - "as SPKI", njs_algorithm_string(key->alg)); + njs_vm_type_error(vm, "private key of \"%V\" cannot be exported " + "as SPKI", njs_algorithm_string(key->alg)); goto fail; } @@ -2426,8 +2429,8 @@ njs_ext_generate_key(njs_vm_t *vm, njs_v } if (njs_slow_path(usage & ~alg->usage)) { - njs_vm_error(vm, "unsupported key usage for \"%V\" key", - njs_algorithm_string(alg)); + njs_vm_type_error(vm, "unsupported key usage for \"%V\" key", + njs_algorithm_string(alg)); goto fail; } @@ -2446,7 +2449,7 @@ njs_ext_generate_key(njs_vm_t *vm, njs_v } if (!njs_value_is_number(val)) { - njs_vm_error(vm, "\"modulusLength\" is not a number"); + njs_vm_type_error(vm, "\"modulusLength\" is not a number"); goto fail; } @@ -2630,8 +2633,9 @@ njs_ext_generate_key(njs_vm_t *vm, njs_v && key->u.s.raw.length != 24 && key->u.s.raw.length != 32) { - njs_vm_error(vm, "length for \"%V\" key should be one of " - "128, 192, 256", njs_algorithm_string(alg)); + njs_vm_type_error(vm, "length for \"%V\" key should be " + "one of 128, 192, 256", + njs_algorithm_string(alg)); goto fail; } } @@ -2658,8 +2662,8 @@ njs_ext_generate_key(njs_vm_t *vm, njs_v break; default: - njs_vm_error(vm, "not implemented generateKey" - "algorithm: \"%V\"", njs_algorithm_string(alg)); + njs_vm_internal_error(vm, "not implemented generateKey" + "algorithm: \"%V\"", njs_algorithm_string(alg)); return NJS_ERROR; } @@ -2736,7 +2740,7 @@ njs_import_jwk_rsa(njs_vm_t *vm, njs_val && !njs_value_is_string(njs_value_arg(&d)))) { fail0: - njs_vm_error(vm, "Invalid JWK RSA key"); + njs_vm_type_error(vm, "Invalid JWK RSA key"); return NULL; } @@ -2750,7 +2754,7 @@ fail0: } if ((key->usage & usage) != key->usage) { - njs_vm_error(vm, "Key operations and usage mismatch"); + njs_vm_type_error(vm, "Key operations and usage mismatch"); return NULL; } } @@ -2778,7 +2782,7 @@ fail0: && !njs_value_is_undefined(val) && !njs_value_bool(val)) { - njs_vm_error(vm, "JWK RSA is not extractable"); + njs_vm_type_error(vm, "JWK RSA is not extractable"); return NULL; } } @@ -2844,7 +2848,7 @@ fail0: || !njs_value_is_string(njs_value_arg(&qi))) { fail1: - njs_vm_error(vm, "Invalid JWK RSA key"); + njs_vm_type_error(vm, "Invalid JWK RSA key"); goto fail; } @@ -3029,7 +3033,7 @@ njs_import_jwk_ec(njs_vm_t *vm, njs_valu && !njs_value_is_string(njs_value_arg(&d)))) { fail0: - njs_vm_error(vm, "Invalid JWK EC key"); + njs_vm_type_error(vm, "Invalid JWK EC key"); return NULL; } @@ -3043,7 +3047,7 @@ fail0: } if ((key->usage & usage) != key->usage) { - njs_vm_error(vm, "Key operations and usage mismatch"); + njs_vm_type_error(vm, "Key operations and usage mismatch"); return NULL; } } @@ -3054,7 +3058,7 @@ fail0: && !njs_value_is_undefined(val) && !njs_value_bool(val)) { - njs_vm_error(vm, "JWK EC is not extractable"); + njs_vm_type_error(vm, "JWK EC is not extractable"); return NULL; } } @@ -3074,7 +3078,7 @@ fail0: } if (curve != key->u.a.curve) { - njs_vm_error(vm, "JWK EC curve mismatch"); + njs_vm_type_error(vm, "JWK EC curve mismatch"); return NULL; } @@ -3185,7 +3189,7 @@ njs_import_jwk_oct(njs_vm_t *vm, njs_val val = njs_vm_object_prop(vm, jwk, &string_k, &value); if (njs_slow_path(val == NULL || !njs_value_is_string(val))) { - njs_vm_error(vm, "Invalid JWK oct key"); + njs_vm_type_error(vm, "Invalid JWK oct key"); return NJS_ERROR; } @@ -3228,7 +3232,8 @@ njs_import_jwk_oct(njs_vm_t *vm, njs_val } } - njs_vm_error(vm, "unexpected \"alg\" value \"%V\" for JWK key", &alg); + njs_vm_type_error(vm, "unexpected \"alg\" value \"%V\" for JWK key", + &alg); return NJS_ERROR; } @@ -3236,8 +3241,8 @@ done: if (key->alg->type != NJS_ALGORITHM_HMAC) { if (key->u.s.raw.length != size) { - njs_vm_error(vm, "key size and \"alg\" value \"%V\" mismatch", - &alg); + njs_vm_type_error(vm, "key size and \"alg\" value \"%V\" mismatch", + &alg); return NJS_ERROR; } } @@ -3250,7 +3255,7 @@ done: } if ((key->usage & usage) != key->usage) { - njs_vm_error(vm, "Key operations and usage mismatch"); + njs_vm_type_error(vm, "Key operations and usage mismatch"); return NJS_ERROR; } } @@ -3261,7 +3266,7 @@ done: && !njs_value_is_undefined(val) && !njs_value_bool(val)) { - njs_vm_error(vm, "JWK oct is not extractable"); + njs_vm_type_error(vm, "JWK oct is not extractable"); return NJS_ERROR; } } @@ -3314,9 +3319,9 @@ njs_ext_import_key(njs_vm_t *vm, njs_val } if (njs_slow_path(!(fmt & alg->fmt))) { - njs_vm_error(vm, "unsupported key fmt \"%V\" for \"%V\" key", - njs_format_string(fmt), - njs_algorithm_string(alg)); + njs_vm_type_error(vm, "unsupported key fmt \"%V\" for \"%V\" key", + njs_format_string(fmt), + njs_algorithm_string(alg)); goto fail; } @@ -3326,8 +3331,8 @@ njs_ext_import_key(njs_vm_t *vm, njs_val } if (njs_slow_path(usage & ~alg->usage)) { - njs_vm_error(vm, "unsupported key usage for \"%V\" key", - njs_algorithm_string(alg)); + njs_vm_type_error(vm, "unsupported key usage for \"%V\" key", + njs_algorithm_string(alg)); goto fail; } @@ -3398,7 +3403,8 @@ njs_ext_import_key(njs_vm_t *vm, njs_val case NJS_KEY_FORMAT_JWK: jwk = njs_arg(args, nargs, 2); if (!njs_value_is_object(jwk)) { - njs_vm_error(vm, "invalid JWK key data: object value expected"); + njs_vm_type_error(vm, "invalid JWK key data: object value " + "expected"); goto fail; } @@ -3436,7 +3442,7 @@ njs_ext_import_key(njs_vm_t *vm, njs_val } } else { - njs_vm_error(vm, "invalid JWK key type: %V", &kty); + njs_vm_type_error(vm, "invalid JWK key type: %V", &kty); goto fail; } @@ -3475,7 +3481,7 @@ njs_ext_import_key(njs_vm_t *vm, njs_val } if (key->hash != NJS_HASH_UNSET && key->hash != hash) { - njs_vm_error(vm, "RSA JWK hash mismatch"); + njs_vm_type_error(vm, "RSA JWK hash mismatch"); goto fail; } @@ -3490,8 +3496,8 @@ njs_ext_import_key(njs_vm_t *vm, njs_val } if (key->usage & mask) { - njs_vm_error(vm, "key usage mismatch for \"%V\" key", - njs_algorithm_string(alg)); + njs_vm_type_error(vm, "key usage mismatch for \"%V\" key", + njs_algorithm_string(alg)); goto fail; } @@ -3550,8 +3556,8 @@ njs_ext_import_key(njs_vm_t *vm, njs_val mask = key->u.a.privat ? ~NJS_KEY_USAGE_SIGN : ~NJS_KEY_USAGE_VERIFY; if (key->usage & mask) { - njs_vm_error(vm, "key usage mismatch for \"%V\" key", - njs_algorithm_string(alg)); + njs_vm_type_error(vm, "key usage mismatch for \"%V\" key", + njs_algorithm_string(alg)); goto fail; } @@ -3577,7 +3583,7 @@ njs_ext_import_key(njs_vm_t *vm, njs_val } if (key->hash != NJS_HASH_UNSET && key->hash != hash) { - njs_vm_error(vm, "HMAC JWK hash mismatch"); + njs_vm_type_error(vm, "HMAC JWK hash mismatch"); goto fail; } } @@ -3595,7 +3601,7 @@ njs_ext_import_key(njs_vm_t *vm, njs_val break; default: - njs_vm_error(vm, "AES Invalid key length"); + njs_vm_type_error(vm, "AES Invalid key length"); goto fail; } @@ -3656,7 +3662,8 @@ njs_set_rsa_padding(njs_vm_t *vm, njs_va if (padding == RSA_PKCS1_PSS_PADDING) { value = njs_vm_object_prop(vm, options, &string_saltl, &lvalue); if (njs_slow_path(value == NULL)) { - njs_vm_error(vm, "RSA-PSS algorithm.saltLength is not provided"); + njs_vm_type_error(vm, "RSA-PSS algorithm.saltLength is not " + "provided"); return NJS_ERROR; } @@ -3887,21 +3894,22 @@ njs_ext_sign(njs_vm_t *vm, njs_value_t * key = njs_vm_external(vm, njs_webcrypto_crypto_key_proto_id, njs_arg(args, nargs, 2)); if (njs_slow_path(key == NULL)) { - njs_vm_error(vm, "\"key\" is not a CryptoKey object"); + njs_vm_type_error(vm, "\"key\" is not a CryptoKey object"); goto fail; } mask = verify ? NJS_KEY_USAGE_VERIFY : NJS_KEY_USAGE_SIGN; if (njs_slow_path(!(key->usage & mask))) { - njs_vm_error(vm, "provide key does not support \"sign\" operation"); + njs_vm_type_error(vm, "provide key does not support \"sign\" " + "operation"); goto fail; } if (njs_slow_path(key->alg != alg)) { - njs_vm_error(vm, "cannot %s using \"%V\" with \"%V\" key", - verify ? "verify" : "sign", - njs_algorithm_string(key->alg), - njs_algorithm_string(alg)); + njs_vm_type_error(vm, "cannot %s using \"%V\" with \"%V\" key", + verify ? "verify" : "sign", + njs_algorithm_string(key->alg), + njs_algorithm_string(alg)); goto fail; } @@ -4106,7 +4114,7 @@ static njs_int_t njs_ext_unwrap_key(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval) { - njs_vm_error(vm, "\"unwrapKey\" not implemented"); + njs_vm_internal_error(vm, "\"unwrapKey\" not implemented"); return NJS_ERROR; } @@ -4115,7 +4123,7 @@ static njs_int_t njs_ext_wrap_key(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval) { - njs_vm_error(vm, "\"wrapKey\" not implemented"); + njs_vm_internal_error(vm, "\"wrapKey\" not implemented"); return NJS_ERROR; } @@ -4355,7 +4363,7 @@ njs_ext_get_random_values(njs_vm_t *vm, } if (njs_slow_path(fill.length > 65536)) { - njs_vm_error(vm, "requested length exceeds 65536 bytes"); + njs_vm_type_error(vm, "requested length exceeds 65536 bytes"); return NJS_ERROR; } @@ -4432,7 +4440,7 @@ njs_key_format(njs_vm_t *vm, njs_value_t } } - njs_vm_error(vm, "unknown key format: \"%V\"", &format); + njs_vm_type_error(vm, "unknown key format: \"%V\"", &format); return NJS_KEY_FORMAT_UNKNOWN; } @@ -4480,7 +4488,7 @@ njs_key_usage_array_handler(njs_vm_t *vm } } - njs_vm_error(vm, "unknown key usage: \"%V\"", &u); + njs_vm_type_error(vm, "unknown key usage: \"%V\"", &u); return NJS_ERROR; } @@ -4495,7 +4503,7 @@ njs_key_usage(njs_vm_t *vm, njs_value_t njs_iterator_args_t args; if (!njs_value_is_array(value)) { - njs_vm_error(vm, "\"keyUsages\" argument must be an Array"); + njs_vm_type_error(vm, "\"keyUsages\" argument must be an Array"); return NJS_ERROR; } @@ -4560,7 +4568,7 @@ njs_key_algorithm(njs_vm_t *vm, njs_valu if (njs_value_is_object(options)) { val = njs_vm_object_prop(vm, options, &string_name, &name); if (njs_slow_path(val == NULL)) { - njs_vm_error(vm, "algorithm name is not provided"); + njs_vm_type_error(vm, "algorithm name is not provided"); return NULL; } @@ -4579,7 +4587,7 @@ njs_key_algorithm(njs_vm_t *vm, njs_valu if (njs_strstr_case_eq(&a, &e->name)) { alg = (njs_webcrypto_algorithm_t *) e->value; if (alg->usage & NJS_KEY_USAGE_UNSUPPORTED) { - njs_vm_error(vm, "unsupported algorithm: \"%V\"", &a); + njs_vm_type_error(vm, "unsupported algorithm: \"%V\"", &a); return NULL; } @@ -4587,7 +4595,7 @@ njs_key_algorithm(njs_vm_t *vm, njs_valu } } - njs_vm_error(vm, "unknown algorithm name: \"%V\"", &a); + njs_vm_type_error(vm, "unknown algorithm name: \"%V\"", &a); return NULL; } @@ -4644,7 +4652,7 @@ njs_algorithm_hash(njs_vm_t *vm, njs_val } } - njs_vm_error(vm, "unknown hash name: \"%V\"", &name); + njs_vm_type_error(vm, "unknown hash name: \"%V\"", &name); return NJS_ERROR; } @@ -4719,7 +4727,7 @@ njs_algorithm_curve(njs_vm_t *vm, njs_va } } - njs_vm_error(vm, "unknown namedCurve: \"%V\"", &name); + njs_vm_type_error(vm, "unknown namedCurve: \"%V\"", &name); return NJS_ERROR; } @@ -4801,7 +4809,7 @@ njs_webcrypto_result(njs_vm_t *vm, njs_o error: - njs_vm_error(vm, "internal error"); + njs_vm_internal_error(vm, "cannot make webcrypto result"); return NJS_ERROR; } diff -r e9c41ee90ac2 -r 86f99fb4e9bd test/harness/runTsuite.js --- a/test/harness/runTsuite.js Wed Jun 21 16:29:51 2023 -0700 +++ b/test/harness/runTsuite.js Wed Jun 21 16:30:00 2023 -0700 @@ -13,7 +13,7 @@ async function run(tlist) { } if (r.status == "rejected" && t[i].optional) { - return r.reason.toString().startsWith("Error: not implemented"); + return r.reason.toString().startsWith("InternalError: not implemented"); } return false; From xeioex at nginx.com Thu Jun 22 22:40:10 2023 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 22 Jun 2023 22:40:10 +0000 Subject: [njs] Zlib: replaced Error with more suitable exception where approriate. Message-ID: details: https://hg.nginx.org/njs/rev/f324807389b4 branches: changeset: 2162:f324807389b4 user: Dmitry Volyntsev date: Wed Jun 21 16:30:12 2023 -0700 description: Zlib: replaced Error with more suitable exception where approriate. diffstat: external/njs_zlib_module.c | 41 +++++++++++++++++++++++------------------ 1 files changed, 23 insertions(+), 18 deletions(-) diffs (147 lines): diff -r 86f99fb4e9bd -r f324807389b4 external/njs_zlib_module.c --- a/external/njs_zlib_module.c Wed Jun 21 16:30:00 2023 -0700 +++ b/external/njs_zlib_module.c Wed Jun 21 16:30:12 2023 -0700 @@ -222,7 +222,7 @@ njs_zlib_ext_deflate(njs_vm_t *vm, njs_v chunk_size = njs_value_number(value); if (njs_slow_path(chunk_size < 64)) { - njs_vm_error(vm, "chunkSize must be >= 64"); + njs_vm_range_error(vm, "chunkSize must be >= 64"); return NJS_ERROR; } } @@ -234,8 +234,8 @@ njs_zlib_ext_deflate(njs_vm_t *vm, njs_v if (njs_slow_path(level < Z_DEFAULT_COMPRESSION || level > Z_BEST_COMPRESSION)) { - njs_vm_error(vm, "level must be in the range %d..%d", - Z_DEFAULT_COMPRESSION, Z_BEST_COMPRESSION); + njs_vm_range_error(vm, "level must be in the range %d..%d", + Z_DEFAULT_COMPRESSION, Z_BEST_COMPRESSION); return NJS_ERROR; } } @@ -246,13 +246,15 @@ njs_zlib_ext_deflate(njs_vm_t *vm, njs_v if (raw) { if (njs_slow_path(window_bits < -15 || window_bits > -9)) { - njs_vm_error(vm, "windowBits must be in the range -15..-9"); + njs_vm_range_error(vm, "windowBits must be in the range " + "-15..-9"); return NJS_ERROR; } } else { if (njs_slow_path(window_bits < 9 || window_bits > 15)) { - njs_vm_error(vm, "windowBits must be in the range 9..15"); + njs_vm_range_error(vm, "windowBits must be in the range " + "9..15"); return NJS_ERROR; } } @@ -263,7 +265,7 @@ njs_zlib_ext_deflate(njs_vm_t *vm, njs_v mem_level = njs_value_number(value); if (njs_slow_path(mem_level < 1 || mem_level > 9)) { - njs_vm_error(vm, "memLevel must be in the range 0..9"); + njs_vm_range_error(vm, "memLevel must be in the range 0..9"); return NJS_ERROR; } } @@ -281,7 +283,7 @@ njs_zlib_ext_deflate(njs_vm_t *vm, njs_v break; default: - njs_vm_error(vm, "unknown strategy: %d", strategy); + njs_vm_type_error(vm, "unknown strategy: %d", strategy); return NJS_ERROR; } } @@ -305,14 +307,14 @@ njs_zlib_ext_deflate(njs_vm_t *vm, njs_v rc = deflateInit2(&stream, level, Z_DEFLATED, window_bits, mem_level, strategy); if (njs_slow_path(rc != Z_OK)) { - njs_vm_error(vm, "deflateInit2() failed"); + njs_vm_internal_error(vm, "deflateInit2() failed"); return NJS_ERROR; } if (dictionary.start != NULL) { rc = deflateSetDictionary(&stream, dictionary.start, dictionary.length); if (njs_slow_path(rc != Z_OK)) { - njs_vm_error(vm, "deflateSetDictionary() failed"); + njs_vm_internal_error(vm, "deflateSetDictionary() failed"); return NJS_ERROR; } } @@ -330,7 +332,8 @@ njs_zlib_ext_deflate(njs_vm_t *vm, njs_v rc = deflate(&stream, Z_FINISH); if (njs_slow_path(rc < 0)) { - njs_vm_error(vm, "failed to deflate the data: %s", stream.msg); + njs_vm_internal_error(vm, "failed to deflate the data: %s", + stream.msg); goto fail; } @@ -402,7 +405,7 @@ njs_zlib_ext_inflate(njs_vm_t *vm, njs_v chunk_size = njs_value_number(value); if (njs_slow_path(chunk_size < 64)) { - njs_vm_error(vm, "chunkSize must be >= 64"); + njs_vm_range_error(vm, "chunkSize must be >= 64"); return NJS_ERROR; } } @@ -413,13 +416,15 @@ njs_zlib_ext_inflate(njs_vm_t *vm, njs_v if (raw) { if (njs_slow_path(window_bits < -15 || window_bits > -8)) { - njs_vm_error(vm, "windowBits must be in the range -15..-8"); + njs_vm_range_error(vm, "windowBits must be in the range " + "-15..-8"); return NJS_ERROR; } } else { if (njs_slow_path(window_bits < 8 || window_bits > 15)) { - njs_vm_error(vm, "windowBits must be in the range 8..15"); + njs_vm_range_error(vm, "windowBits must be in the range " + "8..15"); return NJS_ERROR; } } @@ -443,14 +448,14 @@ njs_zlib_ext_inflate(njs_vm_t *vm, njs_v rc = inflateInit2(&stream, window_bits); if (njs_slow_path(rc != Z_OK)) { - njs_vm_error(vm, "inflateInit2() failed"); + njs_vm_internal_error(vm, "inflateInit2() failed"); return NJS_ERROR; } if (dictionary.start != NULL) { rc = inflateSetDictionary(&stream, dictionary.start, dictionary.length); if (njs_slow_path(rc != Z_OK)) { - njs_vm_error(vm, "deflateSetDictionary() failed"); + njs_vm_internal_error(vm, "deflateSetDictionary() failed"); return NJS_ERROR; } } @@ -468,13 +473,13 @@ njs_zlib_ext_inflate(njs_vm_t *vm, njs_v rc = inflate(&stream, Z_NO_FLUSH); if (njs_slow_path(rc < 0)) { - njs_vm_error(vm, "failed to inflate the compressed data: %s", - stream.msg); + njs_vm_internal_error(vm, "failed to inflate the compressed " + "data: %s", stream.msg); goto fail; } if (rc == Z_NEED_DICT) { - njs_vm_error(vm, "failed to inflate, dictionary is required"); + njs_vm_type_error(vm, "failed to inflate, dictionary is required"); goto fail; } From xeioex at nginx.com Thu Jun 22 22:40:13 2023 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 22 Jun 2023 22:40:13 +0000 Subject: [njs] XML: replaced Error with more suitable exception where approriate. Message-ID: details: https://hg.nginx.org/njs/rev/6a9d7d28b12c branches: changeset: 2163:6a9d7d28b12c user: Dmitry Volyntsev date: Thu Jun 22 15:37:16 2023 -0700 description: XML: replaced Error with more suitable exception where approriate. diffstat: external/njs_xml_module.c | 75 ++++++++++++++++++++++++---------------------- src/test/njs_unit_test.c | 6 +- 2 files changed, 42 insertions(+), 39 deletions(-) diffs (319 lines): diff -r f324807389b4 -r 6a9d7d28b12c external/njs_xml_module.c --- a/external/njs_xml_module.c Wed Jun 21 16:30:12 2023 -0700 +++ b/external/njs_xml_module.c Thu Jun 22 15:37:16 2023 -0700 @@ -433,7 +433,7 @@ njs_xml_ext_parse(njs_vm_t *vm, njs_valu tree->ctx = xmlNewParserCtxt(); if (njs_slow_path(tree->ctx == NULL)) { - njs_vm_error(vm, "xmlNewParserCtxt() failed"); + njs_vm_internal_error(vm, "xmlNewParserCtxt() failed"); return NJS_ERROR; } @@ -718,38 +718,38 @@ njs_xml_node_ext_add_child(njs_vm_t *vm, current = njs_vm_external(vm, njs_xml_node_proto_id, njs_argument(args, 0)); if (njs_slow_path(current == NULL)) { - njs_vm_error(vm, "\"this\" is not a XMLNode object"); + njs_vm_type_error(vm, "\"this\" is not a XMLNode object"); return NJS_ERROR; } node = njs_xml_external_node(vm, njs_arg(args, nargs, 1)); if (njs_slow_path(node == NULL)) { - njs_vm_error(vm, "node is not a XMLNode object"); + njs_vm_type_error(vm, "node is not a XMLNode object"); return NJS_ERROR; } copy = xmlDocCopyNode(current, current->doc, 1); if (njs_slow_path(copy == NULL)) { - njs_vm_error(vm, "xmlDocCopyNode() failed"); + njs_vm_internal_error(vm, "xmlDocCopyNode() failed"); return NJS_ERROR; } node = xmlDocCopyNode(node, current->doc, 1); if (njs_slow_path(node == NULL)) { - njs_vm_error(vm, "xmlDocCopyNode() failed"); + njs_vm_internal_error(vm, "xmlDocCopyNode() failed"); goto error; } rnode = xmlAddChild(copy, node); if (njs_slow_path(rnode == NULL)) { xmlFreeNode(node); - njs_vm_error(vm, "xmlAddChild() failed"); + njs_vm_internal_error(vm, "xmlAddChild() failed"); goto error; } ret = xmlReconciliateNs(current->doc, copy); if (njs_slow_path(ret == -1)) { - njs_vm_error(vm, "xmlReconciliateNs() failed"); + njs_vm_internal_error(vm, "xmlReconciliateNs() failed"); goto error; } @@ -852,7 +852,7 @@ njs_xml_node_ext_remove_all_attributes(n current = njs_vm_external(vm, njs_xml_node_proto_id, njs_argument(args, 0)); if (njs_slow_path(current == NULL)) { - njs_vm_error(vm, "\"this\" is not a XMLNode object"); + njs_vm_type_error(vm, "\"this\" is not a XMLNode object"); return NJS_ERROR; } @@ -877,7 +877,7 @@ njs_xml_node_ext_remove_children(njs_vm_ current = njs_vm_external(vm, njs_xml_node_proto_id, njs_argument(args, 0)); if (njs_slow_path(current == NULL)) { - njs_vm_error(vm, "\"this\" is not a XMLNode object"); + njs_vm_type_error(vm, "\"this\" is not a XMLNode object"); return NJS_ERROR; } @@ -887,7 +887,7 @@ njs_xml_node_ext_remove_children(njs_vm_ if (!njs_value_is_null_or_undefined(selector)) { if (njs_slow_path(!njs_value_is_string(selector))) { - njs_vm_error(vm, "selector is not a string"); + njs_vm_type_error(vm, "selector is not a string"); return NJS_ERROR; } @@ -900,7 +900,7 @@ njs_xml_node_ext_remove_children(njs_vm_ copy = xmlDocCopyNode(current, current->doc, 1); if (njs_slow_path(copy == NULL)) { - njs_vm_error(vm, "xmlDocCopyNode() failed"); + njs_vm_internal_error(vm, "xmlDocCopyNode() failed"); return NJS_ERROR; } @@ -931,14 +931,14 @@ njs_xml_node_ext_set_attribute(njs_vm_t current = njs_vm_external(vm, njs_xml_node_proto_id, njs_argument(args, 0)); if (njs_slow_path(current == NULL)) { - njs_vm_error(vm, "\"this\" is not a XMLNode object"); + njs_vm_type_error(vm, "\"this\" is not a XMLNode object"); return NJS_ERROR; } name = njs_arg(args, nargs, 1); if (njs_slow_path(!njs_value_is_string(name))) { - njs_vm_error(vm, "name is not a string"); + njs_vm_type_error(vm, "name is not a string"); return NJS_ERROR; } @@ -1011,7 +1011,7 @@ njs_xml_node_ext_text(njs_vm_t *vm, njs_ && (setval != NULL && !njs_value_is_null_or_undefined(setval))) { if (njs_slow_path(!njs_value_is_string(setval))) { - njs_vm_error(vm, "setval is not a string"); + njs_vm_type_error(vm, "setval is not a string"); return NJS_ERROR; } @@ -1025,7 +1025,7 @@ njs_xml_node_ext_text(njs_vm_t *vm, njs_ copy = xmlDocCopyNode(current, current->doc, 1); if (njs_slow_path(copy == NULL)) { - njs_vm_error(vm, "xmlDocCopyNode() failed"); + njs_vm_internal_error(vm, "xmlDocCopyNode() failed"); return NJS_ERROR; } @@ -1090,7 +1090,7 @@ njs_xml_node_attr_handler(njs_vm_t *vm, ret = xmlValidateQName(&name_buf[0], 0); if (njs_slow_path(ret != 0)) { - njs_vm_error(vm, "attribute name \"%V\" is not valid", name); + njs_vm_type_error(vm, "attribute name \"%V\" is not valid", name); return NJS_ERROR; } @@ -1116,7 +1116,7 @@ njs_xml_node_attr_handler(njs_vm_t *vm, attr = xmlSetProp(current, &name_buf[0], value); if (njs_slow_path(attr == NULL)) { - njs_vm_error(vm, "xmlSetProp() failed"); + njs_vm_internal_error(vm, "xmlSetProp() failed"); return NJS_ERROR; } @@ -1135,7 +1135,7 @@ njs_xml_node_tag_remove(njs_vm_t *vm, xm copy = xmlDocCopyNode(current, current->doc, 1); if (njs_slow_path(copy == NULL)) { - njs_vm_error(vm, "xmlDocCopyNode() failed"); + njs_vm_internal_error(vm, "xmlDocCopyNode() failed"); return NJS_ERROR; } @@ -1199,8 +1199,9 @@ njs_xml_node_tag_handler(njs_vm_t *vm, x } if (retval != NULL) { - njs_vm_error(vm, "XMLNode.$tag$xxx is not assignable, use addChild() or" - "node.$tags = [node1, node2, ..] syntax"); + njs_vm_type_error(vm, "XMLNode.$tag$xxx is not assignable, " + "use addChild() or node.$tags = [node1, node2, ..] " + "syntax"); return NJS_ERROR; } @@ -1260,8 +1261,9 @@ njs_xml_node_tags_handler(njs_vm_t *vm, } if (name->length > 0) { - njs_vm_error(vm, "XMLNode $tags$xxx is not assignable, use addChild() " - "or node.$tags = [node1, node2, ..] syntax"); + njs_vm_type_error(vm, "XMLNode $tags$xxx is not assignable, use " + "addChild() or node.$tags = [node1, node2, ..] " + "syntax"); return NJS_ERROR; } @@ -1269,7 +1271,7 @@ njs_xml_node_tags_handler(njs_vm_t *vm, copy = xmlDocCopyNode(current, current->doc, 1); if (njs_slow_path(copy == NULL)) { - njs_vm_error(vm, "xmlDocCopyNode() failed"); + njs_vm_internal_error(vm, "xmlDocCopyNode() failed"); return NJS_ERROR; } @@ -1284,7 +1286,7 @@ njs_xml_node_tags_handler(njs_vm_t *vm, } if (!njs_value_is_array(setval)) { - njs_vm_error(vm, "setval is not an array"); + njs_vm_type_error(vm, "setval is not an array"); goto error; } @@ -1298,26 +1300,26 @@ njs_xml_node_tags_handler(njs_vm_t *vm, for (i = 0; i < length; i++) { node = njs_xml_external_node(vm, njs_value_arg(start++)); if (njs_slow_path(node == NULL)) { - njs_vm_error(vm, "setval[%D] is not a XMLNode object", i); + njs_vm_type_error(vm, "setval[%D] is not a XMLNode object", i); goto error; } node = xmlDocCopyNode(node, current->doc, 1); if (njs_slow_path(node == NULL)) { - njs_vm_error(vm, "xmlDocCopyNode() failed"); + njs_vm_internal_error(vm, "xmlDocCopyNode() failed"); goto error; } rnode = xmlAddChild(copy, node); if (njs_slow_path(rnode == NULL)) { - njs_vm_error(vm, "xmlAddChild() failed"); + njs_vm_internal_error(vm, "xmlAddChild() failed"); xmlFreeNode(node); goto error; } ret = xmlReconciliateNs(current->doc, copy); if (njs_slow_path(ret == -1)) { - njs_vm_error(vm, "xmlReconciliateNs() failed"); + njs_vm_internal_error(vm, "xmlReconciliateNs() failed"); goto error; } } @@ -1344,13 +1346,13 @@ njs_xml_external_node(njs_vm_t *vm, njs_ if (njs_slow_path(current == NULL)) { tree = njs_vm_external(vm, njs_xml_doc_proto_id, value); if (njs_slow_path(tree == NULL)) { - njs_vm_error(vm, "\"this\" is not a XMLNode object"); + njs_vm_type_error(vm, "\"this\" is not a XMLNode object"); return NULL; } current = xmlDocGetRootElement(tree->doc); if (njs_slow_path(current == NULL)) { - njs_vm_error(vm, "\"this\" is not a XMLNode object"); + njs_vm_type_error(vm, "\"this\" is not a XMLNode object"); return NULL; } } @@ -1366,8 +1368,8 @@ njs_xml_str_to_c_string(njs_vm_t *vm, nj u_char *p; if (njs_slow_path(str->length > size - njs_length("\0"))) { - njs_vm_error(vm, "njs_xml_str_to_c_string() very long string, " - "length >= %uz", size - njs_length("\0")); + njs_vm_internal_error(vm, "njs_xml_str_to_c_string() very long string, " + "length >= %uz", size - njs_length("\0")); return NJS_ERROR; } @@ -1732,7 +1734,8 @@ njs_xml_ext_canonicalization(njs_vm_t *v if (!njs_value_is_null_or_undefined(excluding)) { node = njs_vm_external(vm, njs_xml_node_proto_id, excluding); if (njs_slow_path(node == NULL)) { - njs_vm_error(vm, "\"excluding\" argument is not a XMLNode object"); + njs_vm_type_error(vm, "\"excluding\" argument is not a XMLNode " + "object"); return NJS_ERROR; } @@ -1764,7 +1767,7 @@ njs_xml_ext_canonicalization(njs_vm_t *v if (!njs_value_is_null_or_undefined(prefixes)) { if (!njs_value_is_string(prefixes)) { - njs_vm_error(vm, "\"prefixes\" argument is not a string"); + njs_vm_type_error(vm, "\"prefixes\" argument is not a string"); return NJS_ERROR; } @@ -1783,7 +1786,7 @@ njs_xml_ext_canonicalization(njs_vm_t *v buf = xmlOutputBufferCreateIO(njs_xml_buf_write_cb, NULL, &chain, NULL); if (njs_slow_path(buf == NULL)) { - njs_vm_error(vm, "xmlOutputBufferCreateIO() failed"); + njs_vm_internal_error(vm, "xmlOutputBufferCreateIO() failed"); return NJS_ERROR; } @@ -1792,7 +1795,7 @@ njs_xml_ext_canonicalization(njs_vm_t *v prefix_list, comments, buf); if (njs_slow_path(ret < 0)) { - njs_vm_error(vm, "xmlC14NExecute() failed"); + njs_vm_internal_error(vm, "xmlC14NExecute() failed"); ret = NJS_ERROR; goto error; } diff -r f324807389b4 -r 6a9d7d28b12c src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Wed Jun 21 16:30:12 2023 -0700 +++ b/src/test/njs_unit_test.c Thu Jun 22 15:37:16 2023 -0700 @@ -22084,7 +22084,7 @@ static njs_unit_test_t njs_xml_test[] = { njs_str("var xml = require('xml');" "var doc = xml.parse(``); xml.exclusiveC14n(doc, 1)"), - njs_str("Error: \"excluding\" argument is not a XMLNode object") }, + njs_str("TypeError: \"excluding\" argument is not a XMLNode object") }, { njs_str(NJS_XML_DOC "doc.$root.$text"), @@ -22163,12 +22163,12 @@ static njs_unit_test_t njs_xml_test[] = { njs_str(NJS_XML_DOC "doc.$root.setAttribute('<', 'xxx')"), - njs_str("Error: attribute name \"<\" is not valid") }, + njs_str("TypeError: attribute name \"<\" is not valid") }, { njs_str(NJS_XML_DOC "doc.$root.$text = 'WAKA';" "doc.$root['$attr$' + 'x'.repeat(1024)] = 1;"), - njs_str("Error: njs_xml_str_to_c_string() very long string, length >= 511") }, + njs_str("InternalError: njs_xml_str_to_c_string() very long string, length >= 511") }, { njs_str(NJS_XML_DOC "delete doc.note.to.$attr$a;" From xeioex at nginx.com Thu Jun 22 22:41:21 2023 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Thu, 22 Jun 2023 22:41:21 +0000 Subject: [njs] Fetch: fixed setting of Content-Type header. Message-ID: details: https://hg.nginx.org/njs/rev/9537c55033d2 branches: changeset: 2164:9537c55033d2 user: Dmitry Volyntsev date: Thu Jun 22 15:40:36 2023 -0700 description: Fetch: fixed setting of Content-Type header. Previously, Content-Type was set unconditionally to "text/plain;charset=UTF-8" when fetch request contained a string body. This may overlap with user's Content-Type. The fix is to set the header only if it was not set before. This fixes #654 issue on Github. diffstat: nginx/ngx_js_fetch.c | 22 +++++++++++++++++++++- nginx/t/js_fetch_objects.t | 21 +++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletions(-) diffs (98 lines): diff -r 6a9d7d28b12c -r 9537c55033d2 nginx/ngx_js_fetch.c --- a/nginx/ngx_js_fetch.c Thu Jun 22 15:37:16 2023 -0700 +++ b/nginx/ngx_js_fetch.c Thu Jun 22 15:40:36 2023 -0700 @@ -65,6 +65,7 @@ typedef struct { GUARD_RESPONSE, } guard; ngx_list_t header_list; + ngx_js_tb_elt_t *content_type; } ngx_js_headers_t; @@ -1951,6 +1952,7 @@ ngx_js_request_constructor(njs_vm_t *vm, * request->cache_mode = CACHE_MODE_DEFAULT; * request->credentials = CREDENTIALS_SAME_ORIGIN; * request->mode = MODE_NO_CORS; + * request->headers.content_type = NULL; */ ngx_memzero(request, sizeof(ngx_js_request_t)); @@ -2092,6 +2094,9 @@ ngx_js_request_constructor(njs_vm_t *vm, * just allocating a new one. */ + ngx_memset(&request->headers, 0, sizeof(ngx_js_headers_t)); + request->headers.guard = GUARD_REQUEST; + rc = ngx_list_init(&request->headers.header_list, pool, 4, sizeof(ngx_js_tb_elt_t)); if (rc != NGX_OK) { @@ -2112,7 +2117,9 @@ ngx_js_request_constructor(njs_vm_t *vm, return NJS_ERROR; } - if (njs_value_is_string(value)) { + if (request->headers.content_type == NULL + && njs_value_is_string(value)) + { ret = ngx_js_headers_append(vm, &request->headers, (u_char *) "Content-Type", njs_length("Content-Type"), @@ -2303,6 +2310,12 @@ ngx_js_headers_append(njs_vm_t *vm, ngx_ h->value.len = vlen; h->next = NULL; + if (len == njs_strlen("Content-Type") + && ngx_strncasecmp(name, (u_char *) "Content-Type", len) == 0) + { + headers->content_type = h; + } + return NJS_OK; } @@ -3334,6 +3347,13 @@ ngx_headers_js_ext_delete(njs_vm_t *vm, } } + if (name.length == njs_strlen("Content-Type") + && ngx_strncasecmp(name.start, (u_char *) "Content-Type", name.length) + == 0) + { + headers->content_type = NULL; + } + njs_value_undefined_set(retval); return NJS_OK; diff -r 6a9d7d28b12c -r 9537c55033d2 nginx/t/js_fetch_objects.t --- a/nginx/t/js_fetch_objects.t Thu Jun 22 15:37:16 2023 -0700 +++ b/nginx/t/js_fetch_objects.t Thu Jun 22 15:40:36 2023 -0700 @@ -373,6 +373,27 @@ my $p0 = port(8080); var body = await r.text(); return `\${body}: \${r.headers.get('Content-Type')}`; }, 'ABC: text/plain;charset=UTF-8'], + ['user content type', async () => { + var r = new Request("http://nginx.org", + {body: 'ABC', + headers: {'Content-Type': 'text/html'}}); + return r.headers.get('Content-Type'); + }, 'text/html'], + ['user content type from Headers()', async () => { + var h = new Headers(); + h.append('Content-Type', 'text/html'); + var r = new Request("http://nginx.org", + {body: 'ABC', headers: h}); + return r.headers.get('Content-Type'); + }, 'text/html'], + ['user content type deleted', async () => { + var h = new Headers(); + h.append('Content-Type', 'text/html'); + h.delete('Content-Type'); + var r = new Request("http://nginx.org", + {body: 'ABC', headers: h}); + return r.headers.get('Content-Type'); + }, 'text/plain;charset=UTF-8'], ['GET body', () => { try { var r = new Request("http://nginx.org", {body: 'ABC'}); From pluknet at nginx.com Fri Jun 23 10:02:01 2023 From: pluknet at nginx.com (Sergey Kandaurov) Date: Fri, 23 Jun 2023 14:02:01 +0400 Subject: [PATCH] HTTP/3: fixed $body_bytes_sent In-Reply-To: References: Message-ID: <931767D8-109E-41AB-B8D9-66F2DAC5303F@nginx.com> > On 20 Jun 2023, at 17:43, Sergey Kandaurov wrote: > > # HG changeset patch > # User Sergey Kandaurov > # Date 1687268079 -14400 > # Tue Jun 20 17:34:39 2023 +0400 > # Node ID a95bffe430283bf25341ad9745ffe1199e7c2190 > # Parent bf4bd5af4d7fdadab83616be9218604b658e3d84 > HTTP/3: fixed $body_bytes_sent. > > diff --git a/src/http/v3/ngx_http_v3_filter_module.c b/src/http/v3/ngx_http_v3_filter_module.c > --- a/src/http/v3/ngx_http_v3_filter_module.c > +++ b/src/http/v3/ngx_http_v3_filter_module.c > @@ -540,6 +540,8 @@ ngx_http_v3_header_filter(ngx_http_reque > *ll = hl; > ll = &cl->next; > > + r->header_size = n + (b->last - b->pos); > + > if (r->headers_out.content_length_n >= 0 > && !r->header_only && !r->expect_trailers) > { This variant of the patch additionally cuts off the first (and only) DATA frame header length from the variable value. This better matches HTTP/1.1 non-"chunked transfer encoding" behaviour, when the content length is known and no trailers expected. Else, when chunked is used, all DATA-frame header lengths (and trailers) are included similar to HTTP/1.1. # HG changeset patch # User Sergey Kandaurov # Date 1687514427 -14400 # Fri Jun 23 14:00:27 2023 +0400 # Node ID c681f4906d838ac45b517fada4c4274ade03fd3c # Parent 77c1418916f7817a0d020f28d8a08f278a12fe43 HTTP/3: fixed $body_bytes_sent. diff --git a/src/http/v3/ngx_http_v3_filter_module.c b/src/http/v3/ngx_http_v3_filter_module.c --- a/src/http/v3/ngx_http_v3_filter_module.c +++ b/src/http/v3/ngx_http_v3_filter_module.c @@ -581,6 +581,7 @@ ngx_http_v3_header_filter(ngx_http_reque for (cl = out; cl; cl = cl->next) { h3c->total_bytes += cl->buf->last - cl->buf->pos; + r->header_size += cl->buf->last - cl->buf->pos; } return ngx_http_write_filter(r, out); -- Sergey Kandaurov From D.Plotnikov at F5.com Fri Jun 23 11:26:34 2023 From: D.Plotnikov at F5.com (Dmitry Plotnikov) Date: Fri, 23 Jun 2023 11:26:34 +0000 Subject: [PATCH] HTTP/3: fixed $body_bytes_sent In-Reply-To: <931767D8-109E-41AB-B8D9-66F2DAC5303F@nginx.com> References: <931767D8-109E-41AB-B8D9-66F2DAC5303F@nginx.com> Message-ID: Look good to me. Thanks, Dmitry From: nginx-devel on behalf of Sergey Kandaurov Date: Friday, June 23, 2023 at 3:02 AM To: nginx-devel at nginx.org Subject: Re: [PATCH] HTTP/3: fixed $body_bytes_sent EXTERNAL MAIL: nginx-devel-bounces at nginx.org > On 20 Jun 2023, at 17:43, Sergey Kandaurov wrote: > > # HG changeset patch > # User Sergey Kandaurov > # Date 1687268079 -14400 > # Tue Jun 20 17:34:39 2023 +0400 > # Node ID a95bffe430283bf25341ad9745ffe1199e7c2190 > # Parent bf4bd5af4d7fdadab83616be9218604b658e3d84 > HTTP/3: fixed $body_bytes_sent. > > diff --git a/src/http/v3/ngx_http_v3_filter_module.c b/src/http/v3/ngx_http_v3_filter_module.c > --- a/src/http/v3/ngx_http_v3_filter_module.c > +++ b/src/http/v3/ngx_http_v3_filter_module.c > @@ -540,6 +540,8 @@ ngx_http_v3_header_filter(ngx_http_reque > *ll = hl; > ll = &cl->next; > > + r->header_size = n + (b->last - b->pos); > + > if (r->headers_out.content_length_n >= 0 > && !r->header_only && !r->expect_trailers) > { This variant of the patch additionally cuts off the first (and only) DATA frame header length from the variable value. This better matches HTTP/1.1 non-"chunked transfer encoding" behaviour, when the content length is known and no trailers expected. Else, when chunked is used, all DATA-frame header lengths (and trailers) are included similar to HTTP/1.1. # HG changeset patch # User Sergey Kandaurov # Date 1687514427 -14400 # Fri Jun 23 14:00:27 2023 +0400 # Node ID c681f4906d838ac45b517fada4c4274ade03fd3c # Parent 77c1418916f7817a0d020f28d8a08f278a12fe43 HTTP/3: fixed $body_bytes_sent. diff --git a/src/http/v3/ngx_http_v3_filter_module.c b/src/http/v3/ngx_http_v3_filter_module.c --- a/src/http/v3/ngx_http_v3_filter_module.c +++ b/src/http/v3/ngx_http_v3_filter_module.c @@ -581,6 +581,7 @@ ngx_http_v3_header_filter(ngx_http_reque for (cl = out; cl; cl = cl->next) { h3c->total_bytes += cl->buf->last - cl->buf->pos; + r->header_size += cl->buf->last - cl->buf->pos; } return ngx_http_write_filter(r, out); -- Sergey Kandaurov _______________________________________________ nginx-devel mailing list nginx-devel at nginx.org https://nam02.safelinks.protection.outlook.com/?url=https%3A%2F%2Fmailman.nginx.org%2Fmailman%2Flistinfo%2Fnginx-devel&data=05%7C01%7Cd.plotnikov%40f5.com%7C33b0174f73f5418697c708db73d0eb25%7Cdd3dfd2f6a3b40d19be0bf8327d81c50%7C0%7C0%7C638231113373934840%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&sdata=GzcQTuRhnL77VlQgxEEzCqQU2VFNl3yKXbNyDKTmzjA%3D&reserved=0 -------------- next part -------------- An HTML attachment was scrubbed... URL: From pluknet at nginx.com Fri Jun 23 15:55:47 2023 From: pluknet at nginx.com (=?iso-8859-1?q?Sergey_Kandaurov?=) Date: Fri, 23 Jun 2023 19:55:47 +0400 Subject: [PATCH] Core: fixed environment on exit better Message-ID: <34a8e1a4161542896c11.1687535747@enoparse.local> # HG changeset patch # User Sergey Kandaurov # Date 1687535739 -14400 # Fri Jun 23 19:55:39 2023 +0400 # Node ID 34a8e1a4161542896c11c4a5c60d6a6fe1931e3d # Parent c681f4906d838ac45b517fada4c4274ade03fd3c Core: fixed environment on exit better. The fix in 6822:c045b4926b2c to replace environment allocations from a pool was incomplete, such that it left pool owned allocations for variables set with values using the "env" directive. Another consumer of this interface is the QUIC BPF helper that uses the environment variable NGINX_BPF_MAPS. The fix is to re-allocate variables with malloc, to avoid use after free. If memory allocation failed, the only option is to expel from environment. The observed symptoms are similar to described in 6822:c045b4926b2c, that is a segmentation fault on worker process exit from atexit() handler seen with 3rd party modules or if nginx was built with lcov profiling. diff --git a/src/core/nginx.c b/src/core/nginx.c --- a/src/core/nginx.c +++ b/src/core/nginx.c @@ -631,17 +631,48 @@ ngx_cleanup_environment(void *data) { char **env = data; - if (environ == env) { + char *p, **penv; + size_t size; + ngx_uint_t i, n; - /* - * if the environment is still used, as it happens on exit, - * the only option is to leak it - */ - + if (environ != env) { + ngx_free(env); return; } - ngx_free(env); + /* + * if the environment is still used, as it happens on exit, + * the only option is to leak it + */ + + for (n = 0; env[n]; n++) { } + + for (i = 0; env[i]; i++) { + + for (penv = ngx_os_environ; *penv; penv++) { + if (ngx_strcmp(*penv, env[i]) == 0) { + break; + } + } + + if (*penv) { + continue; + } + + /* substitute pool allocated variables */ + + size = ngx_strlen(env[i]) + 1; + p = malloc(size); + + if (p) { + ngx_memcpy(p, env[i], size); + env[i] = p; + + } else { + ngx_memmove(&env[i], &env[i + 1], sizeof(char *) * (n - i)); + i--; n--; + } + } } From mdounin at mdounin.ru Sat Jun 24 02:06:46 2023 From: mdounin at mdounin.ru (Maxim Dounin) Date: Sat, 24 Jun 2023 05:06:46 +0300 Subject: [PATCH] Core: fixed environment on exit better In-Reply-To: <34a8e1a4161542896c11.1687535747@enoparse.local> References: <34a8e1a4161542896c11.1687535747@enoparse.local> Message-ID: Hello! On Fri, Jun 23, 2023 at 07:55:47PM +0400, Sergey Kandaurov wrote: > # HG changeset patch > # User Sergey Kandaurov > # Date 1687535739 -14400 > # Fri Jun 23 19:55:39 2023 +0400 > # Node ID 34a8e1a4161542896c11c4a5c60d6a6fe1931e3d > # Parent c681f4906d838ac45b517fada4c4274ade03fd3c > Core: fixed environment on exit better. > > The fix in 6822:c045b4926b2c to replace environment allocations from a pool > was incomplete, such that it left pool owned allocations for variables set > with values using the "env" directive. Another consumer of this interface > is the QUIC BPF helper that uses the environment variable NGINX_BPF_MAPS. > The fix is to re-allocate variables with malloc, to avoid use after free. > If memory allocation failed, the only option is to expel from environment. > > The observed symptoms are similar to described in 6822:c045b4926b2c, that > is a segmentation fault on worker process exit from atexit() handler seen > with 3rd party modules or if nginx was built with lcov profiling. > > diff --git a/src/core/nginx.c b/src/core/nginx.c > --- a/src/core/nginx.c > +++ b/src/core/nginx.c > @@ -631,17 +631,48 @@ ngx_cleanup_environment(void *data) > { > char **env = data; > > - if (environ == env) { > + char *p, **penv; > + size_t size; > + ngx_uint_t i, n; > > - /* > - * if the environment is still used, as it happens on exit, > - * the only option is to leak it > - */ > - > + if (environ != env) { > + ngx_free(env); > return; > } Note: if we assume that the environment can be arbitrary modified, I don't think it's enough. For example, a setenv() call can replace environ with something different, so this code will free env and exit, but pool-allocated variables will be still referenced by the new environ. This is probably out of the scope of this patch though. > > - ngx_free(env); > + /* > + * if the environment is still used, as it happens on exit, > + * the only option is to leak it > + */ > + > + for (n = 0; env[n]; n++) { } > + > + for (i = 0; env[i]; i++) { > + > + for (penv = ngx_os_environ; *penv; penv++) { > + if (ngx_strcmp(*penv, env[i]) == 0) { I don't think it's going to work. If I'm reading this correctly, with the initial environment "FOO=bar" and "env FOO=bar;" in the configuration this will assume the string is from ngx_os_environ, but it will be from ccf->env instead. > + break; > + } > + } > + > + if (*penv) { > + continue; > + } > + > + /* substitute pool allocated variables */ > + > + size = ngx_strlen(env[i]) + 1; > + p = malloc(size); There should be no direct malloc() calls except in low-level code where logging is not available. I don't think this particular place counts, so ngx_alloc() should be used instead. > + > + if (p) { > + ngx_memcpy(p, env[i], size); > + env[i] = p; > + > + } else { > + ngx_memmove(&env[i], &env[i + 1], sizeof(char *) * (n - i)); > + i--; n--; > + } > + } > } Overall, it looks like a better idea might be to simply add all the variables added to the environment to the environ allocation in ngx_set_environment(). In ngx_set_environment() we explicitly know if the particular variable is from OS environment or from ccf->environ, so there will be no need to guess. Also, the appropriate log is readily available (and already used in the existing ngx_alloc() call), and the code to cleanup things is already there and will work without additional modifications. -- Maxim Dounin http://mdounin.ru/ From hongzhidao at gmail.com Sun Jun 25 07:25:29 2023 From: hongzhidao at gmail.com (=?UTF-8?B?5rSq5b+X6YGT?=) Date: Sun, 25 Jun 2023 15:25:29 +0800 Subject: Is ngx_http_headers_out dead code? Message-ID: Hi, I wonder if the `ngx_http_headers_out` variable is being used? If yes, what is it for? ``` /* src/http/ngx_http_header_filter_module.c */ ngx_http_header_out_t ngx_http_headers_out[] = { { ngx_string("Server"), offsetof(ngx_http_headers_out_t, server) }, { ngx_string("Date"), offsetof(ngx_http_headers_out_t, date) }, @@ -151,6 +152,7 @@ { ngx_null_string, 0 } }; ``` Thanks. -------------- next part -------------- An HTML attachment was scrubbed... URL: From arut at nginx.com Wed Jun 28 12:45:16 2023 From: arut at nginx.com (Roman Arutyunyan) Date: Wed, 28 Jun 2023 16:45:16 +0400 Subject: [PATCH] Core: fixed environment on exit better In-Reply-To: References: <34a8e1a4161542896c11.1687535747@enoparse.local> Message-ID: <20230628124516.3tm7usbua36sjwur@N00W24XTQX> Hi, On Sat, Jun 24, 2023 at 05:06:46AM +0300, Maxim Dounin wrote: > Hello! > > On Fri, Jun 23, 2023 at 07:55:47PM +0400, Sergey Kandaurov wrote: > > > # HG changeset patch > > # User Sergey Kandaurov > > # Date 1687535739 -14400 > > # Fri Jun 23 19:55:39 2023 +0400 > > # Node ID 34a8e1a4161542896c11c4a5c60d6a6fe1931e3d > > # Parent c681f4906d838ac45b517fada4c4274ade03fd3c > > Core: fixed environment on exit better. > > > > The fix in 6822:c045b4926b2c to replace environment allocations from a pool > > was incomplete, such that it left pool owned allocations for variables set > > with values using the "env" directive. Another consumer of this interface > > is the QUIC BPF helper that uses the environment variable NGINX_BPF_MAPS. > > The fix is to re-allocate variables with malloc, to avoid use after free. > > If memory allocation failed, the only option is to expel from environment. > > > > The observed symptoms are similar to described in 6822:c045b4926b2c, that > > is a segmentation fault on worker process exit from atexit() handler seen > > with 3rd party modules or if nginx was built with lcov profiling. > > > > diff --git a/src/core/nginx.c b/src/core/nginx.c > > --- a/src/core/nginx.c > > +++ b/src/core/nginx.c > > @@ -631,17 +631,48 @@ ngx_cleanup_environment(void *data) > > { > > char **env = data; > > > > - if (environ == env) { > > + char *p, **penv; > > + size_t size; > > + ngx_uint_t i, n; > > > > - /* > > - * if the environment is still used, as it happens on exit, > > - * the only option is to leak it > > - */ > > - > > + if (environ != env) { > > + ngx_free(env); > > return; > > } > > Note: if we assume that the environment can be arbitrary modified, > I don't think it's enough. For example, a setenv() call can > replace environ with something different, so this code will free > env and exit, but pool-allocated variables will be still > referenced by the new environ. Another problem is if setenv() was called, environ may have been reallocated with realloc() which may result in double-free in this function, even with current code. > This is probably out of the scope of this patch though. > > > > > - ngx_free(env); > > + /* > > + * if the environment is still used, as it happens on exit, > > + * the only option is to leak it > > + */ > > + > > + for (n = 0; env[n]; n++) { } > > + > > + for (i = 0; env[i]; i++) { > > + > > + for (penv = ngx_os_environ; *penv; penv++) { > > + if (ngx_strcmp(*penv, env[i]) == 0) { > > I don't think it's going to work. If I'm reading this correctly, > with the initial environment "FOO=bar" and "env FOO=bar;" in the > configuration this will assume the string is from ngx_os_environ, > but it will be from ccf->env instead. > > > + break; > > + } > > + } > > + > > + if (*penv) { > > + continue; > > + } > > + > > + /* substitute pool allocated variables */ > > + > > + size = ngx_strlen(env[i]) + 1; > > + p = malloc(size); > > There should be no direct malloc() calls except in low-level code > where logging is not available. I don't think this particular > place counts, so ngx_alloc() should be used instead. > > > + > > + if (p) { > > + ngx_memcpy(p, env[i], size); > > + env[i] = p; > > + > > + } else { > > + ngx_memmove(&env[i], &env[i + 1], sizeof(char *) * (n - i)); > > + i--; n--; > > + } > > + } > > } > > Overall, it looks like a better idea might be to simply add all > the variables added to the environment to the environ allocation > in ngx_set_environment(). Again, if setenv() is called, realloc() will free everything, including the variables. On the other hand, since setenv() is not supported anyway, and no one complained, we can try this simple approach. > In ngx_set_environment() we explicitly know if the particular > variable is from OS environment or from ccf->environ, so there > will be no need to guess. Also, the appropriate log is readily > available (and already used in the existing ngx_alloc() call), and > the code to cleanup things is already there and will work without > additional modifications. > > -- > Maxim Dounin > http://mdounin.ru/ > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > https://mailman.nginx.org/mailman/listinfo/nginx-devel -- Roman Arutyunyan From mdounin at mdounin.ru Wed Jun 28 15:08:35 2023 From: mdounin at mdounin.ru (Maxim Dounin) Date: Wed, 28 Jun 2023 18:08:35 +0300 Subject: [PATCH] Core: fixed environment on exit better In-Reply-To: <20230628124516.3tm7usbua36sjwur@N00W24XTQX> References: <34a8e1a4161542896c11.1687535747@enoparse.local> <20230628124516.3tm7usbua36sjwur@N00W24XTQX> Message-ID: Hello! On Wed, Jun 28, 2023 at 04:45:16PM +0400, Roman Arutyunyan wrote: > On Sat, Jun 24, 2023 at 05:06:46AM +0300, Maxim Dounin wrote: > > Hello! > > > > On Fri, Jun 23, 2023 at 07:55:47PM +0400, Sergey Kandaurov wrote: > > > > > # HG changeset patch > > > # User Sergey Kandaurov > > > # Date 1687535739 -14400 > > > # Fri Jun 23 19:55:39 2023 +0400 > > > # Node ID 34a8e1a4161542896c11c4a5c60d6a6fe1931e3d > > > # Parent c681f4906d838ac45b517fada4c4274ade03fd3c > > > Core: fixed environment on exit better. > > > > > > The fix in 6822:c045b4926b2c to replace environment allocations from a pool > > > was incomplete, such that it left pool owned allocations for variables set > > > with values using the "env" directive. Another consumer of this interface > > > is the QUIC BPF helper that uses the environment variable NGINX_BPF_MAPS. > > > The fix is to re-allocate variables with malloc, to avoid use after free. > > > If memory allocation failed, the only option is to expel from environment. > > > > > > The observed symptoms are similar to described in 6822:c045b4926b2c, that > > > is a segmentation fault on worker process exit from atexit() handler seen > > > with 3rd party modules or if nginx was built with lcov profiling. > > > > > > diff --git a/src/core/nginx.c b/src/core/nginx.c > > > --- a/src/core/nginx.c > > > +++ b/src/core/nginx.c > > > @@ -631,17 +631,48 @@ ngx_cleanup_environment(void *data) > > > { > > > char **env = data; > > > > > > - if (environ == env) { > > > + char *p, **penv; > > > + size_t size; > > > + ngx_uint_t i, n; > > > > > > - /* > > > - * if the environment is still used, as it happens on exit, > > > - * the only option is to leak it > > > - */ > > > - > > > + if (environ != env) { > > > + ngx_free(env); > > > return; > > > } > > > > Note: if we assume that the environment can be arbitrary modified, > > I don't think it's enough. For example, a setenv() call can > > replace environ with something different, so this code will free > > env and exit, but pool-allocated variables will be still > > referenced by the new environ. > > Another problem is if setenv() was called, environ may have been > reallocated with realloc() which may result in double-free in this function, > even with current code. I don't think that realloc() is allowed here. At least BSD libc does not try to do this and only use realloc() on it's internal storage, and glibc does the same. > > This is probably out of the scope of this patch though. > > > > > > > > - ngx_free(env); > > > + /* > > > + * if the environment is still used, as it happens on exit, > > > + * the only option is to leak it > > > + */ > > > + > > > + for (n = 0; env[n]; n++) { } > > > + > > > + for (i = 0; env[i]; i++) { > > > + > > > + for (penv = ngx_os_environ; *penv; penv++) { > > > + if (ngx_strcmp(*penv, env[i]) == 0) { > > > > I don't think it's going to work. If I'm reading this correctly, > > with the initial environment "FOO=bar" and "env FOO=bar;" in the > > configuration this will assume the string is from ngx_os_environ, > > but it will be from ccf->env instead. > > > > > + break; > > > + } > > > + } > > > + > > > + if (*penv) { > > > + continue; > > > + } > > > + > > > + /* substitute pool allocated variables */ > > > + > > > + size = ngx_strlen(env[i]) + 1; > > > + p = malloc(size); > > > > There should be no direct malloc() calls except in low-level code > > where logging is not available. I don't think this particular > > place counts, so ngx_alloc() should be used instead. > > > > > + > > > + if (p) { > > > + ngx_memcpy(p, env[i], size); > > > + env[i] = p; > > > + > > > + } else { > > > + ngx_memmove(&env[i], &env[i + 1], sizeof(char *) * (n - i)); > > > + i--; n--; > > > + } > > > + } > > > } > > > > Overall, it looks like a better idea might be to simply add all > > the variables added to the environment to the environ allocation > > in ngx_set_environment(). > > Again, if setenv() is called, realloc() will free everything, including the > variables. See above, there should be no realloc(). > On the other hand, since setenv() is not supported anyway, and no > one complained, we can try this simple approach. I believe currently setenv() cannot cause issues additional to the one being fixed by the patch. In the worst case, setenv() will allocate new environ and copy pointers to the variables there. As long as variables are not pool-allocated, everything will work fine. With pool-allocated variables, there will be a segmentation fault if variables are being looked up in an _atexit() handler. (Another question is if setenv() will actually work as expected if called by some code. Since nginx will clear/replace environment on each worker process startup, setenv() results are likely to be cleared unless set in the worker process itself.) To properly support setenv(), a fix would be to check in ngx_cleanup_environment() not only environ itself, but also if any of the variables in current environ refer to the memory allocated in ngx_set_environment(). > > > In ngx_set_environment() we explicitly know if the particular > > variable is from OS environment or from ccf->environ, so there > > will be no need to guess. Also, the appropriate log is readily > > available (and already used in the existing ngx_alloc() call), and > > the code to cleanup things is already there and will work without > > additional modifications. -- Maxim Dounin http://mdounin.ru/ From arut at nginx.com Wed Jun 28 15:36:34 2023 From: arut at nginx.com (Roman Arutyunyan) Date: Wed, 28 Jun 2023 19:36:34 +0400 Subject: [PATCH] Core: fixed environment on exit better In-Reply-To: References: <34a8e1a4161542896c11.1687535747@enoparse.local> <20230628124516.3tm7usbua36sjwur@N00W24XTQX> Message-ID: <20230628153634.ocm3a53wvfcsg5zz@N00W24XTQX> Hi, On Wed, Jun 28, 2023 at 06:08:35PM +0300, Maxim Dounin wrote: > Hello! > > On Wed, Jun 28, 2023 at 04:45:16PM +0400, Roman Arutyunyan wrote: > > > On Sat, Jun 24, 2023 at 05:06:46AM +0300, Maxim Dounin wrote: > > > Hello! > > > > > > On Fri, Jun 23, 2023 at 07:55:47PM +0400, Sergey Kandaurov wrote: > > > > > > > # HG changeset patch > > > > # User Sergey Kandaurov > > > > # Date 1687535739 -14400 > > > > # Fri Jun 23 19:55:39 2023 +0400 > > > > # Node ID 34a8e1a4161542896c11c4a5c60d6a6fe1931e3d > > > > # Parent c681f4906d838ac45b517fada4c4274ade03fd3c > > > > Core: fixed environment on exit better. > > > > > > > > The fix in 6822:c045b4926b2c to replace environment allocations from a pool > > > > was incomplete, such that it left pool owned allocations for variables set > > > > with values using the "env" directive. Another consumer of this interface > > > > is the QUIC BPF helper that uses the environment variable NGINX_BPF_MAPS. > > > > The fix is to re-allocate variables with malloc, to avoid use after free. > > > > If memory allocation failed, the only option is to expel from environment. > > > > > > > > The observed symptoms are similar to described in 6822:c045b4926b2c, that > > > > is a segmentation fault on worker process exit from atexit() handler seen > > > > with 3rd party modules or if nginx was built with lcov profiling. > > > > > > > > diff --git a/src/core/nginx.c b/src/core/nginx.c > > > > --- a/src/core/nginx.c > > > > +++ b/src/core/nginx.c > > > > @@ -631,17 +631,48 @@ ngx_cleanup_environment(void *data) > > > > { > > > > char **env = data; > > > > > > > > - if (environ == env) { > > > > + char *p, **penv; > > > > + size_t size; > > > > + ngx_uint_t i, n; > > > > > > > > - /* > > > > - * if the environment is still used, as it happens on exit, > > > > - * the only option is to leak it > > > > - */ > > > > - > > > > + if (environ != env) { > > > > + ngx_free(env); > > > > return; > > > > } > > > > > > Note: if we assume that the environment can be arbitrary modified, > > > I don't think it's enough. For example, a setenv() call can > > > replace environ with something different, so this code will free > > > env and exit, but pool-allocated variables will be still > > > referenced by the new environ. > > > > Another problem is if setenv() was called, environ may have been > > reallocated with realloc() which may result in double-free in this function, > > even with current code. > > I don't think that realloc() is allowed here. At least BSD libc > does not try to do this and only use realloc() on it's internal > storage, and glibc does the same. You're right. I see, glibc only realloc()'ates what it allocated itself. stdlib/setenv.c: /* If this variable is not a null pointer we allocated the current environment. */ static char **last_environ; [..] -- Roman Arutyunyan From xeioex at nginx.com Fri Jun 30 03:39:19 2023 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Fri, 30 Jun 2023 03:39:19 +0000 Subject: [njs] Removed inappropriate "prototype" property for Math object. Message-ID: details: https://hg.nginx.org/njs/rev/9371326836d2 branches: changeset: 2165:9371326836d2 user: Dmitry Volyntsev date: Mon Jun 26 16:47:17 2023 -0700 description: Removed inappropriate "prototype" property for Math object. diffstat: src/njs_math.c | 2 -- 1 files changed, 0 insertions(+), 2 deletions(-) diffs (12 lines): diff -r 9537c55033d2 -r 9371326836d2 src/njs_math.c --- a/src/njs_math.c Thu Jun 22 15:40:36 2023 -0700 +++ b/src/njs_math.c Mon Jun 26 16:47:17 2023 -0700 @@ -383,8 +383,6 @@ static const njs_object_prop_t njs_math .configurable = 1, }, - NJS_DECLARE_PROP_HANDLER("prototype", njs_object_prototype_create, 0, 0, 0), - NJS_DECLARE_PROP_VALUE("E", njs_value(NJS_NUMBER, 1, M_E), 0), NJS_DECLARE_PROP_VALUE("LN10", njs_value(NJS_NUMBER, 1, M_LN10), 0), From xeioex at nginx.com Fri Jun 30 03:39:21 2023 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Fri, 30 Jun 2023 03:39:21 +0000 Subject: [njs] Using addon module API to unify injecting of external objects. Message-ID: details: https://hg.nginx.org/njs/rev/57ca02d7404c branches: changeset: 2166:57ca02d7404c user: Dmitry Volyntsev date: Wed Jun 28 22:15:57 2023 -0700 description: Using addon module API to unify injecting of external objects. diffstat: nginx/ngx_http_js_module.c | 46 +++++++++++++++++++++------ nginx/ngx_js.c | 70 ++++++++++-------------------------------- nginx/ngx_js.h | 11 +++--- nginx/ngx_js_fetch.c | 38 ++++++++++------------ nginx/ngx_js_fetch.h | 2 +- nginx/ngx_stream_js_module.c | 55 +++++++++++++++++++++++---------- src/test/njs_externals_test.c | 18 +++++++++- src/test/njs_externals_test.h | 6 ++- src/test/njs_unit_test.c | 39 ++++++++++------------- 9 files changed, 151 insertions(+), 134 deletions(-) diffs (637 lines): diff -r 9371326836d2 -r 57ca02d7404c nginx/ngx_http_js_module.c --- a/nginx/ngx_http_js_module.c Mon Jun 26 16:47:17 2023 -0700 +++ b/nginx/ngx_http_js_module.c Wed Jun 28 22:15:57 2023 -0700 @@ -246,6 +246,7 @@ static void ngx_http_js_handle_vm_event( static void ngx_http_js_handle_event(ngx_http_request_t *r, njs_vm_event_t vm_event, njs_value_t *args, njs_uint_t nargs); +static njs_int_t ngx_js_http_init(njs_vm_t *vm); static ngx_int_t ngx_http_js_init(ngx_conf_t *cf); static char *ngx_http_js_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char *ngx_http_js_var(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); @@ -783,6 +784,33 @@ static njs_vm_meta_t ngx_http_js_metas = }; +njs_module_t ngx_js_http_module = { + .name = njs_str("http"), + .init = ngx_js_http_init, +}; + + +njs_module_t *njs_http_js_addon_modules[] = { + /* + * Shared addons should be in the same order and the same positions + * in all nginx modules. + */ + &ngx_js_ngx_module, + &ngx_js_fetch_module, +#ifdef NJS_HAVE_OPENSSL + &njs_webcrypto_module, +#endif +#ifdef NJS_HAVE_XML + &njs_xml_module, +#endif +#ifdef NJS_HAVE_ZLIB + &njs_zlib_module, +#endif + &ngx_js_http_module, + NULL, +}; + + static ngx_int_t ngx_http_js_content_handler(ngx_http_request_t *r) { @@ -4103,21 +4131,17 @@ ngx_http_js_handle_event(ngx_http_reques } -static ngx_int_t -ngx_http_js_externals_init(ngx_conf_t *cf, ngx_js_loc_conf_t *conf_in) +static njs_int_t +ngx_js_http_init(njs_vm_t *vm) { - ngx_http_js_loc_conf_t *conf = (ngx_http_js_loc_conf_t *) conf_in; - - ngx_http_js_request_proto_id = njs_vm_external_prototype(conf->vm, + ngx_http_js_request_proto_id = njs_vm_external_prototype(vm, ngx_http_js_ext_request, njs_nitems(ngx_http_js_ext_request)); if (ngx_http_js_request_proto_id < 0) { - ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "failed to add js request proto"); - return NGX_ERROR; + return NJS_ERROR; } - return NGX_OK; + return NJS_OK; } @@ -4132,11 +4156,11 @@ ngx_http_js_init_conf_vm(ngx_conf_t *cf, options.unhandled_rejection = NJS_VM_OPT_UNHANDLED_REJECTION_THROW; options.ops = &ngx_http_js_ops; options.metas = &ngx_http_js_metas; - options.addons = njs_js_addon_modules; + options.addons = njs_http_js_addon_modules; options.argv = ngx_argv; options.argc = ngx_argc; - return ngx_js_init_conf_vm(cf, conf, &options, ngx_http_js_externals_init); + return ngx_js_init_conf_vm(cf, conf, &options); } diff -r 9371326836d2 -r 57ca02d7404c nginx/ngx_js.c --- a/nginx/ngx_js.c Mon Jun 26 16:47:17 2023 -0700 +++ b/nginx/ngx_js.c Wed Jun 28 22:15:57 2023 -0700 @@ -9,7 +9,6 @@ #include #include #include "ngx_js.h" -#include "ngx_js_fetch.h" static njs_int_t ngx_js_ext_build(njs_vm_t *vm, njs_object_prop_t *prop, @@ -28,10 +27,7 @@ static njs_int_t ngx_js_ext_version(njs_ njs_value_t *value, njs_value_t *setval, njs_value_t *retval); static void ngx_js_cleanup_vm(void *data); - -extern njs_module_t njs_webcrypto_module; -extern njs_module_t njs_xml_module; -extern njs_module_t njs_zlib_module; +static njs_int_t ngx_js_core_init(njs_vm_t *vm); static njs_external_t ngx_js_ext_core[] = { @@ -156,16 +152,14 @@ static njs_external_t ngx_js_ext_core[] }; -njs_module_t *njs_js_addon_modules[] = { -#ifdef NJS_HAVE_OPENSSL - &njs_webcrypto_module, -#endif -#ifdef NJS_HAVE_XML - &njs_xml_module, -#endif -#ifdef NJS_HAVE_ZLIB - &njs_zlib_module, -#endif +njs_module_t ngx_js_ngx_module = { + .name = njs_str("ngx"), + .init = ngx_js_core_init, +}; + + +njs_module_t *njs_js_addon_modules_shared[] = { + &ngx_js_ngx_module, NULL, }; @@ -279,31 +273,22 @@ ngx_js_string(njs_vm_t *vm, njs_value_t } -ngx_int_t -ngx_js_core_init(njs_vm_t *vm, ngx_log_t *log) +static njs_int_t +ngx_js_core_init(njs_vm_t *vm) { - ngx_int_t rc; njs_int_t ret, proto_id; njs_str_t name; njs_opaque_value_t value; - rc = ngx_js_fetch_init(vm, log); - if (rc != NGX_OK) { - return NGX_ERROR; - } - proto_id = njs_vm_external_prototype(vm, ngx_js_ext_core, njs_nitems(ngx_js_ext_core)); if (proto_id < 0) { - ngx_log_error(NGX_LOG_EMERG, log, 0, "failed to add js core proto"); - return NGX_ERROR; + return NJS_ERROR; } ret = njs_vm_external_create(vm, njs_value_arg(&value), proto_id, NULL, 1); if (njs_slow_path(ret != NJS_OK)) { - ngx_log_error(NGX_LOG_EMERG, log, 0, - "njs_vm_external_create() failed\n"); - return NGX_ERROR; + return NJS_ERROR; } name.length = 3; @@ -311,11 +296,10 @@ ngx_js_core_init(njs_vm_t *vm, ngx_log_t ret = njs_vm_bind(vm, &name, njs_value_arg(&value), 1); if (njs_slow_path(ret != NJS_OK)) { - ngx_log_error(NGX_LOG_EMERG, log, 0, "njs_vm_bind() failed\n"); - return NGX_ERROR; + return NJS_ERROR; } - return NGX_OK; + return NJS_OK; } @@ -772,17 +756,13 @@ ngx_js_init_preload_vm(ngx_conf_t *cf, n njs_vm_opt_init(&options); options.init = 1; + options.addons = njs_js_addon_modules_shared; vm = njs_vm_create(&options); if (vm == NULL) { goto error; } - ret = ngx_js_core_init(vm, cf->log); - if (njs_slow_path(ret != NJS_OK)) { - goto error; - } - njs_str_t str = njs_str( "import fs from 'fs';" @@ -1005,8 +985,7 @@ ngx_js_merge_vm(ngx_conf_t *cf, ngx_js_l ngx_int_t ngx_js_init_conf_vm(ngx_conf_t *cf, ngx_js_loc_conf_t *conf, - njs_vm_opt_t *options, - ngx_int_t (*externals_init)(ngx_conf_t *cf, ngx_js_loc_conf_t *conf)) + njs_vm_opt_t *options) { size_t size; u_char *start, *end, *p; @@ -1110,21 +1089,6 @@ ngx_js_init_conf_vm(ngx_conf_t *cf, ngx_ } } - /* - * Core prototypes must be inited before externals_init() because - * the core prototype ids have to be identical in all the modules. - */ - - rc = ngx_js_core_init(conf->vm, cf->log); - if (njs_slow_path(rc != NJS_OK)) { - return NGX_ERROR; - } - - rc = externals_init(cf, conf); - if (rc != NGX_OK) { - return NGX_ERROR; - } - end = start + size; rc = njs_vm_compile(conf->vm, &start, end); diff -r 9371326836d2 -r 57ca02d7404c nginx/ngx_js.h --- a/nginx/ngx_js.h Mon Jun 26 16:47:17 2023 -0700 +++ b/nginx/ngx_js.h Wed Jun 28 22:15:57 2023 -0700 @@ -13,6 +13,7 @@ #include #include #include +#include "ngx_js_fetch.h" #define NGX_JS_UNSET 0 @@ -129,8 +130,7 @@ ngx_int_t ngx_js_merge_vm(ngx_conf_t *cf ngx_js_loc_conf_t *prev, ngx_int_t (*init_vm)(ngx_conf_t *cf, ngx_js_loc_conf_t *conf)); ngx_int_t ngx_js_init_conf_vm(ngx_conf_t *cf, ngx_js_loc_conf_t *conf, - njs_vm_opt_t *options, - ngx_int_t (*externals_init)(ngx_conf_t *cf, ngx_js_loc_conf_t *conf)); + njs_vm_opt_t *options); ngx_js_loc_conf_t *ngx_js_create_conf(ngx_conf_t *cf, size_t size); char * ngx_js_merge_conf(ngx_conf_t *cf, void *parent, void *child, ngx_int_t (*init_vm)(ngx_conf_t *cf, ngx_js_loc_conf_t *conf)); @@ -144,13 +144,14 @@ njs_int_t ngx_js_ext_constant(njs_vm_t * njs_int_t ngx_js_ext_flags(njs_vm_t *vm, njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, njs_value_t *retval); -ngx_int_t ngx_js_core_init(njs_vm_t *vm, ngx_log_t *log); - ngx_int_t ngx_js_string(njs_vm_t *vm, njs_value_t *value, njs_str_t *str); ngx_int_t ngx_js_integer(njs_vm_t *vm, njs_value_t *value, ngx_int_t *n); -extern njs_module_t *njs_js_addon_modules[]; +extern njs_module_t ngx_js_ngx_module; +extern njs_module_t njs_webcrypto_module; +extern njs_module_t njs_xml_module; +extern njs_module_t njs_zlib_module; #endif /* _NGX_JS_H_INCLUDED_ */ diff -r 9371326836d2 -r 57ca02d7404c nginx/ngx_js_fetch.c --- a/nginx/ngx_js_fetch.c Mon Jun 26 16:47:17 2023 -0700 +++ b/nginx/ngx_js_fetch.c Wed Jun 28 22:15:57 2023 -0700 @@ -277,6 +277,8 @@ static njs_int_t ngx_fetch_flag(njs_vm_t static njs_int_t ngx_fetch_flag_set(njs_vm_t *vm, const ngx_js_entry_t *entries, njs_value_t *value, const char *type); +static njs_int_t ngx_js_fetch_init(njs_vm_t *vm); + static const ngx_js_entry_t ngx_js_fetch_credentials[] = { { njs_str("same-origin"), CREDENTIALS_SAME_ORIGIN }, @@ -652,6 +654,12 @@ static njs_int_t ngx_http_js_fetch_re static njs_int_t ngx_http_js_fetch_headers_proto_id; +njs_module_t ngx_js_fetch_module = { + .name = njs_str("fetch"), + .init = ngx_js_fetch_init, +}; + + njs_int_t ngx_js_ext_fetch(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval) @@ -4033,8 +4041,8 @@ ngx_js_fetch_function_bind(njs_vm_t *vm, } -ngx_int_t -ngx_js_fetch_init(njs_vm_t *vm, ngx_log_t *log) +static njs_int_t +ngx_js_fetch_init(njs_vm_t *vm) { njs_int_t ret; @@ -4046,52 +4054,40 @@ ngx_js_fetch_init(njs_vm_t *vm, ngx_log_ ngx_js_ext_http_headers, njs_nitems(ngx_js_ext_http_headers)); if (ngx_http_js_fetch_headers_proto_id < 0) { - ngx_log_error(NGX_LOG_EMERG, log, 0, - "failed to add js fetch Headers proto"); - return NGX_ERROR; + return NJS_ERROR; } ngx_http_js_fetch_request_proto_id = njs_vm_external_prototype(vm, ngx_js_ext_http_request, njs_nitems(ngx_js_ext_http_request)); if (ngx_http_js_fetch_request_proto_id < 0) { - ngx_log_error(NGX_LOG_EMERG, log, 0, - "failed to add js fetch Request proto"); - return NGX_ERROR; + return NJS_ERROR; } ngx_http_js_fetch_response_proto_id = njs_vm_external_prototype(vm, ngx_js_ext_http_response, njs_nitems(ngx_js_ext_http_response)); if (ngx_http_js_fetch_response_proto_id < 0) { - ngx_log_error(NGX_LOG_EMERG, log, 0, - "failed to add js fetch Response proto"); - return NGX_ERROR; + return NJS_ERROR; } ret = ngx_js_fetch_function_bind(vm, &headers, ngx_js_ext_headers_constructor, 1); if (ret != NJS_OK) { - ngx_log_error(NGX_LOG_EMERG, log, 0, - "failed to bind Headers ctor"); - return NGX_ERROR; + return NJS_ERROR; } ret = ngx_js_fetch_function_bind(vm, &request, ngx_js_ext_request_constructor, 1); if (ret != NJS_OK) { - ngx_log_error(NGX_LOG_EMERG, log, 0, - "failed to bind Request ctor"); - return NGX_ERROR; + return NJS_ERROR; } ret = ngx_js_fetch_function_bind(vm, &response, ngx_js_ext_response_constructor, 1); if (ret != NJS_OK) { - ngx_log_error(NGX_LOG_EMERG, log, 0, - "failed to bind Response ctor"); - return NGX_ERROR; + return NJS_ERROR; } - return NGX_OK; + return NJS_OK; } diff -r 9371326836d2 -r 57ca02d7404c nginx/ngx_js_fetch.h --- a/nginx/ngx_js_fetch.h Mon Jun 26 16:47:17 2023 -0700 +++ b/nginx/ngx_js_fetch.h Wed Jun 28 22:15:57 2023 -0700 @@ -12,7 +12,7 @@ njs_int_t ngx_js_ext_fetch(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t level, njs_value_t *retval); -ngx_int_t ngx_js_fetch_init(njs_vm_t *vm, ngx_log_t *log); +extern njs_module_t ngx_js_fetch_module; #endif /* _NGX_JS_FETCH_H_INCLUDED_ */ diff -r 9371326836d2 -r 57ca02d7404c nginx/ngx_stream_js_module.c --- a/nginx/ngx_stream_js_module.c Mon Jun 26 16:47:17 2023 -0700 +++ b/nginx/ngx_stream_js_module.c Wed Jun 28 22:15:57 2023 -0700 @@ -114,6 +114,8 @@ static size_t ngx_stream_js_max_response static void ngx_stream_js_handle_event(ngx_stream_session_t *s, njs_vm_event_t vm_event, njs_value_t *args, njs_uint_t nargs); +static njs_int_t ngx_js_stream_init(njs_vm_t *vm); +static ngx_int_t ngx_stream_js_init(ngx_conf_t *cf); static char *ngx_stream_js_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char *ngx_stream_js_var(ngx_conf_t *cf, ngx_command_t *cmd, @@ -123,7 +125,6 @@ static ngx_int_t ngx_stream_js_init_conf static void *ngx_stream_js_create_srv_conf(ngx_conf_t *cf); static char *ngx_stream_js_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child); -static ngx_int_t ngx_stream_js_init(ngx_conf_t *cf); static ngx_ssl_t *ngx_stream_js_ssl(njs_vm_t *vm, ngx_stream_session_t *s); static ngx_flag_t ngx_stream_js_ssl_verify(njs_vm_t *vm, @@ -565,6 +566,33 @@ static njs_int_t ngx_stream_js_sessio static njs_int_t ngx_stream_js_session_flags_proto_id; +njs_module_t ngx_js_stream_module = { + .name = njs_str("stream"), + .init = ngx_js_stream_init, +}; + + +njs_module_t *njs_stream_js_addon_modules[] = { + /* + * Shared addons should be in the same order and the same positions + * in all nginx modules. + */ + &ngx_js_ngx_module, + &ngx_js_fetch_module, +#ifdef NJS_HAVE_OPENSSL + &njs_webcrypto_module, +#endif +#ifdef NJS_HAVE_XML + &njs_xml_module, +#endif +#ifdef NJS_HAVE_ZLIB + &njs_zlib_module, +#endif + &ngx_js_stream_module, + NULL, +}; + + static ngx_int_t ngx_stream_js_access_handler(ngx_stream_session_t *s) { @@ -1669,30 +1697,24 @@ ngx_stream_js_handle_event(ngx_stream_se } -static ngx_int_t -ngx_stream_js_externals_init(ngx_conf_t *cf, ngx_js_loc_conf_t *conf_in) +static njs_int_t +ngx_js_stream_init(njs_vm_t *vm) { - ngx_stream_js_srv_conf_t *conf = (ngx_stream_js_srv_conf_t *) conf_in; - - ngx_stream_js_session_proto_id = njs_vm_external_prototype(conf->vm, + ngx_stream_js_session_proto_id = njs_vm_external_prototype(vm, ngx_stream_js_ext_session, njs_nitems(ngx_stream_js_ext_session)); if (ngx_stream_js_session_proto_id < 0) { - ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "failed to add js session proto"); - return NGX_ERROR; + return NJS_ERROR; } - ngx_stream_js_session_flags_proto_id = njs_vm_external_prototype(conf->vm, + ngx_stream_js_session_flags_proto_id = njs_vm_external_prototype(vm, ngx_stream_js_ext_session_flags, njs_nitems(ngx_stream_js_ext_session_flags)); if (ngx_stream_js_session_flags_proto_id < 0) { - ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "failed to add js session flags proto"); - return NGX_ERROR; + return NJS_ERROR; } - return NGX_OK; + return NJS_OK; } @@ -1707,12 +1729,11 @@ ngx_stream_js_init_conf_vm(ngx_conf_t *c options.unhandled_rejection = NJS_VM_OPT_UNHANDLED_REJECTION_THROW; options.ops = &ngx_stream_js_ops; options.metas = &ngx_stream_js_metas; - options.addons = njs_js_addon_modules; + options.addons = njs_stream_js_addon_modules; options.argv = ngx_argv; options.argc = ngx_argc; - return ngx_js_init_conf_vm(cf, conf, &options, - ngx_stream_js_externals_init); + return ngx_js_init_conf_vm(cf, conf, &options); } diff -r 9371326836d2 -r 57ca02d7404c src/test/njs_externals_test.c --- a/src/test/njs_externals_test.c Mon Jun 26 16:47:17 2023 -0700 +++ b/src/test/njs_externals_test.c Wed Jun 28 22:15:57 2023 -0700 @@ -26,6 +26,8 @@ typedef struct { } njs_unit_test_prop_t; +static njs_int_t njs_externals_262_init(njs_vm_t *vm); +static njs_int_t njs_externals_shared_init(njs_vm_t *vm); njs_int_t njs_array_buffer_detach(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval); @@ -33,6 +35,18 @@ njs_int_t njs_array_buffer_detach(njs_vm static njs_int_t njs_external_r_proto_id; +njs_module_t njs_unit_test_262_module = { + .name = njs_str("$262"), + .init = njs_externals_262_init, +}; + + +njs_module_t njs_unit_test_external_module = { + .name = njs_str("external"), + .init = njs_externals_shared_init, +}; + + static njs_int_t lvlhsh_unit_test_key_test(njs_lvlhsh_query_t *lhq, void *data) { @@ -1131,7 +1145,7 @@ njs_externals_init_internal(njs_vm_t *vm } -njs_int_t +static njs_int_t njs_externals_262_init(njs_vm_t *vm) { njs_int_t ret, proto_id; @@ -1162,7 +1176,7 @@ njs_externals_262_init(njs_vm_t *vm) } -njs_int_t +static njs_int_t njs_externals_shared_init(njs_vm_t *vm) { return njs_externals_init_internal(vm, njs_test_requests, 1, 1); diff -r 9371326836d2 -r 57ca02d7404c src/test/njs_externals_test.h --- a/src/test/njs_externals_test.h Mon Jun 26 16:47:17 2023 -0700 +++ b/src/test/njs_externals_test.h Wed Jun 28 22:15:57 2023 -0700 @@ -24,8 +24,6 @@ typedef struct { } njs_external_ev_t; -njs_int_t njs_externals_shared_init(njs_vm_t *vm); -njs_int_t njs_externals_262_init(njs_vm_t *vm); njs_int_t njs_externals_init(njs_vm_t *vm); njs_int_t njs_external_env_init(njs_external_env_t *env); njs_int_t njs_external_call(njs_vm_t *vm, const njs_str_t *fname, @@ -33,4 +31,8 @@ njs_int_t njs_external_call(njs_vm_t *vm njs_int_t njs_external_process_events(njs_vm_t *vm, njs_external_env_t *env); +extern njs_module_t njs_unit_test_262_module; +extern njs_module_t njs_unit_test_external_module; + + #endif /* _NJS_EXTERNALS_TEST_H_INCLUDED_ */ diff -r 9371326836d2 -r 57ca02d7404c src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Mon Jun 26 16:47:17 2023 -0700 +++ b/src/test/njs_unit_test.c Wed Jun 28 22:15:57 2023 -0700 @@ -23683,6 +23683,19 @@ done: } +njs_module_t *njs_unit_test_addon_modules[] = { + &njs_unit_test_262_module, + NULL, +}; + + +njs_module_t *njs_unit_test_addon_external_modules[] = { + &njs_unit_test_262_module, + &njs_unit_test_external_module, + NULL, +}; + + static njs_int_t njs_unit_test(njs_unit_test_t tests[], size_t num, njs_str_t *name, njs_opts_t *opts, njs_stat_t *stat) @@ -23716,6 +23729,8 @@ njs_unit_test(njs_unit_test_t tests[], s options.module = opts->module; options.unsafe = opts->unsafe; options.backtrace = opts->backtrace; + options.addons = opts->externals ? njs_unit_test_addon_external_modules + : njs_unit_test_addon_modules; vm = njs_vm_create(&options); if (vm == NULL) { @@ -23723,18 +23738,6 @@ njs_unit_test(njs_unit_test_t tests[], s goto done; } - ret = njs_externals_262_init(vm); - if (ret != NJS_OK) { - goto done; - } - - if (opts->externals) { - ret = njs_externals_shared_init(vm); - if (ret != NJS_OK) { - goto done; - } - } - start = tests[i].script.start; end = start + tests[i].script.length; @@ -23855,6 +23858,8 @@ njs_interactive_test(njs_unit_test_t tes options.init = 1; options.interactive = 1; options.backtrace = 1; + options.addons = opts->externals ? njs_unit_test_addon_external_modules + : njs_unit_test_addon_modules; vm = njs_vm_create(&options); if (vm == NULL) { @@ -23862,17 +23867,7 @@ njs_interactive_test(njs_unit_test_t tes goto done; } - ret = njs_externals_262_init(vm); - if (ret != NJS_OK) { - goto done; - } - if (opts->externals) { - ret = njs_externals_shared_init(vm); - if (ret != NJS_OK) { - goto done; - } - ret = njs_externals_init(vm); if (ret != NJS_OK) { goto done; From xeioex at nginx.com Fri Jun 30 03:39:23 2023 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Fri, 30 Jun 2023 03:39:23 +0000 Subject: [njs] Improved Error.prototype.toString(). Message-ID: details: https://hg.nginx.org/njs/rev/bc69e9407e66 branches: changeset: 2167:bc69e9407e66 user: Dmitry Volyntsev date: Wed Jun 28 22:15:59 2023 -0700 description: Improved Error.prototype.toString(). Making method more generic by using njs_vm_property() when looking for "name" and "message" properties in the prototype chain. diffstat: src/njs_error.c | 31 ++++++++++++------------------- 1 files changed, 12 insertions(+), 19 deletions(-) diffs (56 lines): diff -r 57ca02d7404c -r bc69e9407e66 src/njs_error.c --- a/src/njs_error.c Wed Jun 28 22:15:57 2023 -0700 +++ b/src/njs_error.c Wed Jun 28 22:15:59 2023 -0700 @@ -597,15 +597,14 @@ static njs_int_t njs_error_to_string2(njs_vm_t *vm, njs_value_t *retval, const njs_value_t *error, njs_bool_t want_stack) { - size_t length; - u_char *p; - njs_int_t ret; - njs_object_t *error_object; - njs_value_t value1, value2; - njs_value_t *name_value, *message_value; - njs_string_prop_t name, message; - njs_lvlhsh_query_t lhq; + size_t length; + u_char *p; + njs_int_t ret; + njs_value_t value1, value2; + njs_value_t *name_value, *message_value; + njs_string_prop_t name, message; + static const njs_value_t string_message = njs_string("message"); static const njs_value_t default_name = njs_string("Error"); njs_assert(njs_is_object(error)); @@ -621,12 +620,9 @@ njs_error_to_string2(njs_vm_t *vm, njs_v } } - error_object = njs_object(error); - - njs_object_property_init(&lhq, &njs_string_name, NJS_NAME_HASH); - - ret = njs_object_property(vm, error_object, &lhq, &value1); - + ret = njs_value_property(vm, (njs_value_t *) error, + njs_value_arg(&njs_string_name), + &value1); if (njs_slow_path(ret == NJS_ERROR)) { return ret; } @@ -644,11 +640,8 @@ njs_error_to_string2(njs_vm_t *vm, njs_v (void) njs_string_prop(&name, name_value); - lhq.key_hash = NJS_MESSAGE_HASH; - lhq.key = njs_str_value("message"); - - ret = njs_object_property(vm, error_object, &lhq, &value2); - + ret = njs_value_property(vm, (njs_value_t *) error, + njs_value_arg(&string_message), &value2); if (njs_slow_path(ret == NJS_ERROR)) { return ret; } From xeioex at nginx.com Fri Jun 30 03:39:25 2023 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Fri, 30 Jun 2023 03:39:25 +0000 Subject: [njs] Introduced njs_vm_bind_handler(). Message-ID: details: https://hg.nginx.org/njs/rev/7aa15ae3d8be branches: changeset: 2168:7aa15ae3d8be user: Dmitry Volyntsev date: Thu Jun 29 18:58:45 2023 -0700 description: Introduced njs_vm_bind_handler(). diffstat: src/njs.h | 3 +++ src/njs_vm.c | 49 +++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 44 insertions(+), 8 deletions(-) diffs (86 lines): diff -r bc69e9407e66 -r 7aa15ae3d8be src/njs.h --- a/src/njs.h Wed Jun 28 22:15:59 2023 -0700 +++ b/src/njs.h Thu Jun 29 18:58:45 2023 -0700 @@ -424,6 +424,9 @@ NJS_EXPORT void njs_disassembler(njs_vm_ NJS_EXPORT njs_int_t njs_vm_bind(njs_vm_t *vm, const njs_str_t *var_name, const njs_value_t *value, njs_bool_t shared); +njs_int_t njs_vm_bind_handler(njs_vm_t *vm, const njs_str_t *var_name, + njs_prop_handler_t handler, uint16_t magic16, uint32_t magic32, + njs_bool_t shared); NJS_EXPORT njs_int_t njs_vm_value(njs_vm_t *vm, const njs_str_t *path, njs_value_t *retval); NJS_EXPORT njs_function_t *njs_vm_function(njs_vm_t *vm, const njs_str_t *name); diff -r bc69e9407e66 -r 7aa15ae3d8be src/njs_vm.c --- a/src/njs_vm.c Wed Jun 28 22:15:59 2023 -0700 +++ b/src/njs_vm.c Thu Jun 29 18:58:45 2023 -0700 @@ -792,21 +792,15 @@ njs_vm_value(njs_vm_t *vm, const njs_str } -njs_int_t -njs_vm_bind(njs_vm_t *vm, const njs_str_t *var_name, const njs_value_t *value, +static njs_int_t +njs_vm_bind2(njs_vm_t *vm, const njs_str_t *var_name, njs_object_prop_t *prop, njs_bool_t shared) { njs_int_t ret; njs_object_t *global; njs_lvlhsh_t *hash; - njs_object_prop_t *prop; njs_lvlhsh_query_t lhq; - prop = njs_object_prop_alloc(vm, &njs_value_undefined, value, 1); - if (njs_slow_path(prop == NULL)) { - return NJS_ERROR; - } - ret = njs_string_new(vm, &prop->name, var_name->start, var_name->length, 0); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; @@ -832,6 +826,45 @@ njs_vm_bind(njs_vm_t *vm, const njs_str_ } +njs_int_t +njs_vm_bind(njs_vm_t *vm, const njs_str_t *var_name, const njs_value_t *value, + njs_bool_t shared) +{ + njs_object_prop_t *prop; + + prop = njs_object_prop_alloc(vm, &njs_value_undefined, value, 1); + if (njs_slow_path(prop == NULL)) { + return NJS_ERROR; + } + + return njs_vm_bind2(vm, var_name, prop, shared); +} + + +njs_int_t +njs_vm_bind_handler(njs_vm_t *vm, const njs_str_t *var_name, + njs_prop_handler_t handler, uint16_t magic16, uint32_t magic32, + njs_bool_t shared) +{ + njs_object_prop_t *prop; + + prop = njs_object_prop_alloc(vm, &njs_string_empty, + &njs_value_invalid, 1); + if (njs_slow_path(prop == NULL)) { + return NJS_ERROR; + } + + prop->type = NJS_PROPERTY_HANDLER; + prop->u.value.type = NJS_INVALID; + prop->u.value.data.truth = 1; + njs_prop_magic16(prop) = magic16; + njs_prop_magic32(prop) = magic32; + njs_prop_handler(prop) = handler; + + return njs_vm_bind2(vm, var_name, prop, shared); +} + + void njs_value_string_get(njs_value_t *value, njs_str_t *dst) { From xeioex at nginx.com Fri Jun 30 03:46:59 2023 From: xeioex at nginx.com (Dmitry Volyntsev) Date: Fri, 30 Jun 2023 03:46:59 +0000 Subject: [njs] Modules: introduced ngx.worker_id. Message-ID: details: https://hg.nginx.org/njs/rev/453f5503de13 branches: changeset: 2169:453f5503de13 user: Dmitry Volyntsev date: Thu Jun 29 20:44:14 2023 -0700 description: Modules: introduced ngx.worker_id. worker_id corresponds to an nginx internal worker id. The value is between 0 and worker_processes - 1. diffstat: nginx/ngx_js.c | 20 ++++++++++++++++++++ ts/ngx_core.d.ts | 6 ++++++ 2 files changed, 26 insertions(+), 0 deletions(-) diffs (60 lines): diff -r 7aa15ae3d8be -r 453f5503de13 nginx/ngx_js.c --- a/nginx/ngx_js.c Thu Jun 29 18:58:45 2023 -0700 +++ b/nginx/ngx_js.c Thu Jun 29 20:44:14 2023 -0700 @@ -25,6 +25,8 @@ static njs_int_t ngx_js_ext_prefix(njs_v njs_value_t *value, njs_value_t *setval, njs_value_t *retval); static njs_int_t ngx_js_ext_version(njs_vm_t *vm, njs_object_prop_t *prop, njs_value_t *value, njs_value_t *setval, njs_value_t *retval); +static njs_int_t ngx_js_ext_worker_id(njs_vm_t *vm, njs_object_prop_t *prop, + njs_value_t *value, njs_value_t *setval, njs_value_t *retval); static void ngx_js_cleanup_vm(void *data); static njs_int_t ngx_js_core_init(njs_vm_t *vm); @@ -149,6 +151,15 @@ static njs_external_t ngx_js_ext_core[] } }, + { + .flags = NJS_EXTERN_PROPERTY, + .name.string = njs_str("worker_id"), + .enumerable = 1, + .u.property = { + .handler = ngx_js_ext_worker_id, + } + }, + }; @@ -453,6 +464,15 @@ ngx_js_ext_version(njs_vm_t *vm, njs_obj njs_int_t +ngx_js_ext_worker_id(njs_vm_t *vm, njs_object_prop_t *prop, njs_value_t *value, + njs_value_t *setval, njs_value_t *retval) +{ + njs_value_number_set(retval, ngx_worker); + return NJS_OK; +} + + +njs_int_t ngx_js_ext_log(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t level, njs_value_t *retval) { diff -r 7aa15ae3d8be -r 453f5503de13 ts/ngx_core.d.ts --- a/ts/ngx_core.d.ts Thu Jun 29 18:58:45 2023 -0700 +++ b/ts/ngx_core.d.ts Thu Jun 29 20:44:14 2023 -0700 @@ -311,6 +311,12 @@ interface NgxObject { * @since 0.5.1 */ readonly WARN: number; + /** + * A number corresponding to the current worker process id. + * Can have values from 0 to worker_processes - 1. + * @since 0.8.0 + */ + readonly worker_id: number; } From v.zhestikov at f5.com Fri Jun 30 13:41:06 2023 From: v.zhestikov at f5.com (Vadim Zhestikov) Date: Fri, 30 Jun 2023 13:41:06 +0000 Subject: [njs] Added constructor name for async function. Message-ID: details: https://hg.nginx.org/njs/rev/e85aaeaa7e55 branches: changeset: 2170:e85aaeaa7e55 user: Vadim Zhestikov date: Fri Jun 30 06:38:36 2023 -0700 description: Added constructor name for async function. diffstat: src/njs_async.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diffs (12 lines): diff -r 453f5503de13 -r e85aaeaa7e55 src/njs_async.c --- a/src/njs_async.c Thu Jun 29 20:44:14 2023 -0700 +++ b/src/njs_async.c Fri Jun 30 06:38:36 2023 -0700 @@ -163,6 +163,8 @@ njs_async_context_free(njs_vm_t *vm, njs static const njs_object_prop_t njs_async_constructor_properties[] = { + NJS_DECLARE_PROP_NAME("AsyncFunction"), + NJS_DECLARE_PROP_LENGTH(1), NJS_DECLARE_PROP_HANDLER("prototype", njs_object_prototype_create, 0, 0, 0),