Tomcat: Invalid character found in the request target

Aquellos que todavía utilicéis versiones antiguas de Tomcat y os hayáis animado a actualizar a versiones superiores a las 7.0.73, 8.0.39 y 8.5.7, puede que tras actualizar y arrancar el servicio os hayáis encontrado el siguiente error en el log:

INFO: Error parsing HTTP request header
Note: further occurrences of HTTP header parsing errors will be logged at DEBUG level.
java.lang.IllegalArgumentException: Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986

La solución rápida pasa por establecer un parámetro de configuración a nivel de server.xml que permita «relajar» la configuración estricta de las dos RFC citadas en el error (RFC 7230 y RFC 3986) en referencia a los caracteres que se pueden pasar en una petición HTTP dirigida a Tomcat, relaxedQueryChars.

Si por ejemplo estamos pasando corchetes en la petición HTTP, podríamos excluirlos del siguiente modo:

<Connector port="80"
    protocol="HTTP/1.1"
    maxThreads="150"
    redirectPort="443"
    compression="on"
    relaxedQueryChars="[,]"
    [...]
/>

También está disponible el atributo relaxedPathChars. Os dejo la información extraída de la documentación oficial de Tomcat:

The HTTP/1.1 specification requires that certain characters are %nn encoded when used in URI paths. Unfortunately, many user agents including all the major browsers are not compliant with this specification and use these characters in unencoded form. To prevent Tomcat rejecting such requests, this attribute may be used to specify the additional characters to allow. If not specified, no additional characters will be allowed. The value may be any combination of the
following characters: » < > [ \ ] ^ ` { | } . Any other characters present in the value will be ignored.

Y la de relaxedQueryChars:

The HTTP/1.1 specification requires that certain characters are %nn encoded when used in URI query strings. Unfortunately, many user agents including all the major browsers are not compliant with this specification and use these characters in unencoded form. To prevent Tomcat rejecting such requests, this attribute may be used to specify the additional characters to allow. If not specified, no additional characters will be allowed. The value may be any combination of the following characters: » < > [ \ ] ^ ` { | } . Any other characters present in the value will be ignored.

Obviamente, para cumplir las RFC y evitar problemas de compatibilidad, lo recomendable no es aplicar este workaround, sino corregir el problema de raíz. Esta es la referencia en el changelog de la versiópn 8.5 de Tomcat:

Add: 62273: Implement configuration options to work-around specification non-compliant user agents (including all the major browsers) that do not correctly %nn encode URI paths and query strings as required by RFC 7230 and RFC 3986. (markt)

¿Qué opciones rápidas hay para arreglarlo sin saltarse la RFC? Por ejemplo utilizar encodeURI para pasar la petición codificada y evitar mostrar en claro los caracteres que está procesando.

Un extracto de los caracteres reservados en la RFC 3986:

      reserved    = gen-delims / sub-delims

      gen-delims  = ":" / "/" / "?" / "#" / "[" / "]" / "@"

      sub-delims  = "!" / "$" / "&" / "'" / "(" / ")"
                  / "*" / "+" / "," / ";" / "="

¡Suerte!