Soap content length - java

I look at the following is a sample SOAP 1.1 request to SP server, but its does not matter.
POST /_vti_bin/lists.asmx HTTP/1.1
Host: 192.168.0.25
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://schemas.microsoft.com/sharepoint/soap/GetList"
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<GetList xmlns="http://schemas.microsoft.com/sharepoint/soap/">
<listName>string</listName>
</GetList>
</soap:Body>
</soap:Envelope>
The field Content-Length: length need to be replaced with actual values. What its value? Where is I can see it? Or how to calculate it value before request?
UPD1.
I use ksoap lib
headerPropertyObj = new HeaderProperty("Content-Length", "383"); // should be calc before
headerList.add(headerPropertyObj);
transport.setUrl(URL);
request = new SoapObject(NAMESPACE, METHOD_NAME);
request.addProperty("listName", "Tasks");
envelope.setOutputSoapObject(request);
transport.call(SOAP_ACTION, envelope, headerList);

I solved this problem. I wrote myself class
public class MyHttpTransportSE extends Transport
where is I reloaded call method like below
public List call(String soapAction, SoapSerializationEnvelope envelope, List headers)
throws IOException, XmlPullParserException {
if (soapAction == null)
soapAction = "\"\"";
byte[] requestData = createRequestData(envelope);
requestDump = debug ? new String(requestData) : null;
responseDump = null;
connection = getServiceConnection();
connection.setRequestProperty("User-Agent", "kSOAP/2.0");
// connection.setRequestProperty("SOAPAction", soapAction);
// connection.setRequestProperty("Content-Type", "text/xml");
connection.setRequestProperty("Content-Type", "application/soap+xml");
connection.setRequestProperty("Connection", "close");
connection.setRequestProperty("Content-Length", "" + requestData.length);
Its helped for me, I hope this helps for smb.

The Content-Length value is the length (in bytes) of the body, which starts with the first < and ends with the last character of the body, here > or maybe a newline.

Creating the envelope the right way should be enough, without setting headers by yourself.
http://www.helloandroid.com/tutorials/using-ksoap2-android-and-parsing-output-data
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.setOutputSoapObject(request);
httpTransport.debug = true; //try debugging
If your problem relates to sharepoint authentication, then you should add envelope headers properly so the length keeps being calculated by the library itself. Error in authentication when subscribing to a sharepoint webservice using ksoap2-android
this could help: http://davidsit.wordpress.com/2010/03/03/creating-sharepoint-list-items-with-php/

Related

How to set up SOAPMessage boundary?

I am sending a SoapMessage in java. I keep having problem with setting up proper headers, precisely the part of Content-Type which should looks like this:
Content-Type: multipart/related; type="application/xop+xml"; start="<rootpart#soapui.org>"; start-info="text/xml"; boundary="the boundary of my soapmessage"
I don't know how to add the boundary parameter to my headers so it matches the rest of soap message.
My soap message looks like this:
------=_Part_0_5841104.1608651610791
Content-Type: application/xop+xml; charset=UTF-8; type="text/xml"
Content-Transfer-Encoding: 8bit
Content-ID: <rootpart#soapui.org>
MYXML
------=_Part_0_5841104.1608651610791
Content-Type: application/zip; name=Worker.zip
Content-Transfer-Encoding: binary
Content-ID: <MYFILE.zip>
Content-Disposition: attachment; name="MYFILE.zip"; filename="MYFILEr.zip"
MYATTACHMENT
The boundary part in soapbody is generated automatically (------=_Part_0_5841104.1608651610791) and it changes every time I send the message. When I am trying to add headers I do it this way:
MessageFactory messageFactory = MessageFactory.newInstance(SOAPConstants.SOAP_1_1_PROTOCOL);
SOAPMessage soapMessage = messageFactory.createMessage();
SOAPPart soapPart = soapMessage.getSOAPPart();
String authString = "login" + ":" + "password";
String enc = java.util.Base64.getEncoder().encodeToString((authString).getBytes(StandardCharsets.UTF_8));
MimeHeaders hd = soapMessage.getMimeHeaders();
hd.addHeader("POST","where");
hd.addHeader("Accept-Encoding","gzip,deflate");
hd.addHeader("Content-Type","multipart/related; type=\"application/xop+xml\"; start=\"<rootpart#soapui.org>\"; start-info=\"text/xml\"; boundary=\"----=_????????\"");
hd.addHeader("SOAPAction","Action");
hd.addHeader("MIME-Version","1.0");
hd.addHeader("Host","MyHost");
hd.addHeader("Connection","Keep-Alive");
hd.addHeader("User-Agent","Apache-HttpClient/4.1.1 (java 1.5)");
hd.addHeader("Authorization", "Basic " + enc);
How can I add this proper boundary to my headers?
I have struggled with this today and this was the first hit I found.
When you are done creating your SOAPMessage call saveCanges() on it. This will populate the mimeheaders with correct content-type with the bountary in it.
SOAPMessage msg = //create message...
msg.saveChanges();
msg.getMimeHeaders(); //Now contains a content-type with boundary that you can send as request properties.
Hope this helps anyone having this problem.

Send SOAP Request with XML Parameter UTF-8 Java

I am looking for an advice here with my problem. I have a SOAP Request in Java with the following code:
private static SOAPMessage createSOAPRequest(String shellType, String filterCondition,
Map<String, String> AndySiteToSync) throws Exception {
MessageFactory messageFactory = MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL);
SOAPMessage soapMessage = messageFactory.createMessage();
createSoapEnvelope(soapMessage, shellType, filterCondition, AndySiteToSync);
MimeHeaders headers = soapMessage.getMimeHeaders();
soapMessage.saveChanges();
ByteArrayOutputStream stream = new ByteArrayOutputStream();
soapMessage.writeTo(stream);
return soapMessage;
}
I have the following structure on the XML.
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:gen="http://general.service.webservices.skire.com">
<soap:Header/>
<soap:Body>
<gen:updateShell>
<!--Optional:-->
<gen:shortname>xxx</gen:shortname>
<!--Optional:-->
<gen:authcode>xxx</gen:authcode>
<!--Optional:-->
<gen:shellType>xxx</gen:shellType>
<!--Optional:-->
<gen:shellXML>
<![CDATA[
<List_Wrapper>
<_shell>
<paraminside>letterwithutf8_ññ</uuu_longitude>
</_shell>
</List_Wrapper>
]]>
</gen:shellXML>
</gen:updateShell>
</soap:Body>
</soap:Envelope>
It is working very good with characters without ñ or áéíóú, but when I pass a parameter with ñ for example I see on the result ñ. When I print the input xml it is showing the XML fine with the correct characters but when I send the request the result is showing the incorrect character (ñ)
I paste the same input XML in the SOAPUI and the result was good, the ñ characters was introduce fine. The problem is when I send the request using Java.
I assumed it is the encoding of the message. So I added these lines before saveChanges:
MimeHeaders headers = soapMessage.getMimeHeaders();
headers.addHeader("Content-Type", "application/soap+xml;charset=UTF-8");
Alse test with:
headers.setHeader("Content-Type", "application/soap+xml;charset=UTF-8");
These headers are the same as the SOAPUI, with the exception of the "action"
I made sure the headers were ok printing it.
for (int iii = 0; iii < headers.getHeader("Content-Type").length; iii++) {
System.out.println((headers.getHeader("Content-Type"))[iii]);
}
and I got the response application/soap+xml;charset=UTF-8
This way I am creating the connection:
SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
SOAPConnection soapConnection = soapConnectionFactory.createConnection();
SOAPMessage soapResponse = soapConnection.call(createSOAPRequest(....))
SOAPUI
POST https://xxxxxxxxxxxxxxxxx/WebServices HTTP/1.1
Accept-Encoding: gzip,deflate
Content-Type: application/soap+xml;charset=UTF-8;action="urn:xxxxxxx"
Content-Length: 4381
Host: xxxxxxxxxxxxxxxx
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.1.1 (java 1.5)
Thanks.
===========================================
Thanks to Andreas I did some more testing and the encoding problem was before the SOAP Request, I got the information from a URL in json format with the following code:
JSONArray jsonDataFinal = new JSONArray();
JSONArray jsonData = (JSONArray) parser.parse(readUrl(URL));
And then:
List<Map<String,String>> mergeArray = new ArrayList<Map<String,String>>();
Map<String, String> mergeObj = null;
for (Object o : sitesArray)
{
if((siteAndy.get("xxxx")) == null) mergeObj.put("xxxx", "");
else mergeObj.put("xxxx", ((String) siteAndy.get("xxxx")).trim());
}
At what point should I use the utf-8 encoding?
Thanks
I change to this:
reader = new BufferedReader(new InputStreamReader(url.openStream(), StandardCharsets.UTF_8));
And my problem was fix.
Thanks!!

How to call JAX-WS method from URL

I have a local web service and I can call its methods using a JAVA client.
Is it possible to access its methods using a URL ?
I can access the wsdl XML using this URL:
http://localhost:9999/ws/hello?wsdl
And I would like to call a method like such:
http://localhost:9999/ws/hello/getHelloWorldAsString?name=test
But I am receiving errors "Localhost did not send any data".
Is there a way to do this ?
As far as I was aware Jax-ws uses POST to receive calls. You will have to build an XML request to POST to your URL. Something like this:
POST /ws/hello HTTP/1.1
SOAPAction: ""
Accept: text/xml, multipart/related, text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Content-Type: text/xml; charset=utf-8
User-Agent: Java/1.6.0_13
Host: localhost:9999
Connection: keep-alive
Content-Length: 224
<?xml version="1.0" ?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns2:getHelloWorldAsString xmlns:ns2="http://ws.mkyong.com/">
<arg0>test</arg0>
</ns2:getHelloWorldAsString>
</S:Body>
</S:Envelope>
Use java.net.Url and HttpURLConnection or HTTPSURLConnection
look a sample
URL url = new URL("http://yourwebservices.soap.wsdl");
HttpURLConnection connectionWS = (HttpURLConnection) ur.openConnection();
//not forget this
connectionWS.setDoOutput(true);
connectionWS.setDoInput(true);
connectionWS.setRequestMethod("POST");
connectionMinervaWS.setRequestProperty("Content-Type", "text/xml; charset=utf-8");
StringBuilder envelopeSoapRequest = new StringBuilder()
//make the xml request
//now you send to service
OutputStreamWriter osw = new OutputStreamWriter( connectionWS.getOutputStream() );
osw.write( envelopeSoapRequest.toString() );
osw.flush();
//now you can take response
BufferedReader wsReader = null;
StringBuilder envelopeSoapResponse = new StringBuilder();
wsReader = new BufferedReader(new InputStreamReader(
connectionWS.getInputStream(), StandardCharsets.UTF_8 ));
String line = wsReader.readLine();
while (line != null) {
envelopeSoapResponse.append( line );
line = wsReader.readLine();
}

Java httpget seems to work but encountering 401 error

HAve re-written due to the feedback so far...
I'ev got a Java method to try and download a file via httpget within a selenium script, it looks like so...
private String downloader(WebElement element, String attribute, String filePath) throws IOException, NullPointerException, URISyntaxException {
String fileToDownloadLocation = element.getAttribute(attribute);
fileToDownloadLocation = fileToDownloadLocation.replace("\\", "%5C");
URL fileToDownload = new URL(fileToDownloadLocation);
URI FileDL = new URI(fileToDownload.toString());
File downloadedFile = new File(this.localDownloadPath + filePath);
if (downloadedFile.canWrite() == false) downloadedFile.setWritable(true);
CloseableHttpClient httpclient = HttpClients.createDefault();
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(AuthScope.ANY,new NTCredentials("useraccount", "testpassword", "machinename", "mydomain"));
HttpClientContext context = HttpClientContext.create();
context.setCredentialsProvider(credsProvider);
HttpGet httpget = new HttpGet(FileDL);
CloseableHttpResponse response = httpclient.execute(httpget, context);
this.httpStatusOfLastDownloadAttempt = response.getStatusLine().getStatusCode();
FileUtils.copyInputStreamToFile(response.getEntity().getContent(), downloadedFile);
response.getEntity().getContent().close();
String downloadedFileAbsolutePath = downloadedFile.getAbsolutePath();
return downloadedFileAbsolutePath;
}
When I use this on a regular link (i.e. downloading a file from the bbc for example) it all works. The trouble is the system I'm using it on is an internal one that uses windows authentication to determine if access is permitted. When I attempt to use it on this internal system my Http response ends up reading: -
HTTP/1.1 401 Unauthorized [Cache-Control: no-cache, no-store, must-revalidate, Pragma: no-cache, Content-Type: text/html, Expires: -1, Server: Microsoft-IIS/7.5, WWW-Authenticate: Negotiate, WWW-Authenticate: NTLM, X-Powered-By: ASP.NET, X-UA-Compatible: IE=edge, Date: Mon, 17 Mar 2014 14:52:43 GMT, Content-Length: 1293]
If I debug this and obtain the URL it uses I can manually paste this into a browser and it works fine.
I also noticed that during debug the httpRequestParameters doesn't seem to have any values in in at all (shows as null) so I'm guessing that I'm still not setting the account parameters properly somehow.
I'll be honest and say I'm really not 100% on what all this does properly and am trying to paste things together and get it to play ball but I'm wondering if the section where I have ((AbstractHttpClient) client).getCredentialsProvider(). is set up properly or if I'm missing something here...
Any further help much appreciated!
You can set the BASIC authentication credentials in two different ways:
Setting the appropiated HTTP header:
HttpClient hc = new DefaultHttpClient();
HttpGet get = new HttpGet("http://...");
String basic_auth = new String(Base64.encodeBase64((username + ":" + password).getBytes()));
get.addHeader("Authorization", "Basic " + basic_auth);
or using the CredentialsProvider (depends on the Apache HttpComponents version)
HttpClient hc = new DefaultHttpClient();
hc.getCredentialsProvider().setCredentials(AuthScope.ANY, new UsernamePasswordCredentials("username", "password"));
HttpGet get = new HttpGet ("http://...");
hc.execute(get);
I've finally managed to get my code working, the final version is shown above. I'd made a few obvious errors such as my domain was still set to the examples "microsoft.com" and I had actually misspelled my password, other than that it now does exactly what I need it to! :)
#vzamanillo thanks for your help!

Java HttpUrlConnection POST request special characters strange behavior

i'm trying to implements a POST request with HttpURLConnection. This is my code:
private static void call(String body) throws IOException{
HttpURLConnection con = null;
con = (HttpURLConnection)new URL("http://127.0.0.1:8080").openConnection();
con.setRequestProperty("Accept-Charset", "UTF-8");
con.setRequestMethod("POST");
con.setRequestProperty("Content-Type", "application/json; charset=utf-8");
con.setRequestProperty("Accept", "application/json; charset=utf-8");
con.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
wr.writeBytes(body);
wr.flush();
wr.close();
...
}
I post it to localhost just to sniff it with WireShark.
The problem is that when my body is a string containing characters like 'ò' 'à' 'è' 'ç' ... the request i see has le string correct with those characters replaced by dots.
example:
if body is "hèllo!" ---> the request body is "h.llo!"
Just for test i'm executing the above method in java main and i pass the parameter this way:
String pString = "{\"titlè\":\"Hèllo Wòrld!\"}";
String params = new String(pString.getBytes("UTF-8"),"UTF-8");
....
call(body);
and this is what i get in WireShark:
POST / HTTP/1.1
Accept-Charset: UTF-8
Content-Type: application/json; charset=utf-8
Accept: application/json; charset=utf-8
User-Agent: Java/1.6.0_43
Host: 127.0.0.1:8080
Connection: keep-alive
Content-Length: 24
{"titl.":"H.llo W.rld!"}
Any help would be appreciated.
Thank you
The internal string representation in Java is always UTF-16. So in your second example params = new String(pString.getBytes("UTF-8"),"UTF-8"); converts pString to a byte array with UTF-8 content and then back to UTF-16 which is stored in params.
Every encoding has to be done when strings enter or leave the VM. That means in your case you have to set the encoding when you write the body to the stream.
wr.write(body.getBytes("UTF-8"));

Categories

Resources