22
22
import io .undertow .UndertowMessages ;
23
23
import io .undertow .UndertowOptions ;
24
24
import io .undertow .server .handlers .Cookie ;
25
+ import io .undertow .server .protocol .http .HttpRequestParser ;
26
+ import io .undertow .util .BadRequestException ;
25
27
import io .undertow .util .DateUtils ;
26
28
import io .undertow .util .HeaderMap ;
27
29
import io .undertow .util .HeaderValues ;
@@ -446,7 +448,7 @@ public static void setExchangeRequestPath(final HttpServerExchange exchange, fin
446
448
try {
447
449
final boolean slashDecodingFlag = URLUtils .getSlashDecodingFlag (allowEncodedSlash , exchange .getConnection ().getUndertowOptions ().get (UndertowOptions .DECODE_SLASH ));
448
450
setExchangeRequestPath (exchange , encodedPath , charset , decode , slashDecodingFlag , decodeBuffer , exchange .getConnection ().getUndertowOptions ().get (UndertowOptions .MAX_PARAMETERS , UndertowOptions .DEFAULT_MAX_PARAMETERS ));
449
- } catch (ParameterLimitException e ) {
451
+ } catch (ParameterLimitException | BadRequestException e ) {
450
452
throw new RuntimeException (e );
451
453
}
452
454
}
@@ -459,8 +461,9 @@ public static void setExchangeRequestPath(final HttpServerExchange exchange, fin
459
461
* @param encodedPath The encoded path to decode
460
462
* @param decodeBuffer The decode buffer to use
461
463
* @throws ParameterLimitException
464
+ * @throws BadRequestException
462
465
*/
463
- public static void setExchangeRequestPath (final HttpServerExchange exchange , final String encodedPath , StringBuilder decodeBuffer ) throws ParameterLimitException {
466
+ public static void setExchangeRequestPath (final HttpServerExchange exchange , final String encodedPath , StringBuilder decodeBuffer ) throws ParameterLimitException , BadRequestException {
464
467
final OptionMap options = exchange .getConnection ().getUndertowOptions ();
465
468
boolean slashDecodingFlag = URLUtils .getSlashDecodingFlag (options );
466
469
setExchangeRequestPath (exchange , encodedPath ,
@@ -474,16 +477,44 @@ public static void setExchangeRequestPath(final HttpServerExchange exchange, fin
474
477
/**
475
478
* Sets the request path and query parameters, decoding to the requested charset.
476
479
*
477
- * @param exchange The exchange
478
- * @param encodedPath The encoded path
479
- * @param charset The charset
480
+ * @param exchange the exchange
481
+ * @param encodedPath the encoded path
482
+ * @param decode indicates if the request path should be decoded
483
+ * @param decodeSlashFlag indicates if slash characters contained in the encoded path should be decoded
484
+ * @param decodeBuffer the buffer used for decoding
485
+ * @param maxParameters maximum number of parameters allowed in the path
486
+ * @param charset the charset
487
+ * @throws BadRequestException if there is something wrong with the request, such as non-allowed characters
488
+ */
489
+ public static void setExchangeRequestPath (final HttpServerExchange exchange , final String encodedPath , final String charset , boolean decode , final boolean decodeSlashFlag , StringBuilder decodeBuffer , int maxParameters ) throws ParameterLimitException , BadRequestException {
490
+ setExchangeRequestPath (exchange , encodedPath , charset , decode , decode , decodeSlashFlag , decodeBuffer , maxParameters );
491
+ }
492
+
493
+ /**
494
+ * Sets the request path and query parameters, decoding to the requested charset.
495
+ *
496
+ * @param exchange the exchange
497
+ * @param encodedPath the encoded path
498
+ * @param decode indicates if the request path should be decoded, apart from the query string part of the
499
+ * request (see next parameter)
500
+ * @param decodeQueryString indicates if the query string of the path, when present, should be decoded
501
+ * @param decodeSlashFlag indicates if slash characters contained in the request path should be decoded
502
+ * @param decodeBuffer the buffer used for decoding
503
+ * @param maxParameters maximum number of parameters allowed in the path
504
+ * @param charset the charset
505
+ * @throws BadRequestException if there is something wrong with the request, such as non-allowed characters
480
506
*/
481
- public static void setExchangeRequestPath (final HttpServerExchange exchange , final String encodedPath , final String charset , boolean decode , final boolean decodeSlashFlag , StringBuilder decodeBuffer , int maxParameters ) throws ParameterLimitException {
507
+ public static void setExchangeRequestPath (final HttpServerExchange exchange , final String encodedPath , final String charset , boolean decode , boolean decodeQueryString , final boolean decodeSlashFlag , StringBuilder decodeBuffer , int maxParameters ) throws ParameterLimitException , BadRequestException {
508
+ final OptionMap options = exchange .getConnection ().getUndertowOptions ();
509
+ final boolean allowUnescapedCharactersInUrl = options .get (UndertowOptions .ALLOW_UNESCAPED_CHARACTERS_IN_URL , false );
482
510
boolean requiresDecode = false ;
483
511
final StringBuilder pathBuilder = new StringBuilder ();
484
512
int currentPathPartIndex = 0 ;
485
513
for (int i = 0 ; i < encodedPath .length (); ++i ) {
486
514
char c = encodedPath .charAt (i );
515
+ if (!allowUnescapedCharactersInUrl && !HttpRequestParser .isTargetCharacterAllowed (c )) {
516
+ throw new BadRequestException (UndertowMessages .MESSAGES .invalidCharacterInRequestTarget (c ));
517
+ }
487
518
if (c == '?' ) {
488
519
String part ;
489
520
String encodedPart = encodedPath .substring (currentPathPartIndex , i );
@@ -496,10 +527,22 @@ public static void setExchangeRequestPath(final HttpServerExchange exchange, fin
496
527
part = pathBuilder .toString ();
497
528
exchange .setRequestPath (part );
498
529
exchange .setRelativePath (part );
499
- exchange .setRequestURI (encodedPath .substring (0 , i ));
530
+ if (requiresDecode && allowUnescapedCharactersInUrl ) {
531
+ final String uri = URLUtils .decode (encodedPath .substring (0 , i ), charset , decodeSlashFlag ,false , decodeBuffer );
532
+ exchange .setRequestURI (uri );
533
+ } else {
534
+ exchange .setRequestURI (encodedPath .substring (0 , i ));
535
+ }
536
+
500
537
final String qs = encodedPath .substring (i + 1 );
501
- exchange .setQueryString (qs );
502
- URLUtils .parseQueryString (qs , exchange , charset , decode , maxParameters );
538
+ if (requiresDecode && allowUnescapedCharactersInUrl ) {
539
+ final String decodedQS = URLUtils .decode (qs , charset , decodeSlashFlag ,false , decodeBuffer );
540
+ exchange .setQueryString (decodedQS );
541
+ } else {
542
+ exchange .setQueryString (qs );
543
+ }
544
+
545
+ URLUtils .parseQueryString (qs , exchange , charset , decodeQueryString , maxParameters );
503
546
return ;
504
547
} else if (c == ';' ) {
505
548
String part ;
@@ -510,10 +553,16 @@ public static void setExchangeRequestPath(final HttpServerExchange exchange, fin
510
553
part = encodedPart ;
511
554
}
512
555
pathBuilder .append (part );
513
- exchange .setRequestURI (encodedPath );
556
+ if (requiresDecode && allowUnescapedCharactersInUrl ) {
557
+ final String uri = URLUtils .decode (encodedPath , charset , decodeSlashFlag ,false , decodeBuffer );
558
+ exchange .setRequestURI (uri );
559
+ } else {
560
+ exchange .setRequestURI (encodedPath );
561
+ }
562
+
514
563
currentPathPartIndex = i + 1 + URLUtils .parsePathParams (encodedPath .substring (i + 1 ), exchange , charset , decode , maxParameters );
515
564
i = currentPathPartIndex -1 ;
516
- } else if (c == '% ' || c == '+' ) {
565
+ } else if (decode && ( c == '+ ' || c == '%' || c > 127 ) ) {
517
566
requiresDecode = decode ;
518
567
}
519
568
}
0 commit comments