SOAP web service works only with PHP? - java

I am using a SOAP webservice that is supposed to work with Java, PHP and a lot of technologies. However, it is only working correctly with PHP.
I used the SOAPClient class in PHP to implement the client. When I printed the request and response headers, I got something like this:
REQUEST HEADERS:
POST /ws/something.php HTTP/1.1
Host: xxx.com
Connection: Keep-Alive
User-Agent: PHP-SOAP/5.5.30
Content-Type: text/xml; charset=utf-8
SOAPAction: "http://example.com/ws/something.php/someMethod"
Content-Length: 417
Authorization: Basic <username:password here>
RESPONSE HEADERS:
HTTP/1.1 200 OK
Date: Thu, 03 Mar 2016 18:03:48 GMT
Server: Apache
Strict-Transport-Security: max-age=63072000; includeSubdomains; preload
Content-Length: 512049
Vary: Accept-Encoding,User-Agent
Content-Type: text/xml; charset=utf-8
Set-Cookie: BALANCEID=balancer.<someIP>; path=/; HTTPOnly; Secure
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Then, I used SAAJ in Java to write the exact same request like how PHP does it. I edited even the user-agent to make it exact, but I have no luck. The response is always the SOAP service's wsdl. For some reason, the web service does not execute anything if I use Java.
These are the request headers for Java:
Authorization Basic <username:password here>
SOAPAction http://example.com/ws/something.php/someMethod
POST /ws/something.php HTTP/1.1
Host xxx.com
Connection Keep-Alive
User-Agent PHP-SOAP/5.5.30
Content-Type text/xml; charset=utf-8
Content-Length 417
This is the response header:
Date Thu
Date 03 Mar 2016 18:24:35 GMT
Server Apache
Strict-Transport-Security max-age=63072000; includeSubdomains; preload
Accept-Ranges none
Vary Accept-Encoding
Vary User-Agent
Content-Type text/xml; charset=UTF-8
Set-Cookie BALANCEID=balancer.<some IP>; path=/; HTTPOnly; Secure
Keep-Alive timeout=2
Keep-Alive max=100
Connection Keep-Alive
Transfer-Encoding chunked
Content-Length 8444
SOAPAction ""
Note how the response header is completely different.
I have no idea why the web service won't execute the exact same request from Java. It just returns the wsdl. Does that mean something is wrong with my request or does the web service magically work only with PHP soapClient?

Related

Content-Type Preflight Handling with AWS API Gateway versus Own Rest Server

What is special with API Gateway, it is not required to include Access-Control-Allow-Headers in the response header.
This is AWS API Gateway Response Header:
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 152
Connection: keep-alive
Date: Tue, 11 Oct 2016 02:39:40 GMT
Access-Control-Allow-Origin: *
x-amzn-RequestId: f3838f6a-8f5b-11e6-b13a-XXXXXXX
X-Cache: Miss from cloudfront
Via: 1.1 XXXXXXXXXXX.cloudfront.net (CloudFront)
X-Amz-Cf-Id: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX==
This is My Own Rest Server Response Header:
HTTP/1.1 200
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Content-Type
Content-Type: application/json
Content-Length: 335
Date: Tue, 11 Oct 2016 02:34:31 GMT
The Problem with My Own Rest Server is that I need include Access-Control-Allow-Headers in the response otherwise I will encounter Request header field content-type is not allowed by Access-Control-Allow-Headers in preflight response.
With AWS API Gateway, I am not encounter that error even the Access-Control-Allow-Headers is not in response header.
According to the documentation here, Content-Type should be allowed by default.
"Apart from the headers set automatically by the user agent (e.g. Connection, User-Agent, etc.), the only headers which are allowed to be manually set are:
Accept
Accept-Language
Content-Language
Content-Type
The only allowed values for the Content-Type header are:
application/x-www-form-urlencoded
multipart/form-data
text/plain"
Hope that helps, Ritisha.

Http keep-alive protocol "Connection: close" from client but no "connection" header from server

I've a problem with broken connections and I believe this is due to an incorrect behavior respect to http keepalive but I can't understand if the 'culpit' is on the client or on the server side.
I'm dealing with a scenario where the client sends and HTTP 1.1 request with:
Connection: close
and the server does NOT reply with a Connection header.
The behavior is as follows:
The client sends the request
The server sends it response
The server does NOT close the connection
The client does NOT close the connection (.1)
The client sends another request using the same connection
The server does not do anything and after 30" closes the connection
The components are as follows:
Client: Java HttpConnection (within Dell Boomi iPaaS)
Server: SAP ERP OData Webservice
According to this article: "Should a server adhere to the HTTP Connection: close header sent from a client?" the problem seems to be on the client side. However the Java HttpURLCoonnection implementation should be pretty robust (tested x64 server VM on Linux v 1.7.0_55-b13 and x64 server on Windows 7 v 1.7.0_75-b13).
Here are the complete set of headers from the 1st request from client:
GET /sap/opu/odata/SAP/ZZSALESORDER_SRV/$metadata HTTP/1.1
User-Agent: Boomi Http Transport
Authorization: Basic YmPRIVATESECRETPLEASExNg==
X-CSRF-Token: Fetch
Connection: close
Cache-Control: no-cache
Pragma: no-cache
Host: some.server.behind.firewall.local:8000
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Cookie: sap-usercontext=sap-client=100; SAP_SESSIONID_DEV_100=Cm7LsDSECRETSECRETSECTERFaIMak%3d
And these are the ones from the response from the server:
HTTP/1.1 200 OK
content-type: application/xml
content-length: 79750
x-csrf-token: oolTHISAGAINISASECRET3PA==
last-modified: Fri, 25 Mar 2016 17:55:35 GMT
dataserviceversion: 2.0
After the server has replied the client sends a second request using the same connection:
PUT /sap/opu/odata/SAP/ZZSALESORDER_SRV/SalesOrderItems(NumDocSap='1200001534',PosId='000020') HTTP/1.1
User-Agent: Boomi Http Transport
Content-Type: application/atom+xml
X-CSRF-Token: oolZMYSECRETPA==
Connection: close
Authorization: Basic YmPRIVATESECRETPLEASExNg==
Cache-Control: no-cache
Pragma: no-cache
Host: some.server.behind.firewall.local:8000
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Content-Length: 406
Cookie: sap-usercontext=sap-client=100; SAP_SESSIONID_DEV_100=Cm7PRETTYPRIVATESECRETak%3d
and the server does not reply and closed the connection abruptly after 30".
The problem can be completely resolved setting the JVM flag
http.keepAlive=false
on the java client side (Boomi) but this seems more of a workaround then a solution.
Can someone please explain:
is there an HTTP protocol violation on client or server side?
can this be fixed by sending different headers?

How can I talk to nginx using plain HTTP/1.1 with pure Java sockets?

I connect a nginx http service by socket,i use java Language:
url:api.weibo.com/2/users/show.json
GET /2/users/show.json HTTP/1.1
Host: api.weibo.com
Connection: keep-alive
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.99 Safari/537.36
Accept-Language: zh-CN,zh;q=0.8,en;q=0.6
Cookie: PHPSESSID=uc67dtcb5r3orchgv0dgdd0f57; think_template=default
but it return:
HTTP/1.1 400 Bad Request
Server: Weibo
Date: Sat, 24 Jan 2015 10:07:33 GMT
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
Api-Server-IP: 10.75.0.174
Vary: Accept-Encoding
60
{"error":"source paramter(appkey) is missing","error_code":10006,"request":"/2/users/show.json"}
0
i don't know what is the '60' and '0'
if i use HTTP/1.0 instand of HTTP/1.1,it return:
HTTP/1.1 400 Bad Request
Server: Weibo
Date: Sat, 24 Jan 2015 10:22:09 GMT
Content-Type: application/json;charset=UTF-8
Connection: close
Api-Server-IP: 10.75.5.92
Vary: Accept-Encoding
{"error":"source paramter(appkey) is missing","error_code":10006,"request":"/2/users/show.json"}
if i use socket connect iis or apache,all ok to use HTTP/1.1
Anybody can tell me why,and how to Solve?
The webservice returns the content in chunks, by first sending the length of the next chunk. It is using Chunked Transfer Encoding.
You are saying you can speak HTTP/1.1 with GET /2/users/show.json HTTP/1.1 and
All HTTP/1.1 applications MUST be able to receive and decode the
"chunked" transfer-coding....
You could use something like the Apache HttpClient or some other Java HTTP client library to avoid implementing HTTP on your own.

Soap request over tcpmon changes behaviour

I am consuming a web service. I wrote a client with axis 1.4 using eclipse. I have access to webservices over ssl vpn. My axis client code works fine. However, code must be run on android device. I can not use axis code on android, because java rmi is not supported on android. I am trying to consume service with making httppost with apache httpclient library. In order to see axis request values, I used tcpmon. It helped me to write httppost code easily. The problem is that when I run code directly without using tcpmon it gives me the error below:
Exception in thread "main" java.net.SocketException: Invalid argument: setsockopt
at java.net.DualStackPlainSocketImpl.setIntOption(Native Method)
at java.net.DualStackPlainSocketImpl.socketSetOption(Unknown Source)
at java.net.AbstractPlainSocketImpl.setOption(Unknown Source)
at java.net.PlainSocketImpl.setOption(Unknown Source)
at java.net.Socket.setTcpNoDelay(Unknown Source)
at org.apache.http.impl.conn.DefaultClientConnectionOperator.prepareSocket(DefaultClientConnectionOperator.java:254)
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:185)
at org.apache.http.impl.conn.ManagedClientConnectionImpl.open(ManagedClientConnectionImpl.java:294)
at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:643)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:479)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:906)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:805)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:784)
at TTIncidentClient.main(TTIncidentClient.java:56)
If I send request over tcpmon it works. I get the response. I give you tcpmon output below:
REQUEST:
POST http://localhost:3333/SM/7/ws HTTP/1.1
SOAPAction: RetrieveList
Accept: application/soap+xml, application/dime, multipart/related, text/*
Pragma: no-cache
Cache-Control: no-cache
Authorization: Basic bW9iaXNlbTpPeXAlPzIwMTM=
Content-Length: 456
Content-Type: text/xml; charset=ISO-8859-1
Host: 10.6.105.132:3333
Proxy-Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.2.5 (java 1.5)
<?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><soapenv:Body><RetrieveIncidentListRequest xmlns="http://schemas.hp.com/SM/7"><keys query="flag=true and category="incident" and assignee.name="xx.yy""/></RetrieveIncidentListRequest></soapenv:Body></soapenv:Envelope>
RESPONSE:
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=AF8B0B75ED768852E44D7CB49DB5DD88; Path=/SM
Keep-Alive: timeout=1200000, max=1000
Connection: Keep-Alive
Content-Type: text/xml;charset=utf-8
Content-Length: 2009
Date: Sun, 11 Aug 2013 22:12:17 GMT
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Body><RetrieveIncidentListResponse message="Success" returnCode="0" schemaRevisionDate="2012-11-12" schemaRevisionLevel="0" status="SUCCESS" xmlns="http://schemas.hp.com/SM/7" xmlns:cmn="http://schemas.hp.com/SM/7/Common" xmlns:xmime="http://www.w3.org/2005/05/xmlmime" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://schemas.hp.com/SM/7 http://testsc:3333/SM/7/Incident.xsd">......</SOAP-ENV:Body></SOAP-ENV:Envelope>
Normally I expect tcpmon behaviour must be same with my local but tcpmon changes the result. What can be the reason ?
Very interestingly, instead of using apache httpclient or java urlconnection libraries , I wrote socket programming code for soap as in this example it worked. :)

Calling a JAX-WS webservice from inside Matlab

I have a Vanguard webservice which I can call (using basic authentication) using a custom java class. The java wsimport tool was used to generate the java proxy stubs and this all works perfectly.
The java code (All classes below are generated by wsimport given a url + authentication info):
Authenticator.setDefault(new SimpleAuth(username,pass));
MyWSObject obj = new MyWSObject(url); -> triggers the exception
ServicePortType port = obj.getServicePort();
OutputType result = port.MyWSMethod(params);
OutputData data = result.getOutputData();
When I run the exact same java function (containing the above code) from matlab the webservice call fails with an obscure error:
??? Java exception occurred:
com.sun.xml.internal.ws.streaming.XMLStreamReaderException: XML reader error: com.ctc.wstx.exc.WstxUnexpectedCharException:
Unexpected character '"' (code 34) in DOCTYPE declaration; expected a space between public and system identifiers
at [row,col,system-id]:
[1,63,"<my webservice url>"]
at com.sun.xml.internal.ws.streaming.XMLStreamReaderUtil.wrapException(XMLStreamReaderUtil.java:256)
at com.sun.xml.internal.ws.streaming.XMLStreamReaderUtil.next(XMLStreamReaderUtil.java:84)
at com.sun.xml.internal.ws.streaming.XMLStreamReaderUtil.nextContent(XMLStreamReaderUtil.java:99)
at com.sun.xml.internal.ws.streaming.XMLStreamReaderUtil.nextElementContent(XMLStreamReaderUtil.java:89)
at com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser.hasWSDLDefinitions(RuntimeWSDLParser.java:209)
at com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser.parse(RuntimeWSDLParser.java:119)
at com.sun.xml.internal.ws.client.WSServiceDelegate.parseWSDL(WSServiceDelegate.java:254)
at com.sun.xml.internal.ws.client.WSServiceDelegate.<init>(WSServiceDelegate.java:217)
at com.sun.xml.internal.ws.client.WSServiceDelegate.<init>(WSServiceDelegate.java:165)
at com.sun.xml.internal.ws.spi.ProviderImpl.createServiceDelegate(ProviderImpl.java:93)
at javax.xml.ws.Service.<init>(Service.java:56)
at edu.soton.decode.activities.vanguardws.MyWSObject.<init>(MyWSObject.java:42)
at edu.soton.decode.activities.VanguardActivity.execute(VanguardActivity.java:80)
If I use wireshark to monitor the requests/reponses in both cases I see:
== Java function called directly ==
All the calls/reponses below happen automatically by the JAX-WS code generated by wsimport. My code just calls the webservice method on the generated service proxy, nothing fancy.
GET /bin/ws.dsb?wsdl/mywebservice HTTP/1.1
User-Agent: Java/1.6.0_22
Host: myhost
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive
...
HTTP/1.1 401 Authorization Required
Server: Vanguard Server/5.1.10
Connection: close
Content-Length: 608
Date: Mon, 01 Nov 2010 15:04:17 GMT
Last-Modified: Mon, 01 Nov 2010 15:04:17 GMT
Expires: Mon, 01 Nov 2010 15:04:17 GMT
Cache-Control: no-cache
WWW-Authenticate: Basic realm="Local Library"
Auto-Studio-Login: 0
Content-Type: text/html
...
GET /bin/ws.dsb?wsdl/mywebservice HTTP/1.1
User-Agent: Java/1.6.0_22
Host: myhost
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive
Authorization: Basic Z29yaXNzZW46ZGlyaw==
...
HTTP/1.1 200 OK
Server: Vanguard Server/5.1.10
Connection: close
Content-Length: 5408
Date: Mon, 01 Nov 2010 15:04:17 GMT
Last-Modified: Mon, 01 Nov 2010 15:04:17 GMT
Expires: Mon, 01 Nov 2010 15:04:17 GMT
Cache-Control: no-cache
Set-Cookie: KillIDws=lpvovmb3oa9; path=/
Content-Type:text/xml
...
POST /bin/ws.dsb?soap/mywebservice HTTP/1.1
Content-type: text/xml;charset="utf-8"
Soapaction: ""
Accept: text/xml, multipart/related, text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
User-Agent: JAX-WS RI 2.1.6 in JDK 6
Host: myhost
Connection: keep-alive
Authorization: Basic Z29yaXNzZW46ZGlyaw==
Content-Length: 214
...
HTTP/1.1 200 OK
Server: Vanguard Server/5.1.10
Connection: close
Content-Length: 851
Date: Mon, 01 Nov 2010 15:04:18 GMT
Last-Modified: Mon, 01 Nov 2010 15:04:18 GMT
Expires: Mon, 01 Nov 2010 15:04:18 GMT
Cache-Control: no-cache
Set-Cookie: KillIDws=lpvovmb3oi2; path=/
Content-Type:text/xml; charset=utf-8
...
-> the last response is where the results are returned
== Exactly the same Java function called from inside Matlab ==
GET /bin/ws.dsb?wsdl/mywebservice HTTP/1.1
Accept: */*
Accept-Encoding: gzip
Accept-Language: en
User-Agent: Mozilla/5.0 (Java 1.6.0_22; Windows XP 5.2 amd64; en_GB) ICEbrowser/v6_0_2
Host: myhost
Connection: Keep-Alive
...
HTTP/1.1 401 Authorization Required
Server: Vanguard Server/5.1.10
Connection: close
Content-Length: 608
Date: Mon, 01 Nov 2010 15:02:42 GMT
Last-Modified: Mon, 01 Nov 2010 15:02:42 GMT
Expires: Mon, 01 Nov 2010 15:02:42 GMT
Cache-Control: no-cache
WWW-Authenticate: Basic realm="Local Library"
Auto-Studio-Login: 0
Content-Type: text/html
...
-> everything stops here with the exception shown above. So when running inside Matlab, it seems Matlab is doing something to the JVM environment that stops the generated proxy from making a second, authenticated call. It simply bails out after the 401 instead of authenticating like in the pure java case.
I have set MATLAB_JAVA environment variable so that the same JVM (sun 1.6) is used in both cases. I have also noticed that Matlab does not respect the http.agent property when sending requests.
It turns out that the problem only seems to occur on 64bit versions of Matlab on non-linux platforms. It works fine if I install a 32bit version of Matlab. I am going to mark this question as answered since this seems to be a problem with Matlab and Mathworks are investigating the issue (thread id: 1-DUMQQZ]).
If proxy settings are responsible for the issue, the following static methods can be used for configuration.
% configure
java.lang.System.getProperties().put('http.proxyHost', 'your.proxy');
java.lang.System.getProperties().put('http.proxyPort', 'port number');
java.lang.System.getProperties().put('http.proxyUser', 'name');
java.lang.System.getProperties().put('http.proxyPassword', 'password');
java.lang.System.getProperties().put('http.proxySet', 'true');
% verify
java.lang.System.getProperty('http.proxyHost')
java.lang.System.getProperty('http.proxyPort')
java.lang.System.getProperty('http.proxyUser')
java.lang.System.getProperty('http.proxyPassword')
% test
urlread('http://www.yahoo.com/')
ICEbrowser, which MATLAB still uses on some platforms for HTML rendering, inserts some of its own classes into global VM settings. This may work for you if you never open the Help Browser in the current session.

Categories

Resources