user2016012
user2016012

Reputation: 3159

Tomcat: java.lang.IllegalArgumentException: Invalid character found in method name. HTTP method names must be tokens

I am getting below stack trace when I am deploying my application in a multi-server Apache Tomcat 8 environment. I am getting this error frequently, and it seems it is blocking the tomcat thread:

INFO [http-nio-80-exec-4461] org.apache.coyote.http11.AbstractHttp11Processor.process 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 method name. HTTP method names must be tokens
 at org.apache.coyote.http11.AbstractNioInputBuffer.parseRequestLine(AbstractNioInputBuffer.java:233)
 at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1017)
 at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:684)
 at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1524)
 at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1480)
 at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
 at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
 at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
 at java.lang.Thread.run(Unknown Source)

Can any one direct me how to troubleshoot or narrow down such an exeption? I am not getting any reference to any of my application source files. I tried to google around, and in of the links it said, you are trying to access http url through https, which seems unlikely. I am not getting this error, when the application runs on a single Tomcat 8 instance. I get this only in a multi-server environment.

I am also sharing the meta tags I have embedded on each page, if that helps to identify the cause.

<%
    response.setHeader("Cache-Control", "no-cache");
    response.setHeader("Cache-Control", "no-store");
    response.setDateHeader("Expires", 0);
    response.setHeader("Pragma", "no-cache");
%>


<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, minimum-scale=1.0, maximum-scale=1.0">
<meta name="viewport" content="width=device-width, initial-scale=1">

I am also using the following in a few pages, which basically is same as above:

<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="Expires" content="-1" />
<meta http-equiv="Cache-Control" content="private" />
<meta http-equiv="Cache-Control" content="no-store" />
<meta http-equiv="Pragma" content="no-cache" />

Even if anyone helps in giving a direction to my troubleshooting attempt, that will be useful, as currently I have no idea where to look into.

Upvotes: 305

Views: 616036

Answers (17)

Promise Preston
Promise Preston

Reputation: 28800

I had this issue when working on a Java Project in Debian 10 with Tomcat as the application server.

The issue was that the application already had https defined as it's default protocol while I was using http to call the application in the browser. So when I try running the application I get this error in my log file:

INFO [http-nio-80-exec-4461] org.apache.coyote.http11.AbstractHttp11Processor.process 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 method name. HTTP method names must be tokens

I however tried using the https protocol in the browser but it didn't connect throwing the error:

Here's how I solved it:

You need a certificate to setup the https protocol for the application. You can obtain certificates from Let's Encrypt. For me the easiest route was creating a obtaining a self-signed certificate. .

I first had to create a keystore file for the application, more like a self-signed certificate for the https protocol:

sudo keytool -genkey -keyalg RSA -alias tomcat -keystore /usr/share/tomcat.keystore

Note: You need to have Java installed on the server to be able to do this. Java can be installed using sudo apt install default-jdk.

Next, I added a https Tomcat server connector for the application in the Tomcat server configuration file (/opt/tomcat/conf/server.xml):

sudo nano /opt/tomcat/conf/server.xml

Add the following to the configuration of the application. Notice that the keystore file location and password are specified. Also a port for the https protocol is defined, which is different from the port for the http protocol:

<Connector protocol="org.apache.coyote.http11.Http11Protocol"
           port="8443" maxThreads="200" scheme="https"
           secure="true" SSLEnabled="true"
           keystoreFile="/usr/share/tomcat.keystore"
           keystorePass="my-password"
           clientAuth="false" sslProtocol="TLS"
           URIEncoding="UTF-8"
           compression="force"
           compressableMimeType="text/html,text/xml,text/plain,text/javascript,text/css"/>

So the full server configuration for the application looked liked this in the Tomcat server configuration file (/opt/tomcat/conf/server.xml):

<Service name="my-application">
  <Connector protocol="org.apache.coyote.http11.Http11Protocol"
             port="8443" maxThreads="200" scheme="https"
             secure="true" SSLEnabled="true"
             keystoreFile="/usr/share/tomcat.keystore"
             keystorePass="my-password"
             clientAuth="false" sslProtocol="TLS"
             URIEncoding="UTF-8"
             compression="force"
             compressableMimeType="text/html,text/xml,text/plain,text/javascript,text/css"/>

  <Connector port="8009" protocol="HTTP/1.1"
             connectionTimeout="20000"
             redirectPort="8443" />

  <Engine name="my-application" defaultHost="localhost">
     <Realm className="org.apache.catalina.realm.LockOutRealm">
        <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
             resourceName="UserDatabase"/>
    </Realm>

    <Host name="localhost"  appBase="webapps"
          unpackWARs="true" autoDeploy="true">

        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
             prefix="localhost_access_log" suffix=".txt"
             pattern="%h %l %u %t &quot;%r&quot; %s %b" />

    </Host>
  </Engine>
</Service>

This time when I tried accessing the application from the browser using:

https://my-server-ip-address:https-port

In my case it was:

https:35.123.45.6:8443

it worked fine. Although, I had to accept a warning which added a security exception for the website since the certificate used is a self-signed one.

Upvotes: 7

Priyantha
Priyantha

Reputation: 5083

I got the same exception when I locally tested. The problem was a URL schema in my request.

Change https to http in your client URL.

Upvotes: 144

mibollma
mibollma

Reputation: 15108

I received this exception unrelated to any TLS issues.

In my case, the Content-Length header value did not match the body length.

Upvotes: 14

Arman
Arman

Reputation: 242

I solved this problem by replacing https to http

Upvotes: 9

Axel Osorio
Axel Osorio

Reputation: 39

I was having this problem when I call any get/post Method in my api of webservices in spring. The problem is: parameter was not encoded. Use the java.net.URLEncoder to encode any parameter in your request: i.e. For the parameter called "id" I'm encoding the "idParameter" variable that I'll send in the request:

     String paramsForURL = "?id=" + URLEncoder.encode(idParameter, "UTF-8")

Upvotes: 0

Linyun Liu
Linyun Liu

Reputation: 741

I solved this problem by simply turning off my vpn.

Upvotes: 1

Guru
Guru

Reputation: 2857

You can also try turning off the SSL option in settings, in case you are sending it through POSTMAN

Upvotes: 0

rustylepord
rustylepord

Reputation: 5801

In my case I had to clear browser history/cookies to get rid of this error.

Upvotes: 3

Cyber
Cyber

Reputation: 2704

In case someone is using swagger:

Change the Scheme to HTTP or HTTPS, depend on needs, prior to hit the execute.

Postman:

Change the URL Path to http:// or https:// in the url address

Upvotes: 26

Daniel
Daniel

Reputation: 887

I know this is an old thread, but there is a particular case when this may happen:

If you are using AWS api gateway coupled with a VPC link, and if the Network Load Balancer has proxy protocol v2 enabled, a 400 Bad Request will happen as well.

Took me the whole afternoon to figure it out, so if it may help someone I'd be glad :)

Upvotes: 5

Ravi Shankar Kota
Ravi Shankar Kota

Reputation: 705

I got this error resolved by doing 2 things in chrome browser:

  1. Pressed Ctrl + Shift + Delete and cleared all browsing data from beginning.
  2. Go to Chrome's : Settings ->Advanced Settings -> Open proxy settings -> Internet Properties then Go to the Content window and click on the Clear SSL State Button.

This site has this information and other options as well : https://www.thesslstore.com/blog/fix-err-ssl-protocol-error/

Upvotes: 3

Petar Tonev
Petar Tonev

Reputation: 5141

This exception can occur when you try to execute HTTPS request from client on endpoint which isn't HTTPS enabled. Client will encrypt request data when server is expecting raw data.

Upvotes: 506

privatejava
privatejava

Reputation: 723

It happened to me when I had a same port used in ssh tunnel SOCKS to run Proxy in 8080 port and my server and my firefox browser proxy was set to that port and got this issue.

Upvotes: 0

smilyface
smilyface

Reputation: 5513

Answering this old question (for others which may help)

Configuring your httpd conf correctly will make the problem solved. Install any httpd server, if you don't have one.

Listing my config here.

[smilyface@box002 ~]$ cat /etc/httpd/conf/httpd.conf | grep shirts | grep -v "#"


        ProxyPass /shirts-service http://local.box002.com:16743/shirts-service
        ProxyPassReverse /shirts-service http://local.box002.com:16743/shirts-service
        ProxyPass /shirts http://local.box002.com:16443/shirts
        ProxyPassReverse /shirts http://local.box002.com:16443/shirts
        ...
        ...
        ...

edit the file as above and then restart httpd as below

[smilyface@box002 ~]$ sudo service httpd restart


And then request with with https will work without exception.
Also request with http will forward to https ! No worries.

Upvotes: 1

vignesh294
vignesh294

Reputation: 782

This usually happens when you are using a URI scheme that is not supported by the server in which the app is deployed. So, you might either want to check what all schemes your server supports and modify your request URI accordingly, or, you might want to add the support for that scheme in your server. The scope of your application should help you decide on this.

Upvotes: 0

Shivan Sawant
Shivan Sawant

Reputation: 509

You are calling local server with http://localhost:8080/foo/bar. Call it with https://localhost:8080/foo/bar. This solves the problem

Upvotes: 28

Asif Iquebal Ajazi
Asif Iquebal Ajazi

Reputation: 125

I was getting the same exception, whenever a page was getting loaded,

NFO: 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 method name. HTTP method names must be tokens
    at org.apache.coyote.http11.InternalInputBuffer.parseRequestLine(InternalInputBuffer.java:139)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1028)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:637)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:748)

I found that one of my page URL was https instead of http, when I changed the same, error was gone.

Upvotes: 0

Related Questions