Sending Soap with attachment with Mule ESB - httpclient

I am using Mule ESB version 1.3 and as soap engine it has AXIS1.4 embedded.Mule uses the code below to send stream as ws attachment. I checked they are still using it in newer versions.
File temp = File.createTempFile("soap", ".tmp");
temp.deleteOnExit(); // TODO cleanup files earlier (IOUtils
// has a file tracker)
FileOutputStream fos = new FileOutputStream(temp);
msgContext.getRequestMessage().writeTo(fos);
fos.close();
contentLength = (int)temp.length();
payload = new FileInputStream(temp);
Here the content of soap message with attachment is saved on a file and handle for this file is given to the rest of system. I did not get the logic behind this. Why not just use
javax.activation.DataHandler
inputstream and instead first saving and then reading message from file. As far as I understand Axis1.4 itself not working that way. Am I missing something here ?
After some modifications to make mule send file I came accross the below difference between axis and mule client generated messages. Except this line generated messages are same.
Mule generate this header:
Content-Type: multipart/related;type="application/xop+xml"
Axis generate this header which is correct:
Content-Type: multipart/related;type="application/xop+xml"; start="<2F4952A019F62AB6704A0C06DB5E8AA1>"; start-info="text/xml; charset=utf-8"; .boundary="----=_Part_0_1836994030.1387284330292"
What is causing this difference ?

Related

Explicitly setting `Content-Length` header in `java.net.http.HttpRequest`

I want to upload a file from InputStream over HTTP, and for this, I am using the new HttpClient provided as part of JDK11. When I try to set the Content-Length while creating a post request I get an IllegalArgumentException saying restricted header name: "Content-Length" and if I try to upload a file from InputStream without the Content-Length header I get an internal server error from the server where I want to upload the file. Is there any option to set the Content-Length in the request in Java 11?
CodeI am using for creating HttpRequest:
var postRequest = HttpRequest.newBuilder()
.POST(HttpRequest.BodyPublishers.ofInputStream(() -> inputStream))
.uri(new URI(url))
.header(HttpHeaders.CONTENT_LENGTH, Long.toString(inputStreamSupplier.getFileSize()))
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_OCTET_STREAM_VALUE)
.build();
Note: It won't be possible to update to Java 12 to allow the restricted headers.
I could also use another library, just wanted to know if there is an option to use the classes from JDK before switching to RestTemplate from Spring. (yes, it's deprecated, As the alternative uses spring boot can't use it at the moment)
Simply use fromPublisher:
var bodyPublisher = BodyPublishers
.fromPublisher(BodyPublishers.ofInputStream(()-> inputStream)), length);
Note that you must ensure that the InputStream delivers exactly length bytes.

How to include file bytes into the POST request body in Jmeter? (What encoding to use)

I have to perform POST requests from Jmeter. I use default HTTPRequest sampler, where I specify the JSON structure that is understandable by the testing app. One part of this JSON has to contain binary data from a pdf file.
For reading the file I use BeanShellSampler in the setUp thread group:
File file = new File(bsh.args[0]);
try {
FileInputStream fis = new FileInputStream(file);
byte[] array = new byte[(int)file.length()];
log.info("String is read.");
fis.read(array);
vars.put("fileEntity", new String(array, "cp1252"));
} catch (e) {
e.printStackTrace();
log.error(e.getMessage());
}
The problem is that when I look at the request with Fiddler, I see that difference, how the binary object is represented there in comparison with Postman's requests:
Postman
Jmeter
I think that there is something wrong with the encoding when I create a String object in the BeanShellSampler. What encoding is correct?
I tried to use RawDataSource plugin but it doesn't help for two reasons:
It fails to read my file, saying "Error reading next chunk"
It uses the same approach that I do to read the file, but uses UTF8 encoding. I tried this encoding also, but without any success.
My expectation is that your fis.read(array); function relies on default value of the file.encoding system property which may or may not be cp1252.
I would recommend introducing an InputStreamReader and explicitly specify the encoding there like:
InputStreamReader isr = new InputStreamReader(fis,"cp1252");
Also be aware that starting from JMeter 3.1 it's recommended to use JSR223 Test Elements and Groovy language for scripting mainly because Groovy performs much better comparing to Beanshell.

How to read Gzipped payload in a POST request in SpringBoot

I need to read gzipped json payload in a POST request in my SPringBoot app which accepts json data. How to do that in order to keep the application generic as there may be other clients in future sending data in plain json or other compression formats? I suppose this should be handled by the server itself so is there any way to instruct the embedded Tomcat to unzip the payload?
My SpringBoot application runs on embedded Tomcat 9.0.17.
The controller accepts JSON payload in a POST request.
#RequestMapping(value = "/update/v1", method = RequestMethod.POST, produces = "application/json", consumes = "application/json")
public ResponseEntity<String> receiveUpdates(#RequestBody String update) {
We recently changed our content provider and the new one is sending payload in "gzip" format (with header content-encoding=gzip) and without any content-type header. As a result it gives the following error
'error': 'Unsupported Media Type', 'message': "Content type '' not supported"
If I change my consume type to MediaType.ALL_VALUE, my controller starts receiving the request but the payload itself is gzipped. I can handle it in my service layer but that would make it specific to gzipped data.
This problem could be solved by introducing a Filter to handle gzipped payload as mentioned here and here.
But I believe there should be a way to instruct the Tomcat to handle this and serve unzipped data.

Nancy - return pdf stream via ajax

Is there any sample out there how to return a pdf stream (e.g. generated by Crystal Report) from a nancy module via an ajax request?
I'm not sure what you mean by "ajax request" and why it matters, but recently we had to solve similar problem - i.e. returning pdf, generated from other tool. We ended up using as a template a binary processor, utilizing the content negotiation.
You can modify the binary processor to work with application/pdf MIME type and "pdf" file extensions, so it returns the proper response whenever the request has an Accept header of "application/pdf" or when the request is like http://example.com/reports/report.pdf.
Using this, and assuming you have IReportEngine with Stream GetReportByName(string name), your module will look like (pseudo code):
Get["reports/{reportName}"] = _ => _engine.GetReportByName(_.reportName);

SOAP/WSDL, AXIS2 and digital signing a SOAP message

We need to send a SOAP message to a webservice. This is somewhat new territory, so we are a bit confused... even when searching and reading about the subject. Here is what we know / did:
1) We must authenticate through the use of a Digital Certificate in Base64 (obtained issuing a CSR – Certificate Signing Request).
2) The SOAP message must contain a Security Header (wss:Security xmlns:wss="http://schemas.xmlsoap.org/ws/2002/12/secext") and a Body.
3) The WSDL file does not contain a HEADER section, but we have the header "Field structure"
4) We decided to use Axis2/xmlbeans, and created the JAVA classes with https://axis.apache.org/axis2/java/core/tools/eclipse/wsdl2java-plugin.html
5) We can easily create the STUB and send the WSDL body element using the provided sync/async register stub methods (i assume Axis2 will generate the correct SOAP message)
Questions
1) How can we add the WS-Security(?) HEADER to the SOAP message. Do we have to manipulate the AXIS2 generated code?
2) How can we authenticate using the Digital Certificate?
Thanks
1) How can we add the WS-Security(?) HEADER to the SOAP message. Do we have to manipulate the AXIS2 generated code?
ServiceClient client = stub._getServiceClient();
SOAP11Factory factory = new SOAP11Factory();
OMNamespace SecurityElementNamespace = factory.createOMNamespace("http://schemas.xmlsoap.org/ws/2002/12/secext", "wss");
OMElement usernameTokenEl = factory.createOMElement("UsernameToken", SecurityElementNamespace);
OMElement usernameEl = factory.createOMElement("Username", SecurityElementNamespace);
OMElement passwordEl = factory.createOMElement("Password", SecurityElementNamespace);
usernameEl.setText(username);
passwordEl.setText(password);
usernameTokenEl.addChild(usernameEl);
usernameTokenEl.addChild(passwordEl);
SOAPHeaderBlockImpl block = new SOAP11HeaderBlockImpl("Security", SecurityElementNamespace, factory);
block.addChild(usernameTokenEl);
client.addHeader(block);