@@ -30,6 +30,7 @@ public class NettyHandler extends ChannelInboundHandlerAdapter {
3030 private final int bufferSize ;
3131 private final boolean defaultHeaders ;
3232 private final long maxRequestSize ;
33+ private final int maxFormFields ;
3334 private long contentLength ;
3435 private long chunkSize ;
3536 private final boolean http2 ;
@@ -42,12 +43,14 @@ public NettyHandler(
4243 NettyDateService serverDate ,
4344 Context .Selector contextSelector ,
4445 long maxRequestSize ,
46+ int maxFormFields ,
4547 int bufferSize ,
4648 boolean defaultHeaders ,
4749 boolean http2 ) {
4850 this .serverDate = serverDate ;
4951 this .contextSelector = contextSelector ;
5052 this .maxRequestSize = maxRequestSize ;
53+ this .maxFormFields = maxFormFields ;
5154 this .bufferSize = bufferSize ;
5255 this .defaultHeaders = defaultHeaders ;
5356 this .http2 = http2 ;
@@ -84,7 +87,7 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) {
8487 if (contentLength > 0 || isTransferEncodingChunked (req )) {
8588 context .httpDataFactory = new DefaultHttpDataFactory (bufferSize );
8689 context .httpDataFactory .setBaseDir (app .getTmpdir ().toString ());
87- context .setDecoder (newDecoder (req , context .httpDataFactory ));
90+ context .setDecoder (newDecoder (req , context .httpDataFactory , maxFormFields ));
8891 } else {
8992 // no body, move on
9093 router .match (context ).execute (context );
@@ -95,10 +98,11 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) {
9598 try {
9699 // when decoder == null, chunk is always a LastHttpContent.EMPTY, ignore it
97100 if (context .decoder != null ) {
98- offer (context , chunk );
99- Router .Match route = router .match (context );
100- resetDecoderState (context , !route .matches ());
101- route .execute (context );
101+ if (offer (context , chunk )) {
102+ Router .Match route = router .match (context );
103+ resetDecoderState (context , !route .matches ());
104+ route .execute (context );
105+ }
102106 }
103107 } finally {
104108 release (chunk );
@@ -232,14 +236,16 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
232236 }
233237 }
234238
235- private void offer (NettyContext context , HttpContent chunk ) {
239+ private boolean offer (NettyContext context , HttpContent chunk ) {
236240 try {
237241 context .decoder .offer (chunk );
238- } catch (HttpPostRequestDecoder .ErrorDataDecoderException
239- | HttpPostRequestDecoder .TooLongFormFieldException
240- | HttpPostRequestDecoder .TooManyFormFieldsException x ) {
241- resetDecoderState (context , true );
242- context .sendError (x , StatusCode .BAD_REQUEST );
242+ return true ;
243+ } catch (Exception x ) {
244+ if (x instanceof HttpPostRequestDecoder .TooManyFormFieldsException ) {
245+ context .setAttribute ("__too_many_fields" , x );
246+ }
247+ router .match (context ).execute (context , Route .FORM_DECODER_HANDLER );
248+ return false ;
243249 }
244250 }
245251
@@ -257,14 +263,16 @@ private void resetDecoderState(NettyContext context, boolean destroy) {
257263 }
258264
259265 private static InterfaceHttpPostRequestDecoder newDecoder (
260- HttpRequest request , HttpDataFactory factory ) {
266+ HttpRequest request , HttpDataFactory factory , int maxFormFields ) {
261267 String contentType = request .headers ().get (HttpHeaderNames .CONTENT_TYPE );
262268 if (contentType != null ) {
263269 String lowerContentType = contentType .toLowerCase ();
264270 if (lowerContentType .startsWith (MediaType .MULTIPART_FORMDATA )) {
265- return new HttpPostMultipartRequestDecoder (factory , request , StandardCharsets .UTF_8 );
271+ return new HttpPostMultipartRequestDecoder (
272+ factory , request , StandardCharsets .UTF_8 , maxFormFields , -1 );
266273 } else if (lowerContentType .startsWith (MediaType .FORM_URLENCODED )) {
267- return new HttpPostStandardRequestDecoder (factory , request , StandardCharsets .UTF_8 );
274+ return new HttpPostStandardRequestDecoder (
275+ factory , request , StandardCharsets .UTF_8 , maxFormFields , -1 );
268276 }
269277 }
270278 return new HttpRawPostRequestDecoder (factory , request );
0 commit comments