What causes jetty badMessage: 413 for HttpChannelOverHttp - java

I have an application with an embedded jetty server, I have noticed for some web/browser GET requests application throws this message
badMessage: 413 for HttpChannelOverHttp from org.eclipse.jetty.http.HttpParser and ultimately 413 responses. I am not sure what is causing this error and how to solve this.
Based on documentation it could be related to the request header size, but header size is almost the same (but not sure about the cookie part), Even if it is related to header size how can I configure the server to accept the request with a bigger payload.
Java version= openjdk version "1.8.0_181"
Jetty Version= 9.2.26.v20180806
P.S.: I'm new to web development with java
Thanks

Related

Tomcat receives HTTP 400 but CURL receives 200

I have a very strange scenario where, in a Linux server, CURL successfully retrieves a response from a web service. When that same request is issued by Tomcat on the same linux server used for the CURL command, for some reason Tomcat receives a 400 status code, which prevents me from doing our business logic.
Flow with CURL:
CURL issues request to Service A using Proxy A
Service A retrieves the data we need and returns it, as well as a 200 Status Code
CURL receives the correct data and 200 status code...
Flow with Tomcat:
Tomcat issues request to Service A using Proxy A
Service A retrieves the data we need and returns it, as well as a 200 Status Code
Tomcat receives a 400 status code and is not able to receive the correct data...
What could be causing this problem? Tomcat and CURL are using the same proxy and are in the same linux server... even the service is able to fetch the data successfully and return it to both. Only in the case of tomcat, the service is throwing this error after trying to write the data in the response:
2021-03-10 21:49:36.908 WARN 90623 --- [https-jsse-nio-8123-exec-10] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotReadableException: I/O error while reading input message; nested exception is org.apache.catalina.connector.ClientAbortException: java.net.SocketTimeoutException]
Tomcat closes the socket because it sees a 400 response code, and doesn't even try reading the bytes from the response when I do con.getInputStream(). I don't really know where that 400 Status code is coming from.
Any help is appreciated. Thanks.
UPDATE 2021/03/11:
One thing I forgot to mention is that, Tomcat is able to perform other requests to that same service. The main difference here is the size of the response. It timesout when trying to read this large response, in comparison to other smaller responses we get.
UPDATE 2021/03/16:
After investigating deeper on what is happening I found out that, whenever I issue the request with Java, for some reason it timesout at exactly 2 minutes. That doesn't happen with CURL, only with Java. Is there anything I may be missing? I have already added these to my code:
JVM Arguments:
-Dsun.net.client.defaultReadTimeout=6000000 -Dsun.net.client.defaultConnectTimeout=6000000
Java code
con.setReadTimeout(Integer.MAX_VALUE);
con.setConnectTimeout(Integer.MAX_VALUE);
con.setDoOutput(true);
con.setDoInput(true);
I'm using an HttpURLConnection object.
http.converter.HttpMessageNotReadableException
The message that your tomcat sends to the service can not be read. Something happens with the message that your tomcat sends to the service. Does it have a json body included? If yes check that model class how it is serialized.

Force tomcat to use only HTTP 1.0 or ignore Except header

Is there a possibility to force tomcat to ignore "Expect" header or to use only HTTP 1.0?
I am sending curl request curl POST -vv 'http://127.0.0.1:8080/test' -d "#requests/test.xml" -H "SOAPAction: abc/test" -H "Content-Type: text/xml; charset=UTF-8" and curl adds by default "Expect" header which causes server waits for another request which never come.
Tech stack: Springboot 2.1.3.RELEASE, Tomcat 9.0.16
I cannot modify clients and to their requests empty header "Expect:".
I don't think there is a way to get Tomcat to respond only with an HTTP 1.0 response. That would be a protocol violation. If server gets an HTTP 1.1 request it must either respond with a HTTP 1.1 compatible response, or signal that it can't with a 505 HTTP Version Not Supported error.
Likewise, I don't think there is a way to get Tomcat to ignore a (well-formed / non-empty) Expect header. That would also be a protocol violation.
(While it is possible in theory for a server to violate the spec, I couldn't find a way to configure Tomcat to do that. Obviously you could download the Tomcat source code and modify it, but then you have the problem of maintaining your "fork".)
So what are the alternatives:
The HTTP spec says that server must ignore an Expect header in an HTTP 1.0 request. So you could add the --http1.0 option to the curl command.
The curl command uses a defaults file - ~/.curlrc - to get default overrides for various things. You could add an empty default for the Expect header into this file; see How to setup default "Expect" header for curl.
However, I think you may be worried unduly:
If you are worried that this will slow up the client (curl), don't. By default it only waits for 1 second for the 100 Continue response. (And I don't think that is what you are talking about ...)
If you are worried that this might tie up server side resources (in Tomcat), I can't see how that could be significant. The Tomcat server will timeout and close a client connection if there is no activity. This should deal with a curl command that sends the initial request but doesn't follow up.

Capturing HTTP traffic using Fiddler from Java applicaiton

I'm having difficulty using Fiddler to diagnose a problem in a Java application to connect to Microsoft Graph's API. Here's my basic environment:
JDK: 1.8.0_131
Apache HttpClient: 4.4
Fiddler: 4.6
The endpoint I'm trying to reach is https://login.microsoftonline.com/common/oauth2/authorize The problem I have is that the traffic is not captured by Fiddler.
I've tried various things as suggested by Googling for this problem, but have not got it to work. In my application, I set the proxy settings as follows:
httpClientBuilder.setProxy(new HttpHost(proxyServer, proxyPort, proxyScheme));
httpClientBuilder.build();
If I use ("127.0.0.1", 8888, "https"): then the error that I see is:
Unrecognized SSL message, plaintext connection?
If I use
("127.0.0.1", 8888, "http"): then the error that I see is: I/O
exception (org.apache.http.conn.UnsupportedSchemeException) caught
when processing request to
{tls}->http://127.0.0.1:8888->https://login.microsoftonline.com:443:
http protocol is not supported
I've tried other things (for example "localhost", "localhost.", and so on as suggested, and setting: -Djsse.enableSNIExtension=false), but so far no luck. Hopefully I am missing something obvious! Thanks for any help.
It turns out that the second configuration for the proxy is the correct one to use (using "http"), but what I had forgotten was that I was setting a ConnectionSocketFactoryRegistry in my HttpClientBuilder. I had not registered a ConnectionSocketFactory for "http" and this caused the second configuration to fail. I added this to the HttpClientBuilder, and now I can see traffic being captured by Fiddler:
connectionSocketFactoryRegistryBuilder.register("http", new PlainConnectionSocketFactory());

Https web service call failure

We have implemented webservice call using JAX-WS RI 2.1.6 in JDK 6 now problem comes when we enable https webservice call stops reaching server and java reports following error,
javax.xml.ws.WebServiceException: java.io.IOException: Async IO
operation failed (3), reason: RC: 55 The specified network resource
or device is no longer available.
Now I have tested this within SoapUI and response from the service is received there.
Looked into various solution where it tells us to provide timeout settings but nothing seems work.
#WebEndpoint(name = "RulesSoap")
public RulesSoap getRulesSoap() {
((BindingProvider)super.getPort(new QName("urn:decision:Rules", "RulesSoap"), RulesSoap.class)).getRequestContext().put("com.sun.xml.internal.ws.connect.timeout", 1000);
((BindingProvider)super.getPort(new QName("urn:decision:Rules", "RulesSoap"), RulesSoap.class)).getRequestContext().put("com.sun.xml.internal.ws.request.timeout", 1000);
return super.getPort(new QName("urn:decision:Rules", "RulesSoap"), RulesSoap.class);
}
And just for information JAX-WS implementation is following few simple lines,
of course we submit all necessary data into respective stubs and all but I am not submitting here because our http calls are getting through,
Rules rules = new Rules(new URL(url), new QName("urn:decision:Rules", "Rules"));
RulesSoap rulesSoap = rules.getRulesSoap();
CorticonResponse response = rulesSoap.processRequest(request);
Note : Our application server WebSphere Application Server and Version 7.0.0.19
Thanks in Advance.
After lots of efforts we resolved this. I will provide steps if anything related to this happens how to find root cause,
Step 1 :
First of all we enabled soap tracing in WebSphere Application Server by following setting,
Admin Console > Servers > Server Types > WebSphere Application Servers >
{your server} > Troubleshooting > Change Log Detail Levels > Runtime
In run time please put this , *=info: com.ibm.ws.websvcs.*=all: org.apache.axis2.jaxws.*=all
This step will create trace.log file in your logs folder.
Now any web service request which goes out of your server will add logs to this file and necessary props like endpoint, request, response etc.
Step 2 :
Reading this trace.log file we found following endpoint,
PropertyValid 1 org.apache.axis2.jaxws.client.PropertyValidator validate validate property=(javax.xml.ws.service.endpoint.address) with value=(http://uxm.solutions.lnet.com:9445/axis/dswsdl/Rules/1/0)
HTTPConnectio 3 resetConnection : http://uxm.solutions.lnet.com:9445/axis/dswsdl/Rules/1/0 Persistent : true
Now if you notice here that our soap has endpoint address javax.xml.ws.service.endpoint.address where protocol is still using http which causes to fail ssl handshake.
Step 3 :
Solution for this is to override endpoint inside your soap stubs which can be implemented by adding following line,
RulesSoap rulesSoap = rules.getRulesSoap();
((BindingProvider)rulesSoap).getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, "https://uxm.solutions.lnet.com:9445/axis/dswsdl/Rules/1/0");
Conclusion :
So here is what i think even we pass https url while we are creating objects but still does not take this https url on runtime, to me this looks like stubs creation issue with JAX-WS.
Thanks.
What protocol /ciphers are you using? You have mentioned there is connection to webservice on WAS7 with JDK6 and Java 6 does not support TLS1.2 (and TLS1.1 only from certain fixpack).
See this:
How to use TLS 1.2 in Java 6

Tomcat 6.0.36 not reporting why it responded with 400

I have a tomcat server and java client with java.net.HttpUrlConnection sending messages. Usually all works fine, but there some requests the client sends out which are responded with a 400 http error.
The problem is that nothing is shown on tomcat logs. I even tried to put .level=fine and other log level changes, and still no exception or error was shown.
I'm suspecting bad encoding in request or something like that, but tomcat doesn't give me any clues.
By the way, the URL is OK. I also see the request reaches the server but not to my servlet.
It appears tomcat gets the message, declares it bad and doesn't log what's wrong.
Can anybody think of a way to see the 400 reason?
Thank you
I finally figured out -
I saw that the size of the total headers + size of data written to OutputStream - was exceptionally high - and so I defined in the Tomcat HTTP connector:
Connector port="8080" protocol="HTTP 1/1" maxPostSize="10485760" maxHttpHeaderSize="10485760"/
It is a shame Tomcat doesn't just tell me this, and I had to guess my - I will report this as a bug.
Thank you
Indeed, this was also the solution to the "http 400 bad request" error on Internet Explorer 11.
Adding
maxHttpHeaderSize="10485760" maxPostSize="10485760"
to the Connector-node of Tomcat's server.xml.
Seems my ajax-request (extjs) on IE11 are using a bigger request header then the default (8192 = 8 KB) max http header size on Tomcat 6?
With IE10 and Chrome I didn't experience this problem.
This is a very nice issue to be discussed about. I also faced the same issue in my organization's work. I was clueless about it as there were no good logging about it in catalina.out or in our application logs. Http calls made from client apps to the API that was running in Tomcat_8 were getting rejected by the server with 400 bad request. Only Tomcat locahost_access logs records it by printing the 400 http status fro the request. After I increased the http header size the issue got resolved.

Categories