1010import robaho .net .httpserver .http2 .HTTP2Exception ;
1111
1212import java .util .List ;
13+ import java .util .Map ;
1314
1415import com .sun .net .httpserver .Headers ;
1516
@@ -117,8 +118,6 @@ private int decodeDynamicTableSizeUpdate(byte[] buffer, int index) throws HTTP2E
117118 int size = pair .value ;
118119 index = pair .index ;
119120
120- System .out .println ("updating dynamic table size to " +size );
121-
122121 if (size > 4096 ) { // Assuming 4096 is the maximum size for the dynamic table
123122 throw new HTTP2Exception (HTTP2ErrorCode .COMPRESSION_ERROR , "Dynamic table size update too large: " + size );
124123 }
@@ -233,18 +232,27 @@ private static byte[] encodeHeadersFrame(Headers headers) {
233232 }
234233
235234 private static byte [] encodeHeader (String name , String value ) {
236- byte [] nameBytes = name .getBytes ();
237- byte [] valueBytes = value .getBytes ();
235+ if (":status" .equals (name )) {
236+ byte [] result = RFC7541Parser .STATUSES .get (value );
237+ if (result !=null ) return result ;
238+ }
239+ var index = RFC7541Parser .getIndex (name );
240+
238241 byte [] buffer = new byte [1 ];
239242 buffer [0 ]=0x00 ; // Literal Header Field without Indexing
240243
241- // Encode header name
242- byte [] header = encodeString (nameBytes );
243- buffer = Arrays .copyOf (buffer , buffer .length + header .length );
244- System .arraycopy (header , 0 , buffer , buffer .length - header .length , header .length );
244+ if (index !=null ) {
245+ buffer = encodeIndexedField (index ,4 );
246+ } else {
247+ byte [] nameBytes = name .getBytes ();
248+ byte [] header = encodeString (nameBytes );
249+ buffer = Arrays .copyOf (buffer , buffer .length + header .length );
250+ System .arraycopy (header , 0 , buffer , buffer .length - header .length , header .length );
251+ }
245252
246253 // Encode header value
247- header = encodeString (valueBytes );
254+ byte [] valueBytes = value .getBytes ();
255+ byte [] header = encodeString (valueBytes );
248256 buffer = Arrays .copyOf (buffer , buffer .length + header .length );
249257 System .arraycopy (header , 0 , buffer , buffer .length - header .length , header .length );
250258
@@ -267,11 +275,44 @@ private static byte[] encodeString(byte[] value) {
267275 return buffer ;
268276 }
269277
278+ private static byte [] encodeIndexedField (int index , int prefixBits ) {
279+ byte [] buffer = new byte [1 ];
280+ int mask = (1 << prefixBits ) - 1 ;
281+ if (index < mask ) {
282+ buffer [0 ] = (byte ) index ;
283+ return buffer ;
284+ }
285+ buffer [0 ] = (byte ) mask ;
286+ index -= mask ;
287+ while (index >= 128 ) {
288+ buffer = Arrays .copyOf (buffer , buffer .length + 1 );
289+ buffer [buffer .length - 1 ] = (byte ) ((index & 0x7F ) | 0x80 );
290+ index >>>= 7 ;
291+ }
292+ buffer = Arrays .copyOf (buffer , buffer .length + 1 );
293+ buffer [buffer .length - 1 ] = (byte ) index ;
294+ return buffer ;
295+ }
296+
270297}
271298
272299class RFC7541Parser {
273300
274301 private static final HTTP2HeaderField [] STATIC_HEADER_TABLE = new HTTP2HeaderField [62 ];
302+ static final Map <String ,byte []> STATUSES = Map .of (
303+ "200" ,indexedField (8 ),
304+ "204" ,indexedField (9 ),
305+ "206" ,indexedField (10 ),
306+ "304" ,indexedField (11 ),
307+ "400" ,indexedField (12 ),
308+ "404" ,indexedField (13 ),
309+ "500" ,indexedField (13 ));
310+
311+ private static byte [] indexedField (int index ) {
312+ byte [] buffer = new byte [1 ];
313+ buffer [0 ] = (byte ) (0x80 | index );
314+ return buffer ;
315+ }
275316
276317 static {
277318 STATIC_HEADER_TABLE [1 ] = new HTTP2HeaderField (":authority" , null );
@@ -337,6 +378,18 @@ class RFC7541Parser {
337378 STATIC_HEADER_TABLE [61 ] = new HTTP2HeaderField ("www-authenticate" , null );
338379 }
339380
381+ private static final Map <String , Integer > STATIC_HEADER_NAME_TO_INDEX = Arrays .stream (STATIC_HEADER_TABLE )
382+ .filter (f -> f != null )
383+ .collect (java .util .stream .Collectors .toMap (
384+ f -> f .name ,
385+ f -> Arrays .asList (STATIC_HEADER_TABLE ).indexOf (f ),
386+ (a , b ) -> a
387+ ));
388+
389+ public static Integer getIndex (String name ) {
390+ return STATIC_HEADER_NAME_TO_INDEX .get (name );
391+ }
392+
340393 public static HTTP2HeaderField getHeaderField (int index ) {
341394 if (index < 1 || index >= STATIC_HEADER_TABLE .length ) {
342395 return null ;
0 commit comments