@@ -77,6 +77,7 @@ typedef struct h2_config {
7777 int output_buffered ;
7878 apr_interval_time_t stream_timeout ;/* beam timeout */
7979 int max_data_frame_len ; /* max # bytes in a single h2 DATA frame */
80+ int max_hd_block_len ; /* max # bytes in a response header block */
8081 int proxy_requests ; /* act as forward proxy */
8182 int h2_websockets ; /* if mod_h2 negotiating WebSockets */
8283} h2_config ;
@@ -117,6 +118,7 @@ static h2_config defconf = {
117118 1 , /* stream output buffered */
118119 -1 , /* beam timeout */
119120 0 , /* max DATA frame len, 0 == no extra limit */
121+ 0 , /* max header block len, 0 == no extra limit */
120122 0 , /* forward proxy */
121123 0 , /* WebSockets negotiation, enabled */
122124};
@@ -165,6 +167,7 @@ void *h2_config_create_svr(apr_pool_t *pool, server_rec *s)
165167 conf -> output_buffered = DEF_VAL ;
166168 conf -> stream_timeout = DEF_VAL ;
167169 conf -> max_data_frame_len = DEF_VAL ;
170+ conf -> max_hd_block_len = DEF_VAL ;
168171 conf -> proxy_requests = DEF_VAL ;
169172 conf -> h2_websockets = DEF_VAL ;
170173 return conf ;
@@ -216,6 +219,7 @@ static void *h2_config_merge(apr_pool_t *pool, void *basev, void *addv)
216219 n -> padding_always = H2_CONFIG_GET (add , base , padding_always );
217220 n -> stream_timeout = H2_CONFIG_GET (add , base , stream_timeout );
218221 n -> max_data_frame_len = H2_CONFIG_GET (add , base , max_data_frame_len );
222+ n -> max_hd_block_len = H2_CONFIG_GET (add , base , max_hd_block_len );
219223 n -> proxy_requests = H2_CONFIG_GET (add , base , proxy_requests );
220224 n -> h2_websockets = H2_CONFIG_GET (add , base , h2_websockets );
221225 return n ;
@@ -313,6 +317,8 @@ static apr_int64_t h2_srv_config_geti64(const h2_config *conf, h2_config_var_t v
313317 return H2_CONFIG_GET (conf , & defconf , proxy_requests );
314318 case H2_CONF_WEBSOCKETS :
315319 return H2_CONFIG_GET (conf , & defconf , h2_websockets );
320+ case H2_CONF_MAX_HEADER_BLOCK_LEN :
321+ return H2_CONFIG_GET (conf , & defconf , max_hd_block_len );
316322 default :
317323 return DEF_VAL ;
318324 }
@@ -381,6 +387,8 @@ static void h2_srv_config_seti(h2_config *conf, h2_config_var_t var, int val)
381387 case H2_CONF_WEBSOCKETS :
382388 H2_CONFIG_SET (conf , h2_websockets , val );
383389 break ;
390+ case H2_CONF_MAX_HEADER_BLOCK_LEN :
391+ H2_CONFIG_SET (conf , max_hd_block_len , val );
384392 default :
385393 break ;
386394 }
@@ -650,6 +658,17 @@ static const char *h2_conf_set_max_data_frame_len(cmd_parms *cmd,
650658 return NULL ;
651659}
652660
661+ static const char * h2_conf_set_max_hd_block_len (cmd_parms * cmd ,
662+ void * dirconf , const char * value )
663+ {
664+ int val = (int )apr_atoi64 (value );
665+ if (val < 0 ) {
666+ return "value must be 0 or larger" ;
667+ }
668+ CONFIG_CMD_SET (cmd , dirconf , H2_CONF_MAX_HEADER_BLOCK_LEN , val );
669+ return NULL ;
670+ }
671+
653672static const char * h2_conf_set_session_extra_files (cmd_parms * cmd ,
654673 void * dirconf , const char * value )
655674{
@@ -1071,6 +1090,8 @@ const command_rec h2_cmds[] = {
10711090 RSRC_CONF , "set stream timeout" ),
10721091 AP_INIT_TAKE1 ("H2MaxDataFrameLen" , h2_conf_set_max_data_frame_len , NULL ,
10731092 RSRC_CONF , "maximum number of bytes in a single HTTP/2 DATA frame" ),
1093+ AP_INIT_TAKE1 ("H2MaxHeaderBlockLen" , h2_conf_set_max_hd_block_len , NULL ,
1094+ RSRC_CONF , "maximum number of bytes in a response header block" ),
10741095 AP_INIT_TAKE2 ("H2EarlyHint" , h2_conf_add_early_hint , NULL ,
10751096 OR_FILEINFO |OR_AUTHCFG , "add a a 'Link:' header for a 103 Early Hints response." ),
10761097 AP_INIT_TAKE1 ("H2ProxyRequests" , h2_conf_set_proxy_requests , NULL ,
0 commit comments