Mittwoch, 18. April 2007

Http Error 400 Bad Request: Nightmare V1.1

Last week (sorry for the time delay) I wrote a (java+axis2) client program for a web service provided my apartment, which was constructed by .NET C#. At first the client program was working fine, but after we found that the original wsdl file contains the server name which can't be accessed hinter the firewall and changed it, rather curiously, the client program was not working anymore. What's more curious, the "on-fly-parse " function provided by soapclient.com website functioned well after the change, which couldn't run before the modification of wsdl file. Or more clearly
Before:
wsdl contains server name which can't be accessed outside, SOAP web service runs normal, java client program runs well, SOAPclient.com can't run the web service.
After:
wsdl contails another server name which was "mapped back" to the old server, SOAP web services runs normal. java client program doesn't run (with Http Error 400: Bad Request), SOAPclient.com can reach the web service and parse it correctly.

So what's wrong?

Since the only change in the wsdl file is the server name, I guess it could be that the "new server", which stands before the firewall, can't identify the quest by client program, while the "old server" can. Then why the SOAPclient.com parser can parse it right? The most important key fact of this problem, I believe, is to find out why it's a 400 Error(Bad Request), and if possible, what is the request.

Http 400 Error describes by definition a request from client which can't be recognized and handled by the server. Hence it is reasonable to infer that the new server can't recognize the same client-request which can be handled by the old one. Why then? It may be of great help, when I am able to read directly the request. So I googled again(i have to say I can't truly work without googling...) and find a java-based APACHE program called TCPMon(http://ws.apache.org/commons/tcpmon/), which can used as a stimulating web-service client and, very useful, as a light-weighted port monitor.

With its help I found out that the bad-request contains not only the SOAP-envelop and its body , which is strictly XML data, but also some seemingly "non-sense" characters before and after the body. Days before I have seen a post which states that these characters are caused by Http1.1 head proctocol and its "chunked" transport, the idea came into my mind: would it be the reason that the "new server" identify the request as "bad" cause it has additional characters other than xml body?

After another round of google and diving into Axis2 documentation, i added the following lines to my original program:

/*existing line
PIP_Java_Client.PIPServiceStub stub = new PIP_Java_Client.PIPServiceStub("http://www.dkfz.de/mga/PIP/PIPService.asmx");
*/

//following are new lines
org.apache.axis2.client.Options option = stub._getServiceClient().getOptions();
option.setProperty(org.apache.axis2.transport.http.HTTPConstants.HTTP_PROTOCOL_VERSION, "HTTP/1.0");
option.setProperty(org.apache.axis2.transport.http.HTTPConstants.CHUNKED,Boolean.FALSE);

stub._getServiceClient().setOptions(option);

//End of code

That is, to force the axis transport SOAP message in Http1.0 protocol instead of 1.1, because the former one doesn't support "chunked" transport type. After new compiling the monitored request shown that the additional noises disappeared and the web service can now be called without question from the java client program.

One day and almost one night was spent just for this "small" difference protocol, which is a little annoying. The reason behind is that our "old server" supports Http1.1 while the "new one" supports only Http1.0. Hence when trying to access the "old server", the java client program had no problem; but when trying to call the service from the new one, the server can't identify the chunked information being transported and didn't know what to do except for reminding us of that weird 400 Error. Another side of this story is that SOAPclient.com may use just Http1.0 or the both implicitly, so that its parsing will not lead to any error.

So if you had the similar problem of Http Error 400, it is not a bad idea to use a port monitor to check whether your message is sent correctly. If not so , trying to find the reason out of google or docus.

Thanks Alex to give me one after another chance to learn new staffs while trying to solve the problems, which offers a lot of Spaß. Though he is going to Basel this sommer, i will always think of him , who has led me into the great new world of programming.